blob: 9908cbb8436d42853f18623a52d372fbabe0b672 [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 Capens58df2f62016-06-07 14:48:56 -040040#ifdef __ANDROID__
Nicolas Capens0bac2852016-05-07 06:09:58 -040041#include <cutils/log.h>
42#endif
43
44namespace es2
45{
46
47static bool validImageSize(GLint level, GLsizei width, GLsizei height)
48{
49 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
50 {
51 return false;
52 }
53
54 return true;
55}
56
Nicolas Capens0bac2852016-05-07 06:09:58 -040057void ActiveTexture(GLenum texture)
58{
59 TRACE("(GLenum texture = 0x%X)", texture);
60
61 es2::Context *context = es2::getContext();
62
63 if(context)
64 {
65 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
66 {
67 return error(GL_INVALID_ENUM);
68 }
69
70 context->setActiveSampler(texture - GL_TEXTURE0);
71 }
72}
73
74void AttachShader(GLuint program, GLuint shader)
75{
76 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
77
78 es2::Context *context = es2::getContext();
79
80 if(context)
81 {
82 es2::Program *programObject = context->getProgram(program);
83 es2::Shader *shaderObject = context->getShader(shader);
84
85 if(!programObject)
86 {
87 if(context->getShader(program))
88 {
89 return error(GL_INVALID_OPERATION);
90 }
91 else
92 {
93 return error(GL_INVALID_VALUE);
94 }
95 }
96
97 if(!shaderObject)
98 {
99 if(context->getProgram(shader))
100 {
101 return error(GL_INVALID_OPERATION);
102 }
103 else
104 {
105 return error(GL_INVALID_VALUE);
106 }
107 }
108
109 if(!programObject->attachShader(shaderObject))
110 {
111 return error(GL_INVALID_OPERATION);
112 }
113 }
114}
115
116void BeginQueryEXT(GLenum target, GLuint name)
117{
118 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
119
120 switch(target)
121 {
122 case GL_ANY_SAMPLES_PASSED_EXT:
123 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
124 break;
125 default:
126 return error(GL_INVALID_ENUM);
127 }
128
129 if(name == 0)
130 {
131 return error(GL_INVALID_OPERATION);
132 }
133
134 es2::Context *context = es2::getContext();
135
136 if(context)
137 {
138 context->beginQuery(target, name);
139 }
140}
141
142void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
143{
144 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
145
146 if(index >= es2::MAX_VERTEX_ATTRIBS)
147 {
148 return error(GL_INVALID_VALUE);
149 }
150
151 es2::Context *context = es2::getContext();
152
153 if(context)
154 {
155 es2::Program *programObject = context->getProgram(program);
156
157 if(!programObject)
158 {
159 if(context->getShader(program))
160 {
161 return error(GL_INVALID_OPERATION);
162 }
163 else
164 {
165 return error(GL_INVALID_VALUE);
166 }
167 }
168
169 if(strncmp(name, "gl_", 3) == 0)
170 {
171 return error(GL_INVALID_OPERATION);
172 }
173
174 programObject->bindAttributeLocation(index, name);
175 }
176}
177
178void BindBuffer(GLenum target, GLuint buffer)
179{
180 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
181
182 es2::Context *context = es2::getContext();
183
184 if(context)
185 {
186 GLint clientVersion = egl::getClientVersion();
187
188 switch(target)
189 {
190 case GL_ARRAY_BUFFER:
191 context->bindArrayBuffer(buffer);
192 return;
193 case GL_ELEMENT_ARRAY_BUFFER:
194 context->bindElementArrayBuffer(buffer);
195 return;
196 case GL_COPY_READ_BUFFER:
197 if(clientVersion >= 3)
198 {
199 context->bindCopyReadBuffer(buffer);
200 return;
201 }
202 else return error(GL_INVALID_ENUM);
203 case GL_COPY_WRITE_BUFFER:
204 if(clientVersion >= 3)
205 {
206 context->bindCopyWriteBuffer(buffer);
207 return;
208 }
209 else return error(GL_INVALID_ENUM);
210 case GL_PIXEL_PACK_BUFFER:
211 if(clientVersion >= 3)
212 {
213 context->bindPixelPackBuffer(buffer);
214 return;
215 }
216 else return error(GL_INVALID_ENUM);
217 case GL_PIXEL_UNPACK_BUFFER:
218 if(clientVersion >= 3)
219 {
220 context->bindPixelUnpackBuffer(buffer);
221 return;
222 }
223 else return error(GL_INVALID_ENUM);
224 case GL_TRANSFORM_FEEDBACK_BUFFER:
225 if(clientVersion >= 3)
226 {
227 context->bindTransformFeedbackBuffer(buffer);
228 return;
229 }
230 else return error(GL_INVALID_ENUM);
231 case GL_UNIFORM_BUFFER:
232 if(clientVersion >= 3)
233 {
234 context->bindGenericUniformBuffer(buffer);
235 return;
236 }
237 else return error(GL_INVALID_ENUM);
238 default:
239 return error(GL_INVALID_ENUM);
240 }
241 }
242}
243
244void BindFramebuffer(GLenum target, GLuint framebuffer)
245{
246 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
247
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000248 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400249 {
250 return error(GL_INVALID_ENUM);
251 }
252
253 es2::Context *context = es2::getContext();
254
255 if(context)
256 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000257 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400258 {
259 context->bindReadFramebuffer(framebuffer);
260 }
261
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000262 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400263 {
264 context->bindDrawFramebuffer(framebuffer);
265 }
266 }
267}
268
269void BindRenderbuffer(GLenum target, GLuint renderbuffer)
270{
271 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
272
273 if(target != GL_RENDERBUFFER)
274 {
275 return error(GL_INVALID_ENUM);
276 }
277
278 es2::Context *context = es2::getContext();
279
280 if(context)
281 {
282 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
283 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
284 // If renderbuffer is not zero, then the resulting renderbuffer object
285 // is a new state vector, initialized with a zero-sized memory buffer.
286 context->bindRenderbuffer(renderbuffer);
287 }
288}
289
290void BindTexture(GLenum target, GLuint texture)
291{
292 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
293
294 es2::Context *context = es2::getContext();
295
296 if(context)
297 {
298 es2::Texture *textureObject = context->getTexture(texture);
299
300 if(textureObject && textureObject->getTarget() != target && texture != 0)
301 {
302 return error(GL_INVALID_OPERATION);
303 }
304
305 GLint clientVersion = context->getClientVersion();
306
307 switch(target)
308 {
309 case GL_TEXTURE_2D:
310 context->bindTexture2D(texture);
311 break;
312 case GL_TEXTURE_CUBE_MAP:
313 context->bindTextureCubeMap(texture);
314 break;
315 case GL_TEXTURE_EXTERNAL_OES:
316 context->bindTextureExternal(texture);
317 break;
318 case GL_TEXTURE_2D_ARRAY:
319 if(clientVersion < 3)
320 {
321 return error(GL_INVALID_ENUM);
322 }
323 context->bindTexture2DArray(texture);
324 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500325 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400326 context->bindTexture3D(texture);
327 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500328 case GL_TEXTURE_RECTANGLE_ARB:
329 context->bindTexture2DRect(texture);
330 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400331 default:
332 return error(GL_INVALID_ENUM);
333 }
334 }
335}
336
337void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
338{
339 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
340 red, green, blue, alpha);
341
342 es2::Context* context = es2::getContext();
343
344 if(context)
345 {
346 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
347 }
348}
349
350void BlendEquation(GLenum mode)
351{
352 glBlendEquationSeparate(mode, mode);
353}
354
355void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
356{
357 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
358
359 switch(modeRGB)
360 {
361 case GL_FUNC_ADD:
362 case GL_FUNC_SUBTRACT:
363 case GL_FUNC_REVERSE_SUBTRACT:
364 case GL_MIN_EXT:
365 case GL_MAX_EXT:
366 break;
367 default:
368 return error(GL_INVALID_ENUM);
369 }
370
371 switch(modeAlpha)
372 {
373 case GL_FUNC_ADD:
374 case GL_FUNC_SUBTRACT:
375 case GL_FUNC_REVERSE_SUBTRACT:
376 case GL_MIN_EXT:
377 case GL_MAX_EXT:
378 break;
379 default:
380 return error(GL_INVALID_ENUM);
381 }
382
383 es2::Context *context = es2::getContext();
384
385 if(context)
386 {
387 context->setBlendEquation(modeRGB, modeAlpha);
388 }
389}
390
391void BlendFunc(GLenum sfactor, GLenum dfactor)
392{
393 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
394}
395
396void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
397{
398 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
399 srcRGB, dstRGB, srcAlpha, dstAlpha);
400
401 GLint clientVersion = egl::getClientVersion();
402
403 switch(srcRGB)
404 {
405 case GL_ZERO:
406 case GL_ONE:
407 case GL_SRC_COLOR:
408 case GL_ONE_MINUS_SRC_COLOR:
409 case GL_DST_COLOR:
410 case GL_ONE_MINUS_DST_COLOR:
411 case GL_SRC_ALPHA:
412 case GL_ONE_MINUS_SRC_ALPHA:
413 case GL_DST_ALPHA:
414 case GL_ONE_MINUS_DST_ALPHA:
415 case GL_CONSTANT_COLOR:
416 case GL_ONE_MINUS_CONSTANT_COLOR:
417 case GL_CONSTANT_ALPHA:
418 case GL_ONE_MINUS_CONSTANT_ALPHA:
419 case GL_SRC_ALPHA_SATURATE:
420 break;
421 default:
422 return error(GL_INVALID_ENUM);
423 }
424
425 switch(dstRGB)
426 {
427 case GL_ZERO:
428 case GL_ONE:
429 case GL_SRC_COLOR:
430 case GL_ONE_MINUS_SRC_COLOR:
431 case GL_DST_COLOR:
432 case GL_ONE_MINUS_DST_COLOR:
433 case GL_SRC_ALPHA:
434 case GL_ONE_MINUS_SRC_ALPHA:
435 case GL_DST_ALPHA:
436 case GL_ONE_MINUS_DST_ALPHA:
437 case GL_CONSTANT_COLOR:
438 case GL_ONE_MINUS_CONSTANT_COLOR:
439 case GL_CONSTANT_ALPHA:
440 case GL_ONE_MINUS_CONSTANT_ALPHA:
441 break;
442 case GL_SRC_ALPHA_SATURATE:
443 if(clientVersion < 3)
444 {
445 return error(GL_INVALID_ENUM);
446 }
447 break;
448 default:
449 return error(GL_INVALID_ENUM);
450 }
451
452 switch(srcAlpha)
453 {
454 case GL_ZERO:
455 case GL_ONE:
456 case GL_SRC_COLOR:
457 case GL_ONE_MINUS_SRC_COLOR:
458 case GL_DST_COLOR:
459 case GL_ONE_MINUS_DST_COLOR:
460 case GL_SRC_ALPHA:
461 case GL_ONE_MINUS_SRC_ALPHA:
462 case GL_DST_ALPHA:
463 case GL_ONE_MINUS_DST_ALPHA:
464 case GL_CONSTANT_COLOR:
465 case GL_ONE_MINUS_CONSTANT_COLOR:
466 case GL_CONSTANT_ALPHA:
467 case GL_ONE_MINUS_CONSTANT_ALPHA:
468 case GL_SRC_ALPHA_SATURATE:
469 break;
470 default:
471 return error(GL_INVALID_ENUM);
472 }
473
474 switch(dstAlpha)
475 {
476 case GL_ZERO:
477 case GL_ONE:
478 case GL_SRC_COLOR:
479 case GL_ONE_MINUS_SRC_COLOR:
480 case GL_DST_COLOR:
481 case GL_ONE_MINUS_DST_COLOR:
482 case GL_SRC_ALPHA:
483 case GL_ONE_MINUS_SRC_ALPHA:
484 case GL_DST_ALPHA:
485 case GL_ONE_MINUS_DST_ALPHA:
486 case GL_CONSTANT_COLOR:
487 case GL_ONE_MINUS_CONSTANT_COLOR:
488 case GL_CONSTANT_ALPHA:
489 case GL_ONE_MINUS_CONSTANT_ALPHA:
490 break;
491 case GL_SRC_ALPHA_SATURATE:
492 if(clientVersion < 3)
493 {
494 return error(GL_INVALID_ENUM);
495 }
496 break;
497 default:
498 return error(GL_INVALID_ENUM);
499 }
500
501 es2::Context *context = es2::getContext();
502
503 if(context)
504 {
505 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
506 }
507}
508
509void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
510{
511 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
512
513 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
514 target, size, data, usage);
515
516 if(size < 0)
517 {
518 return error(GL_INVALID_VALUE);
519 }
520
521 GLint clientVersion = egl::getClientVersion();
522
523 switch(usage)
524 {
525 case GL_STREAM_DRAW:
526 case GL_STATIC_DRAW:
527 case GL_DYNAMIC_DRAW:
528 break;
529 case GL_STREAM_READ:
530 case GL_STREAM_COPY:
531 case GL_STATIC_READ:
532 case GL_STATIC_COPY:
533 case GL_DYNAMIC_READ:
534 case GL_DYNAMIC_COPY:
535 if(clientVersion < 3)
536 {
537 return error(GL_INVALID_ENUM);
538 }
539 break;
540 default:
541 return error(GL_INVALID_ENUM);
542 }
543
544 es2::Context *context = es2::getContext();
545
546 if(context)
547 {
548 es2::Buffer *buffer = nullptr;
549 if(!context->getBuffer(target, &buffer))
550 {
551 return error(GL_INVALID_ENUM);
552 }
553
554 if(!buffer)
555 {
556 // A null buffer means that "0" is bound to the requested buffer target
557 return error(GL_INVALID_OPERATION);
558 }
559
560 buffer->bufferData(data, size, usage);
561 }
562}
563
564void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
565{
566 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
567 offset = static_cast<GLint>(offset);
568
569 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
570 target, offset, size, data);
571
572 if(size < 0 || offset < 0)
573 {
574 return error(GL_INVALID_VALUE);
575 }
576
577 es2::Context *context = es2::getContext();
578
579 if(context)
580 {
581 es2::Buffer *buffer = nullptr;
582 if(!context->getBuffer(target, &buffer))
583 {
584 return error(GL_INVALID_ENUM);
585 }
586
587 if(!buffer)
588 {
589 // A null buffer means that "0" is bound to the requested buffer target
590 return error(GL_INVALID_OPERATION);
591 }
592
Alexis Hetu6e864492017-11-14 15:27:00 -0500593 if(buffer->isMapped())
594 {
595 // It is an invalid operation to update an already mapped buffer
596 return error(GL_INVALID_OPERATION);
597 }
598
Nicolas Capens0bac2852016-05-07 06:09:58 -0400599 if((size_t)size + offset > buffer->size())
600 {
601 return error(GL_INVALID_VALUE);
602 }
603
604 buffer->bufferSubData(data, size, offset);
605 }
606}
607
608GLenum CheckFramebufferStatus(GLenum target)
609{
610 TRACE("(GLenum target = 0x%X)", target);
611
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000612 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400613 {
614 return error(GL_INVALID_ENUM, 0);
615 }
616
617 es2::Context *context = es2::getContext();
618
619 if(context)
620 {
621 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000622 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400623 {
624 framebuffer = context->getReadFramebuffer();
625 }
626 else
627 {
628 framebuffer = context->getDrawFramebuffer();
629 }
630
631 return framebuffer->completeness();
632 }
633
634 return 0;
635}
636
637void Clear(GLbitfield mask)
638{
639 TRACE("(GLbitfield mask = %X)", mask);
640
641 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
642 {
643 return error(GL_INVALID_VALUE);
644 }
645
646 es2::Context *context = es2::getContext();
647
648 if(context)
649 {
650 context->clear(mask);
651 }
652}
653
654void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
655{
656 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
657 red, green, blue, alpha);
658
659 es2::Context *context = es2::getContext();
660
661 if(context)
662 {
663 context->setClearColor(red, green, blue, alpha);
664 }
665}
666
667void ClearDepthf(GLclampf depth)
668{
669 TRACE("(GLclampf depth = %f)", depth);
670
671 es2::Context *context = es2::getContext();
672
673 if(context)
674 {
675 context->setClearDepth(depth);
676 }
677}
678
679void ClearStencil(GLint s)
680{
681 TRACE("(GLint s = %d)", s);
682
683 es2::Context *context = es2::getContext();
684
685 if(context)
686 {
687 context->setClearStencil(s);
688 }
689}
690
691void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
692{
693 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
694 red, green, blue, alpha);
695
696 es2::Context *context = es2::getContext();
697
698 if(context)
699 {
700 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
701 }
702}
703
704void CompileShader(GLuint shader)
705{
706 TRACE("(GLuint shader = %d)", shader);
707
708 es2::Context *context = es2::getContext();
709
710 if(context)
711 {
712 es2::Shader *shaderObject = context->getShader(shader);
713
714 if(!shaderObject)
715 {
716 if(context->getProgram(shader))
717 {
718 return error(GL_INVALID_OPERATION);
719 }
720 else
721 {
722 return error(GL_INVALID_VALUE);
723 }
724 }
725
726 shaderObject->compile();
727 }
728}
729
730void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
731 GLint border, GLsizei imageSize, const GLvoid* data)
732{
733 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
734 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
735 target, level, internalformat, width, height, border, imageSize, data);
736
737 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
738 {
739 return error(GL_INVALID_VALUE);
740 }
741
Nicolas Capens03589982018-02-01 17:28:32 -0500742 if(!IsCompressed(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400743 {
Nicolas Capens03589982018-02-01 17:28:32 -0500744 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400745 }
746
747 if(border != 0)
748 {
749 return error(GL_INVALID_VALUE);
750 }
751
752 es2::Context *context = es2::getContext();
753
754 if(context)
755 {
756 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
757 {
758 return error(GL_INVALID_VALUE);
759 }
760
761 switch(target)
762 {
763 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -0500764 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400765 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
766 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
767 {
768 return error(GL_INVALID_VALUE);
769 }
770 break;
771 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
772 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
773 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
774 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
775 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
776 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
777 if(width != height)
778 {
779 return error(GL_INVALID_VALUE);
780 }
781
782 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
783 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
784 {
785 return error(GL_INVALID_VALUE);
786 }
787 break;
788 default:
789 return error(GL_INVALID_ENUM);
790 }
791
792 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat))
793 {
794 return error(GL_INVALID_VALUE);
795 }
796
Alexis Hetu46768622018-01-16 22:09:28 -0500797 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400798 {
Alexis Hetu46768622018-01-16 22:09:28 -0500799 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400800
801 if(!texture)
802 {
803 return error(GL_INVALID_OPERATION);
804 }
805
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500806 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500807 if(validationError != GL_NONE)
808 {
809 return error(validationError);
810 }
811
Nicolas Capens0bac2852016-05-07 06:09:58 -0400812 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
813 }
814 else
815 {
816 es2::TextureCubeMap *texture = context->getTextureCubeMap();
817
818 if(!texture)
819 {
820 return error(GL_INVALID_OPERATION);
821 }
822
823 switch(target)
824 {
825 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
826 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
827 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
828 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
829 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
830 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500831 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500832 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500833 if(validationError != GL_NONE)
834 {
835 return error(validationError);
836 }
837
838 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
839 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400840 break;
841 default: UNREACHABLE(target);
842 }
843 }
844 }
845}
846
847void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
848 GLenum format, GLsizei imageSize, const GLvoid* data)
849{
850 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
851 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
852 "GLsizei imageSize = %d, const GLvoid* data = %p)",
853 target, level, xoffset, yoffset, width, height, format, imageSize, data);
854
855 if(!es2::IsTextureTarget(target))
856 {
857 return error(GL_INVALID_ENUM);
858 }
859
860 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
861 {
862 return error(GL_INVALID_VALUE);
863 }
864
865 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
866 {
867 return error(GL_INVALID_VALUE);
868 }
869
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500870 if(imageSize != egl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400871 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500872 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400873 }
874
875 es2::Context *context = es2::getContext();
876
877 if(context)
878 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400879 if(xoffset % 4 != 0 || yoffset % 4 != 0)
880 {
881 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
882 return error(GL_INVALID_OPERATION);
883 }
884
885 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_NONE);
886
Alexis Hetu46768622018-01-16 22:09:28 -0500887 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400888 {
Alexis Hetu46768622018-01-16 22:09:28 -0500889 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400890
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500891 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
892 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400893 {
894 return error(validationError);
895 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500896
897 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
898 if(validationError != GL_NONE)
899 {
900 return error(validationError);
901 }
902
903 texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400904 }
905 else if(es2::IsCubemapTextureTarget(target))
906 {
907 es2::TextureCubeMap *texture = context->getTextureCubeMap();
908
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500909 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
910 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400911 {
912 return error(validationError);
913 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500914
915 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
916 if(validationError != GL_NONE)
917 {
918 return error(validationError);
919 }
920
921 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400922 }
923 else UNREACHABLE(target);
924 }
925}
926
927void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
928{
929 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
930 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
931 target, level, internalformat, x, y, width, height, border);
932
933 if(!validImageSize(level, width, height))
934 {
935 return error(GL_INVALID_VALUE);
936 }
937
938 if(border != 0)
939 {
940 return error(GL_INVALID_VALUE);
941 }
942
943 es2::Context *context = es2::getContext();
944
945 if(context)
946 {
947 switch(target)
948 {
949 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -0500950 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400951 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
952 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
953 {
954 return error(GL_INVALID_VALUE);
955 }
956 break;
957 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
958 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
959 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
960 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
961 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
962 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
963 if(width != height)
964 {
965 return error(GL_INVALID_VALUE);
966 }
967
968 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
969 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
970 {
971 return error(GL_INVALID_VALUE);
972 }
973 break;
974 default:
975 return error(GL_INVALID_ENUM);
976 }
977
978 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
979
980 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
981 {
982 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
983 }
984
985 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
986
987 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
988 {
989 return error(GL_INVALID_OPERATION);
990 }
991
992 GLenum colorbufferFormat = source->getFormat();
993
Nicolas Capens8f215a42018-02-02 13:25:53 -0500994 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400995 {
996 return;
997 }
998
Alexis Hetu46768622018-01-16 22:09:28 -0500999 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001000 {
Alexis Hetu46768622018-01-16 22:09:28 -05001001 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001002
1003 if(!texture)
1004 {
1005 return error(GL_INVALID_OPERATION);
1006 }
1007
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001008 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001009 }
1010 else if(es2::IsCubemapTextureTarget(target))
1011 {
1012 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1013
1014 if(!texture)
1015 {
1016 return error(GL_INVALID_OPERATION);
1017 }
1018
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001019 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001020 }
1021 else UNREACHABLE(target);
1022 }
1023}
1024
1025void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1026{
1027 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1028 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1029 target, level, xoffset, yoffset, x, y, width, height);
1030
1031 if(!es2::IsTextureTarget(target))
1032 {
1033 return error(GL_INVALID_ENUM);
1034 }
1035
1036 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1037 {
1038 return error(GL_INVALID_VALUE);
1039 }
1040
1041 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1042 {
1043 return error(GL_INVALID_VALUE);
1044 }
1045
1046 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1047 {
1048 return error(GL_INVALID_VALUE);
1049 }
1050
Nicolas Capens0bac2852016-05-07 06:09:58 -04001051 es2::Context *context = es2::getContext();
1052
1053 if(context)
1054 {
1055 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1056
1057 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1058 {
1059 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1060 }
1061
1062 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1063
1064 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1065 {
1066 return error(GL_INVALID_OPERATION);
1067 }
1068
1069 es2::Texture *texture = nullptr;
1070
Alexis Hetu46768622018-01-16 22:09:28 -05001071 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001072 {
Alexis Hetu46768622018-01-16 22:09:28 -05001073 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001074 }
1075 else if(es2::IsCubemapTextureTarget(target))
1076 {
1077 texture = context->getTextureCubeMap();
1078 }
1079 else UNREACHABLE(target);
1080
Nicolas Capensd2faaa92017-12-04 11:15:51 -05001081 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capens0bac2852016-05-07 06:09:58 -04001082 if(validationError != GL_NONE)
1083 {
1084 return error(validationError);
1085 }
1086
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001087 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001088 }
1089}
1090
1091GLuint CreateProgram(void)
1092{
1093 TRACE("()");
1094
1095 es2::Context *context = es2::getContext();
1096
1097 if(context)
1098 {
1099 return context->createProgram();
1100 }
1101
1102 return 0;
1103}
1104
1105GLuint CreateShader(GLenum type)
1106{
1107 TRACE("(GLenum type = 0x%X)", type);
1108
1109 es2::Context *context = es2::getContext();
1110
1111 if(context)
1112 {
1113 switch(type)
1114 {
1115 case GL_FRAGMENT_SHADER:
1116 case GL_VERTEX_SHADER:
1117 return context->createShader(type);
1118 default:
1119 return error(GL_INVALID_ENUM, 0);
1120 }
1121 }
1122
1123 return 0;
1124}
1125
1126void CullFace(GLenum mode)
1127{
1128 TRACE("(GLenum mode = 0x%X)", mode);
1129
1130 switch(mode)
1131 {
1132 case GL_FRONT:
1133 case GL_BACK:
1134 case GL_FRONT_AND_BACK:
1135 {
1136 es2::Context *context = es2::getContext();
1137
1138 if(context)
1139 {
1140 context->setCullMode(mode);
1141 }
1142 }
1143 break;
1144 default:
1145 return error(GL_INVALID_ENUM);
1146 }
1147}
1148
1149void DeleteBuffers(GLsizei n, const GLuint* buffers)
1150{
1151 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1152
1153 if(n < 0)
1154 {
1155 return error(GL_INVALID_VALUE);
1156 }
1157
1158 es2::Context *context = es2::getContext();
1159
1160 if(context)
1161 {
1162 for(int i = 0; i < n; i++)
1163 {
1164 context->deleteBuffer(buffers[i]);
1165 }
1166 }
1167}
1168
1169void DeleteFencesNV(GLsizei n, const GLuint* fences)
1170{
1171 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1172
1173 if(n < 0)
1174 {
1175 return error(GL_INVALID_VALUE);
1176 }
1177
1178 es2::Context *context = es2::getContext();
1179
1180 if(context)
1181 {
1182 for(int i = 0; i < n; i++)
1183 {
1184 context->deleteFence(fences[i]);
1185 }
1186 }
1187}
1188
1189void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1190{
1191 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1192
1193 if(n < 0)
1194 {
1195 return error(GL_INVALID_VALUE);
1196 }
1197
1198 es2::Context *context = es2::getContext();
1199
1200 if(context)
1201 {
1202 for(int i = 0; i < n; i++)
1203 {
1204 if(framebuffers[i] != 0)
1205 {
1206 context->deleteFramebuffer(framebuffers[i]);
1207 }
1208 }
1209 }
1210}
1211
1212void DeleteProgram(GLuint program)
1213{
1214 TRACE("(GLuint program = %d)", program);
1215
1216 if(program == 0)
1217 {
1218 return;
1219 }
1220
1221 es2::Context *context = es2::getContext();
1222
1223 if(context)
1224 {
1225 if(!context->getProgram(program))
1226 {
1227 if(context->getShader(program))
1228 {
1229 return error(GL_INVALID_OPERATION);
1230 }
1231 else
1232 {
1233 return error(GL_INVALID_VALUE);
1234 }
1235 }
1236
1237 context->deleteProgram(program);
1238 }
1239}
1240
1241void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1242{
1243 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1244
1245 if(n < 0)
1246 {
1247 return error(GL_INVALID_VALUE);
1248 }
1249
1250 es2::Context *context = es2::getContext();
1251
1252 if(context)
1253 {
1254 for(int i = 0; i < n; i++)
1255 {
1256 context->deleteQuery(ids[i]);
1257 }
1258 }
1259}
1260
1261void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1262{
1263 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1264
1265 if(n < 0)
1266 {
1267 return error(GL_INVALID_VALUE);
1268 }
1269
1270 es2::Context *context = es2::getContext();
1271
1272 if(context)
1273 {
1274 for(int i = 0; i < n; i++)
1275 {
1276 context->deleteRenderbuffer(renderbuffers[i]);
1277 }
1278 }
1279}
1280
1281void DeleteShader(GLuint shader)
1282{
1283 TRACE("(GLuint shader = %d)", shader);
1284
1285 if(shader == 0)
1286 {
1287 return;
1288 }
1289
1290 es2::Context *context = es2::getContext();
1291
1292 if(context)
1293 {
1294 if(!context->getShader(shader))
1295 {
1296 if(context->getProgram(shader))
1297 {
1298 return error(GL_INVALID_OPERATION);
1299 }
1300 else
1301 {
1302 return error(GL_INVALID_VALUE);
1303 }
1304 }
1305
1306 context->deleteShader(shader);
1307 }
1308}
1309
1310void DeleteTextures(GLsizei n, const GLuint* textures)
1311{
1312 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1313
1314 if(n < 0)
1315 {
1316 return error(GL_INVALID_VALUE);
1317 }
1318
1319 es2::Context *context = es2::getContext();
1320
1321 if(context)
1322 {
1323 for(int i = 0; i < n; i++)
1324 {
1325 if(textures[i] != 0)
1326 {
1327 context->deleteTexture(textures[i]);
1328 }
1329 }
1330 }
1331}
1332
1333void DepthFunc(GLenum func)
1334{
1335 TRACE("(GLenum func = 0x%X)", func);
1336
1337 switch(func)
1338 {
1339 case GL_NEVER:
1340 case GL_ALWAYS:
1341 case GL_LESS:
1342 case GL_LEQUAL:
1343 case GL_EQUAL:
1344 case GL_GREATER:
1345 case GL_GEQUAL:
1346 case GL_NOTEQUAL:
1347 break;
1348 default:
1349 return error(GL_INVALID_ENUM);
1350 }
1351
1352 es2::Context *context = es2::getContext();
1353
1354 if(context)
1355 {
1356 context->setDepthFunc(func);
1357 }
1358}
1359
1360void DepthMask(GLboolean flag)
1361{
1362 TRACE("(GLboolean flag = %d)", flag);
1363
1364 es2::Context *context = es2::getContext();
1365
1366 if(context)
1367 {
1368 context->setDepthMask(flag != GL_FALSE);
1369 }
1370}
1371
1372void DepthRangef(GLclampf zNear, GLclampf zFar)
1373{
1374 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1375
1376 es2::Context *context = es2::getContext();
1377
1378 if(context)
1379 {
1380 context->setDepthRange(zNear, zFar);
1381 }
1382}
1383
1384void DetachShader(GLuint program, GLuint shader)
1385{
1386 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1387
1388 es2::Context *context = es2::getContext();
1389
1390 if(context)
1391 {
1392
1393 es2::Program *programObject = context->getProgram(program);
1394 es2::Shader *shaderObject = context->getShader(shader);
1395
1396 if(!programObject)
1397 {
1398 es2::Shader *shaderByProgramHandle;
1399 shaderByProgramHandle = context->getShader(program);
1400 if(!shaderByProgramHandle)
1401 {
1402 return error(GL_INVALID_VALUE);
1403 }
1404 else
1405 {
1406 return error(GL_INVALID_OPERATION);
1407 }
1408 }
1409
1410 if(!shaderObject)
1411 {
1412 es2::Program *programByShaderHandle = context->getProgram(shader);
1413 if(!programByShaderHandle)
1414 {
1415 return error(GL_INVALID_VALUE);
1416 }
1417 else
1418 {
1419 return error(GL_INVALID_OPERATION);
1420 }
1421 }
1422
1423 if(!programObject->detachShader(shaderObject))
1424 {
1425 return error(GL_INVALID_OPERATION);
1426 }
1427 }
1428}
1429
1430void Disable(GLenum cap)
1431{
1432 TRACE("(GLenum cap = 0x%X)", cap);
1433
1434 es2::Context *context = es2::getContext();
1435
1436 if(context)
1437 {
1438 switch(cap)
1439 {
1440 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1441 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1442 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1443 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1444 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1445 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1446 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1447 case GL_BLEND: context->setBlendEnabled(false); break;
1448 case GL_DITHER: context->setDitherEnabled(false); break;
1449 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1450 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1451 default:
1452 return error(GL_INVALID_ENUM);
1453 }
1454 }
1455}
1456
1457void DisableVertexAttribArray(GLuint index)
1458{
1459 TRACE("(GLuint index = %d)", index);
1460
1461 if(index >= es2::MAX_VERTEX_ATTRIBS)
1462 {
1463 return error(GL_INVALID_VALUE);
1464 }
1465
1466 es2::Context *context = es2::getContext();
1467
1468 if(context)
1469 {
1470 context->setVertexAttribArrayEnabled(index, false);
1471 }
1472}
1473
1474void DrawArrays(GLenum mode, GLint first, GLsizei count)
1475{
1476 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1477
1478 switch(mode)
1479 {
1480 case GL_POINTS:
1481 case GL_LINES:
1482 case GL_LINE_LOOP:
1483 case GL_LINE_STRIP:
1484 case GL_TRIANGLES:
1485 case GL_TRIANGLE_FAN:
1486 case GL_TRIANGLE_STRIP:
1487 break;
1488 default:
1489 return error(GL_INVALID_ENUM);
1490 }
1491
1492 if(count < 0 || first < 0)
1493 {
1494 return error(GL_INVALID_VALUE);
1495 }
1496
1497 es2::Context *context = es2::getContext();
1498
1499 if(context)
1500 {
1501 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1502 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1503 {
1504 return error(GL_INVALID_OPERATION);
1505 }
1506
1507 context->drawArrays(mode, first, count);
1508 }
1509}
1510
1511void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1512{
1513 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1514 mode, count, type, indices);
1515
1516 switch(mode)
1517 {
1518 case GL_POINTS:
1519 case GL_LINES:
1520 case GL_LINE_LOOP:
1521 case GL_LINE_STRIP:
1522 case GL_TRIANGLES:
1523 case GL_TRIANGLE_FAN:
1524 case GL_TRIANGLE_STRIP:
1525 break;
1526 default:
1527 return error(GL_INVALID_ENUM);
1528 }
1529
1530 if(count < 0)
1531 {
1532 return error(GL_INVALID_VALUE);
1533 }
1534
1535 es2::Context *context = es2::getContext();
1536
1537 if(context)
1538 {
1539 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1540 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1541 {
1542 return error(GL_INVALID_OPERATION);
1543 }
1544
1545 switch(type)
1546 {
1547 case GL_UNSIGNED_BYTE:
1548 case GL_UNSIGNED_SHORT:
1549 case GL_UNSIGNED_INT:
1550 break;
1551 default:
1552 return error(GL_INVALID_ENUM);
1553 }
1554
1555 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1556 }
1557}
1558
1559void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1560{
1561 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1562 mode, first, count, instanceCount);
1563
1564 switch(mode)
1565 {
1566 case GL_POINTS:
1567 case GL_LINES:
1568 case GL_LINE_LOOP:
1569 case GL_LINE_STRIP:
1570 case GL_TRIANGLES:
1571 case GL_TRIANGLE_FAN:
1572 case GL_TRIANGLE_STRIP:
1573 break;
1574 default:
1575 return error(GL_INVALID_ENUM);
1576 }
1577
1578 if(count < 0 || instanceCount < 0)
1579 {
1580 return error(GL_INVALID_VALUE);
1581 }
1582
1583 es2::Context *context = es2::getContext();
1584
1585 if(context)
1586 {
1587 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1588 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1589 {
1590 return error(GL_INVALID_OPERATION);
1591 }
1592
1593 context->drawArrays(mode, first, count, instanceCount);
1594 }
1595}
1596
1597void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1598{
1599 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1600 mode, count, type, indices, instanceCount);
1601
1602 switch(mode)
1603 {
1604 case GL_POINTS:
1605 case GL_LINES:
1606 case GL_LINE_LOOP:
1607 case GL_LINE_STRIP:
1608 case GL_TRIANGLES:
1609 case GL_TRIANGLE_FAN:
1610 case GL_TRIANGLE_STRIP:
1611 break;
1612 default:
1613 return error(GL_INVALID_ENUM);
1614 }
1615
1616 switch(type)
1617 {
1618 case GL_UNSIGNED_BYTE:
1619 case GL_UNSIGNED_SHORT:
1620 case GL_UNSIGNED_INT:
1621 break;
1622 default:
1623 return error(GL_INVALID_ENUM);
1624 }
1625
1626 if(count < 0 || instanceCount < 0)
1627 {
1628 return error(GL_INVALID_VALUE);
1629 }
1630
1631 es2::Context *context = es2::getContext();
1632
1633 if(context)
1634 {
1635 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1636 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1637 {
1638 return error(GL_INVALID_OPERATION);
1639 }
1640
1641 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1642 }
1643}
1644
1645void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1646{
1647 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1648
1649 es2::Context *context = es2::getContext();
1650
1651 if(context)
1652 {
1653 if(index >= es2::MAX_VERTEX_ATTRIBS)
1654 {
1655 return error(GL_INVALID_VALUE);
1656 }
1657
1658 context->setVertexAttribDivisor(index, divisor);
1659 }
1660}
1661
1662void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1663{
1664 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1665 mode, first, count, instanceCount);
1666
1667 switch(mode)
1668 {
1669 case GL_POINTS:
1670 case GL_LINES:
1671 case GL_LINE_LOOP:
1672 case GL_LINE_STRIP:
1673 case GL_TRIANGLES:
1674 case GL_TRIANGLE_FAN:
1675 case GL_TRIANGLE_STRIP:
1676 break;
1677 default:
1678 return error(GL_INVALID_ENUM);
1679 }
1680
1681 if(count < 0 || instanceCount < 0)
1682 {
1683 return error(GL_INVALID_VALUE);
1684 }
1685
1686 es2::Context *context = es2::getContext();
1687
1688 if(context)
1689 {
1690 if(!context->hasZeroDivisor())
1691 {
1692 return error(GL_INVALID_OPERATION);
1693 }
1694
1695 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1696 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1697 {
1698 return error(GL_INVALID_OPERATION);
1699 }
1700
1701 context->drawArrays(mode, first, count, instanceCount);
1702 }
1703}
1704
1705void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1706{
1707 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1708 mode, count, type, indices, instanceCount);
1709
1710 switch(mode)
1711 {
1712 case GL_POINTS:
1713 case GL_LINES:
1714 case GL_LINE_LOOP:
1715 case GL_LINE_STRIP:
1716 case GL_TRIANGLES:
1717 case GL_TRIANGLE_FAN:
1718 case GL_TRIANGLE_STRIP:
1719 break;
1720 default:
1721 return error(GL_INVALID_ENUM);
1722 }
1723
1724 switch(type)
1725 {
1726 case GL_UNSIGNED_BYTE:
1727 case GL_UNSIGNED_SHORT:
1728 case GL_UNSIGNED_INT:
1729 break;
1730 default:
1731 return error(GL_INVALID_ENUM);
1732 }
1733
1734 if(count < 0 || instanceCount < 0)
1735 {
1736 return error(GL_INVALID_VALUE);
1737 }
1738
1739 es2::Context *context = es2::getContext();
1740
1741 if(context)
1742 {
1743 if(!context->hasZeroDivisor())
1744 {
1745 return error(GL_INVALID_OPERATION);
1746 }
1747
1748 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1749 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1750 {
1751 return error(GL_INVALID_OPERATION);
1752 }
1753
1754 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1755 }
1756}
1757
1758void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1759{
1760 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1761
1762 es2::Context *context = es2::getContext();
1763
1764 if(context)
1765 {
1766 if(index >= MAX_VERTEX_ATTRIBS)
1767 {
1768 return error(GL_INVALID_VALUE);
1769 }
1770
1771 context->setVertexAttribDivisor(index, divisor);
1772 }
1773}
1774
1775void Enable(GLenum cap)
1776{
1777 TRACE("(GLenum cap = 0x%X)", cap);
1778
1779 es2::Context *context = es2::getContext();
1780
1781 if(context)
1782 {
1783 switch(cap)
1784 {
1785 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1786 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1787 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1788 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1789 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1790 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1791 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1792 case GL_BLEND: context->setBlendEnabled(true); break;
1793 case GL_DITHER: context->setDitherEnabled(true); break;
1794 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1795 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1796 default:
1797 return error(GL_INVALID_ENUM);
1798 }
1799 }
1800}
1801
1802void EnableVertexAttribArray(GLuint index)
1803{
1804 TRACE("(GLuint index = %d)", index);
1805
1806 if(index >= es2::MAX_VERTEX_ATTRIBS)
1807 {
1808 return error(GL_INVALID_VALUE);
1809 }
1810
1811 es2::Context *context = es2::getContext();
1812
1813 if(context)
1814 {
1815 context->setVertexAttribArrayEnabled(index, true);
1816 }
1817}
1818
1819void EndQueryEXT(GLenum target)
1820{
1821 TRACE("GLenum target = 0x%X)", target);
1822
1823 switch(target)
1824 {
1825 case GL_ANY_SAMPLES_PASSED_EXT:
1826 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1827 break;
1828 default:
1829 return error(GL_INVALID_ENUM);
1830 }
1831
1832 es2::Context *context = es2::getContext();
1833
1834 if(context)
1835 {
1836 context->endQuery(target);
1837 }
1838}
1839
1840void FinishFenceNV(GLuint fence)
1841{
1842 TRACE("(GLuint fence = %d)", fence);
1843
1844 es2::Context *context = es2::getContext();
1845
1846 if(context)
1847 {
1848 es2::Fence *fenceObject = context->getFence(fence);
1849
1850 if(!fenceObject)
1851 {
1852 return error(GL_INVALID_OPERATION);
1853 }
1854
1855 fenceObject->finishFence();
1856 }
1857}
1858
1859void Finish(void)
1860{
1861 TRACE("()");
1862
1863 es2::Context *context = es2::getContext();
1864
1865 if(context)
1866 {
1867 context->finish();
1868 }
1869}
1870
1871void Flush(void)
1872{
1873 TRACE("()");
1874
1875 es2::Context *context = es2::getContext();
1876
1877 if(context)
1878 {
1879 context->flush();
1880 }
1881}
1882
1883void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1884{
1885 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1886 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1887
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001888 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001889 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1890 {
1891 return error(GL_INVALID_ENUM);
1892 }
1893
1894 es2::Context *context = es2::getContext();
1895
1896 if(context)
1897 {
1898 es2::Framebuffer *framebuffer = nullptr;
1899 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001900 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001901 {
1902 framebuffer = context->getReadFramebuffer();
1903 framebufferName = context->getReadFramebufferName();
1904 }
1905 else
1906 {
1907 framebuffer = context->getDrawFramebuffer();
1908 framebufferName = context->getDrawFramebufferName();
1909 }
1910
1911 if(!framebuffer || framebufferName == 0)
1912 {
1913 return error(GL_INVALID_OPERATION);
1914 }
1915
1916 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1917 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1918 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1919 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1920 if(renderbuffer != 0)
1921 {
1922 if(!context->getRenderbuffer(renderbuffer))
1923 {
1924 return error(GL_INVALID_OPERATION);
1925 }
1926 }
1927
1928 GLint clientVersion = context->getClientVersion();
1929
1930 switch(attachment)
1931 {
1932 case GL_COLOR_ATTACHMENT0:
1933 case GL_COLOR_ATTACHMENT1:
1934 case GL_COLOR_ATTACHMENT2:
1935 case GL_COLOR_ATTACHMENT3:
1936 case GL_COLOR_ATTACHMENT4:
1937 case GL_COLOR_ATTACHMENT5:
1938 case GL_COLOR_ATTACHMENT6:
1939 case GL_COLOR_ATTACHMENT7:
1940 case GL_COLOR_ATTACHMENT8:
1941 case GL_COLOR_ATTACHMENT9:
1942 case GL_COLOR_ATTACHMENT10:
1943 case GL_COLOR_ATTACHMENT11:
1944 case GL_COLOR_ATTACHMENT12:
1945 case GL_COLOR_ATTACHMENT13:
1946 case GL_COLOR_ATTACHMENT14:
1947 case GL_COLOR_ATTACHMENT15:
1948 case GL_COLOR_ATTACHMENT16:
1949 case GL_COLOR_ATTACHMENT17:
1950 case GL_COLOR_ATTACHMENT18:
1951 case GL_COLOR_ATTACHMENT19:
1952 case GL_COLOR_ATTACHMENT20:
1953 case GL_COLOR_ATTACHMENT21:
1954 case GL_COLOR_ATTACHMENT22:
1955 case GL_COLOR_ATTACHMENT23:
1956 case GL_COLOR_ATTACHMENT24:
1957 case GL_COLOR_ATTACHMENT25:
1958 case GL_COLOR_ATTACHMENT26:
1959 case GL_COLOR_ATTACHMENT27:
1960 case GL_COLOR_ATTACHMENT28:
1961 case GL_COLOR_ATTACHMENT29:
1962 case GL_COLOR_ATTACHMENT30:
1963 case GL_COLOR_ATTACHMENT31:
1964 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1965 {
1966 return error(GL_INVALID_ENUM);
1967 }
1968 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1969 break;
1970 case GL_DEPTH_ATTACHMENT:
1971 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1972 break;
1973 case GL_STENCIL_ATTACHMENT:
1974 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1975 break;
1976 case GL_DEPTH_STENCIL_ATTACHMENT:
1977 if(clientVersion >= 3)
1978 {
1979 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1980 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1981 break;
1982 }
1983 else return error(GL_INVALID_ENUM);
1984 default:
1985 return error(GL_INVALID_ENUM);
1986 }
1987 }
1988}
1989
1990void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1991{
1992 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1993 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1994
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001995 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001996 {
1997 return error(GL_INVALID_ENUM);
1998 }
1999
2000 es2::Context *context = es2::getContext();
2001
2002 if(context)
2003 {
Nicolas Capensd5401e22017-03-16 17:32:43 -04002004 GLint clientVersion = context->getClientVersion();
2005
Nicolas Capens0bac2852016-05-07 06:09:58 -04002006 if(texture == 0)
2007 {
2008 textarget = GL_NONE;
2009 }
2010 else
2011 {
2012 es2::Texture *tex = context->getTexture(texture);
2013
2014 if(!tex)
2015 {
2016 return error(GL_INVALID_OPERATION);
2017 }
2018
2019 switch(textarget)
2020 {
2021 case GL_TEXTURE_2D:
2022 if(tex->getTarget() != GL_TEXTURE_2D)
2023 {
2024 return error(GL_INVALID_OPERATION);
2025 }
2026 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002027 case GL_TEXTURE_RECTANGLE_ARB:
2028 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
2029 {
2030 return error(GL_INVALID_OPERATION);
2031 }
2032 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002033 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2034 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2035 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2036 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2037 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2038 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2039 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2040 {
2041 return error(GL_INVALID_OPERATION);
2042 }
2043 break;
2044 default:
2045 return error(GL_INVALID_ENUM);
2046 }
2047
Nicolas Capensd5401e22017-03-16 17:32:43 -04002048 if((level != 0) && (clientVersion < 3))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002049 {
2050 return error(GL_INVALID_VALUE);
2051 }
2052
2053 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2054 {
2055 return error(GL_INVALID_VALUE);
2056 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002057
2058 if(tex->isCompressed(textarget, level))
2059 {
2060 return error(GL_INVALID_OPERATION);
2061 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002062 }
2063
2064 es2::Framebuffer *framebuffer = nullptr;
2065 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002066 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002067 {
2068 framebuffer = context->getReadFramebuffer();
2069 framebufferName = context->getReadFramebufferName();
2070 }
2071 else
2072 {
2073 framebuffer = context->getDrawFramebuffer();
2074 framebufferName = context->getDrawFramebufferName();
2075 }
2076
2077 if(framebufferName == 0 || !framebuffer)
2078 {
2079 return error(GL_INVALID_OPERATION);
2080 }
2081
2082 switch(attachment)
2083 {
2084 case GL_COLOR_ATTACHMENT0:
2085 case GL_COLOR_ATTACHMENT1:
2086 case GL_COLOR_ATTACHMENT2:
2087 case GL_COLOR_ATTACHMENT3:
2088 case GL_COLOR_ATTACHMENT4:
2089 case GL_COLOR_ATTACHMENT5:
2090 case GL_COLOR_ATTACHMENT6:
2091 case GL_COLOR_ATTACHMENT7:
2092 case GL_COLOR_ATTACHMENT8:
2093 case GL_COLOR_ATTACHMENT9:
2094 case GL_COLOR_ATTACHMENT10:
2095 case GL_COLOR_ATTACHMENT11:
2096 case GL_COLOR_ATTACHMENT12:
2097 case GL_COLOR_ATTACHMENT13:
2098 case GL_COLOR_ATTACHMENT14:
2099 case GL_COLOR_ATTACHMENT15:
2100 case GL_COLOR_ATTACHMENT16:
2101 case GL_COLOR_ATTACHMENT17:
2102 case GL_COLOR_ATTACHMENT18:
2103 case GL_COLOR_ATTACHMENT19:
2104 case GL_COLOR_ATTACHMENT20:
2105 case GL_COLOR_ATTACHMENT21:
2106 case GL_COLOR_ATTACHMENT22:
2107 case GL_COLOR_ATTACHMENT23:
2108 case GL_COLOR_ATTACHMENT24:
2109 case GL_COLOR_ATTACHMENT25:
2110 case GL_COLOR_ATTACHMENT26:
2111 case GL_COLOR_ATTACHMENT27:
2112 case GL_COLOR_ATTACHMENT28:
2113 case GL_COLOR_ATTACHMENT29:
2114 case GL_COLOR_ATTACHMENT30:
2115 case GL_COLOR_ATTACHMENT31:
2116 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2117 {
2118 return error(GL_INVALID_ENUM);
2119 }
2120 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2121 break;
2122 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2123 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capensd5401e22017-03-16 17:32:43 -04002124 case GL_DEPTH_STENCIL_ATTACHMENT:
2125 if(clientVersion >= 3)
2126 {
2127 framebuffer->setDepthbuffer(textarget, texture, level);
2128 framebuffer->setStencilbuffer(textarget, texture, level);
2129 break;
2130 }
2131 else return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002132 default:
2133 return error(GL_INVALID_ENUM);
2134 }
2135 }
2136}
2137
2138void FrontFace(GLenum mode)
2139{
2140 TRACE("(GLenum mode = 0x%X)", mode);
2141
2142 switch(mode)
2143 {
2144 case GL_CW:
2145 case GL_CCW:
2146 {
2147 es2::Context *context = es2::getContext();
2148
2149 if(context)
2150 {
2151 context->setFrontFace(mode);
2152 }
2153 }
2154 break;
2155 default:
2156 return error(GL_INVALID_ENUM);
2157 }
2158}
2159
2160void GenBuffers(GLsizei n, GLuint* buffers)
2161{
2162 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2163
2164 if(n < 0)
2165 {
2166 return error(GL_INVALID_VALUE);
2167 }
2168
2169 es2::Context *context = es2::getContext();
2170
2171 if(context)
2172 {
2173 for(int i = 0; i < n; i++)
2174 {
2175 buffers[i] = context->createBuffer();
2176 }
2177 }
2178}
2179
2180void GenerateMipmap(GLenum target)
2181{
2182 TRACE("(GLenum target = 0x%X)", target);
2183
2184 es2::Context *context = es2::getContext();
2185
2186 if(context)
2187 {
2188 es2::Texture *texture = nullptr;
2189
2190 GLint clientVersion = context->getClientVersion();
2191
2192 switch(target)
2193 {
2194 case GL_TEXTURE_2D:
2195 texture = context->getTexture2D();
2196 break;
2197 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002198 {
2199 TextureCubeMap *cube = context->getTextureCubeMap();
2200 texture = cube;
2201
2202 if(!cube->isCubeComplete())
2203 {
2204 return error(GL_INVALID_OPERATION);
2205 }
2206 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002207 break;
2208 case GL_TEXTURE_2D_ARRAY:
2209 if(clientVersion < 3)
2210 {
2211 return error(GL_INVALID_ENUM);
2212 }
2213 else
2214 {
2215 texture = context->getTexture2DArray();
2216 }
2217 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002218 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002219 texture = context->getTexture3D();
2220 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002221 case GL_TEXTURE_RECTANGLE_ARB:
2222 texture = context->getTexture2DRect();
2223 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002224 default:
2225 return error(GL_INVALID_ENUM);
2226 }
2227
Nicolas Capense6115342017-12-18 15:58:46 -05002228 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel()), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002229 {
2230 return error(GL_INVALID_OPERATION);
2231 }
2232
Nicolas Capens0bac2852016-05-07 06:09:58 -04002233 texture->generateMipmaps();
2234 }
2235}
2236
2237void GenFencesNV(GLsizei n, GLuint* fences)
2238{
2239 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2240
2241 if(n < 0)
2242 {
2243 return error(GL_INVALID_VALUE);
2244 }
2245
2246 es2::Context *context = es2::getContext();
2247
2248 if(context)
2249 {
2250 for(int i = 0; i < n; i++)
2251 {
2252 fences[i] = context->createFence();
2253 }
2254 }
2255}
2256
2257void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2258{
2259 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2260
2261 if(n < 0)
2262 {
2263 return error(GL_INVALID_VALUE);
2264 }
2265
2266 es2::Context *context = es2::getContext();
2267
2268 if(context)
2269 {
2270 for(int i = 0; i < n; i++)
2271 {
2272 framebuffers[i] = context->createFramebuffer();
2273 }
2274 }
2275}
2276
2277void GenQueriesEXT(GLsizei n, GLuint* ids)
2278{
2279 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2280
2281 if(n < 0)
2282 {
2283 return error(GL_INVALID_VALUE);
2284 }
2285
2286 es2::Context *context = es2::getContext();
2287
2288 if(context)
2289 {
2290 for(int i = 0; i < n; i++)
2291 {
2292 ids[i] = context->createQuery();
2293 }
2294 }
2295}
2296
2297void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2298{
2299 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2300
2301 if(n < 0)
2302 {
2303 return error(GL_INVALID_VALUE);
2304 }
2305
2306 es2::Context *context = es2::getContext();
2307
2308 if(context)
2309 {
2310 for(int i = 0; i < n; i++)
2311 {
2312 renderbuffers[i] = context->createRenderbuffer();
2313 }
2314 }
2315}
2316
2317void GenTextures(GLsizei n, GLuint* textures)
2318{
2319 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2320
2321 if(n < 0)
2322 {
2323 return error(GL_INVALID_VALUE);
2324 }
2325
2326 es2::Context *context = es2::getContext();
2327
2328 if(context)
2329 {
2330 for(int i = 0; i < n; i++)
2331 {
2332 textures[i] = context->createTexture();
2333 }
2334 }
2335}
2336
2337void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2338{
2339 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2340 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2341 program, index, bufsize, length, size, type, name);
2342
2343 if(bufsize < 0)
2344 {
2345 return error(GL_INVALID_VALUE);
2346 }
2347
2348 es2::Context *context = es2::getContext();
2349
2350 if(context)
2351 {
2352 es2::Program *programObject = context->getProgram(program);
2353
2354 if(!programObject)
2355 {
2356 if(context->getShader(program))
2357 {
2358 return error(GL_INVALID_OPERATION);
2359 }
2360 else
2361 {
2362 return error(GL_INVALID_VALUE);
2363 }
2364 }
2365
2366 if(index >= programObject->getActiveAttributeCount())
2367 {
2368 return error(GL_INVALID_VALUE);
2369 }
2370
2371 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2372 }
2373}
2374
2375void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2376{
2377 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2378 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2379 program, index, bufsize, length, size, type, name);
2380
2381 if(bufsize < 0)
2382 {
2383 return error(GL_INVALID_VALUE);
2384 }
2385
2386 es2::Context *context = es2::getContext();
2387
2388 if(context)
2389 {
2390 es2::Program *programObject = context->getProgram(program);
2391
2392 if(!programObject)
2393 {
2394 if(context->getShader(program))
2395 {
2396 return error(GL_INVALID_OPERATION);
2397 }
2398 else
2399 {
2400 return error(GL_INVALID_VALUE);
2401 }
2402 }
2403
2404 if(index >= programObject->getActiveUniformCount())
2405 {
2406 return error(GL_INVALID_VALUE);
2407 }
2408
2409 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2410 }
2411}
2412
2413void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2414{
2415 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2416 program, maxcount, count, shaders);
2417
2418 if(maxcount < 0)
2419 {
2420 return error(GL_INVALID_VALUE);
2421 }
2422
2423 es2::Context *context = es2::getContext();
2424
2425 if(context)
2426 {
2427 es2::Program *programObject = context->getProgram(program);
2428
2429 if(!programObject)
2430 {
2431 if(context->getShader(program))
2432 {
2433 return error(GL_INVALID_OPERATION);
2434 }
2435 else
2436 {
2437 return error(GL_INVALID_VALUE);
2438 }
2439 }
2440
2441 return programObject->getAttachedShaders(maxcount, count, shaders);
2442 }
2443}
2444
2445int GetAttribLocation(GLuint program, const GLchar* name)
2446{
2447 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2448
2449 es2::Context *context = es2::getContext();
2450
2451 if(context)
2452 {
2453
2454 es2::Program *programObject = context->getProgram(program);
2455
2456 if(!programObject)
2457 {
2458 if(context->getShader(program))
2459 {
2460 return error(GL_INVALID_OPERATION, -1);
2461 }
2462 else
2463 {
2464 return error(GL_INVALID_VALUE, -1);
2465 }
2466 }
2467
2468 if(!programObject->isLinked())
2469 {
2470 return error(GL_INVALID_OPERATION, -1);
2471 }
2472
2473 return programObject->getAttributeLocation(name);
2474 }
2475
2476 return -1;
2477}
2478
2479void GetBooleanv(GLenum pname, GLboolean* params)
2480{
2481 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2482
2483 es2::Context *context = es2::getContext();
2484
2485 if(context)
2486 {
2487 if(!(context->getBooleanv(pname, params)))
2488 {
2489 GLenum nativeType;
2490 unsigned int numParams = 0;
2491 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2492 return error(GL_INVALID_ENUM);
2493
2494 if(numParams == 0)
2495 return; // it is known that the pname is valid, but there are no parameters to return
2496
2497 if(nativeType == GL_FLOAT)
2498 {
2499 GLfloat *floatParams = nullptr;
2500 floatParams = new GLfloat[numParams];
2501
2502 context->getFloatv(pname, floatParams);
2503
2504 for(unsigned int i = 0; i < numParams; ++i)
2505 {
2506 if(floatParams[i] == 0.0f)
2507 params[i] = GL_FALSE;
2508 else
2509 params[i] = GL_TRUE;
2510 }
2511
2512 delete [] floatParams;
2513 }
2514 else if(nativeType == GL_INT)
2515 {
2516 GLint *intParams = nullptr;
2517 intParams = new GLint[numParams];
2518
2519 context->getIntegerv(pname, intParams);
2520
2521 for(unsigned int i = 0; i < numParams; ++i)
2522 {
2523 if(intParams[i] == 0)
2524 params[i] = GL_FALSE;
2525 else
2526 params[i] = GL_TRUE;
2527 }
2528
2529 delete [] intParams;
2530 }
2531 }
2532 }
2533}
2534
2535void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2536{
2537 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2538
2539 es2::Context *context = es2::getContext();
2540
2541 if(context)
2542 {
2543 es2::Buffer *buffer;
2544 if(!context->getBuffer(target, &buffer))
2545 {
2546 return error(GL_INVALID_ENUM);
2547 }
2548
2549 if(!buffer)
2550 {
2551 // A null buffer means that "0" is bound to the requested buffer target
2552 return error(GL_INVALID_OPERATION);
2553 }
2554
2555 GLint clientVersion = context->getClientVersion();
2556
2557 switch(pname)
2558 {
2559 case GL_BUFFER_USAGE:
2560 *params = buffer->usage();
2561 break;
2562 case GL_BUFFER_SIZE:
2563 *params = (GLint)buffer->size();
2564 break;
2565 case GL_BUFFER_ACCESS_FLAGS:
2566 if(clientVersion >= 3)
2567 {
2568 *params = buffer->access();
2569 break;
2570 }
2571 else return error(GL_INVALID_ENUM);
2572 case GL_BUFFER_MAPPED:
2573 if(clientVersion >= 3)
2574 {
2575 *params = buffer->isMapped();
2576 break;
2577 }
2578 else return error(GL_INVALID_ENUM);
2579 case GL_BUFFER_MAP_LENGTH:
2580 if(clientVersion >= 3)
2581 {
2582 *params = (GLint)buffer->length();
2583 break;
2584 }
2585 else return error(GL_INVALID_ENUM);
2586 case GL_BUFFER_MAP_OFFSET:
2587 if(clientVersion >= 3)
2588 {
2589 *params = (GLint)buffer->offset();
2590 break;
2591 }
2592 else return error(GL_INVALID_ENUM);
2593 default:
2594 return error(GL_INVALID_ENUM);
2595 }
2596 }
2597}
2598
2599GLenum GetError(void)
2600{
2601 TRACE("()");
2602
2603 es2::Context *context = es2::getContext();
2604
2605 if(context)
2606 {
2607 return context->getError();
2608 }
2609
2610 return GL_NO_ERROR;
2611}
2612
2613void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2614{
2615 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2616
2617 es2::Context *context = es2::getContext();
2618
2619 if(context)
2620 {
2621 es2::Fence *fenceObject = context->getFence(fence);
2622
2623 if(!fenceObject)
2624 {
2625 return error(GL_INVALID_OPERATION);
2626 }
2627
2628 fenceObject->getFenceiv(pname, params);
2629 }
2630}
2631
2632void GetFloatv(GLenum pname, GLfloat* params)
2633{
2634 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2635
2636 es2::Context *context = es2::getContext();
2637
2638 if(context)
2639 {
2640 if(!(context->getFloatv(pname, params)))
2641 {
2642 GLenum nativeType;
2643 unsigned int numParams = 0;
2644 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2645 return error(GL_INVALID_ENUM);
2646
2647 if(numParams == 0)
2648 return; // it is known that the pname is valid, but that there are no parameters to return.
2649
2650 if(nativeType == GL_BOOL)
2651 {
2652 GLboolean *boolParams = nullptr;
2653 boolParams = new GLboolean[numParams];
2654
2655 context->getBooleanv(pname, boolParams);
2656
2657 for(unsigned int i = 0; i < numParams; ++i)
2658 {
2659 if(boolParams[i] == GL_FALSE)
2660 params[i] = 0.0f;
2661 else
2662 params[i] = 1.0f;
2663 }
2664
2665 delete [] boolParams;
2666 }
2667 else if(nativeType == GL_INT)
2668 {
2669 GLint *intParams = nullptr;
2670 intParams = new GLint[numParams];
2671
2672 context->getIntegerv(pname, intParams);
2673
2674 for(unsigned int i = 0; i < numParams; ++i)
2675 {
2676 params[i] = (GLfloat)intParams[i];
2677 }
2678
2679 delete [] intParams;
2680 }
2681 }
2682 }
2683}
2684
2685void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2686{
2687 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2688 target, attachment, pname, params);
2689
2690 es2::Context *context = es2::getContext();
2691
2692 if(context)
2693 {
2694 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2695 {
2696 return error(GL_INVALID_ENUM);
2697 }
2698
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002699 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002700
Nicolas Capens0bac2852016-05-07 06:09:58 -04002701 if(target == GL_READ_FRAMEBUFFER)
2702 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002703 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002704 }
2705 else
2706 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002707 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002708 }
2709
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002710 GLint clientVersion = context->getClientVersion();
2711
2712 if(framebufferName == 0) // Default framebuffer.
2713 {
2714 if(clientVersion < 3)
2715 {
2716 return error(GL_INVALID_OPERATION);
2717 }
2718 }
2719
Nicolas Capens0bac2852016-05-07 06:09:58 -04002720 switch(attachment)
2721 {
2722 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002723 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002724 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002725 if(clientVersion < 3)
2726 {
2727 return error(GL_INVALID_ENUM);
2728 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002729
2730 if(framebufferName != 0)
2731 {
2732 return error(GL_INVALID_OPERATION);
2733 }
2734 break;
2735 case GL_DEPTH_ATTACHMENT:
2736 case GL_STENCIL_ATTACHMENT:
2737 if(framebufferName == 0)
2738 {
2739 return error(GL_INVALID_OPERATION);
2740 }
2741 break;
2742 case GL_DEPTH_STENCIL_ATTACHMENT:
2743 if(clientVersion < 3)
2744 {
2745 return error(GL_INVALID_ENUM);
2746 }
2747
2748 if(framebufferName == 0)
2749 {
2750 return error(GL_INVALID_OPERATION);
2751 }
2752 break;
2753 default:
2754 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2755 {
2756 if(framebufferName == 0)
2757 {
2758 return error(GL_INVALID_OPERATION);
2759 }
2760 }
2761 else return error(GL_INVALID_ENUM);
2762 }
2763
2764 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2765
2766 GLenum attachmentType;
2767 GLuint attachmentHandle;
2768 GLint attachmentLayer;
2769 Renderbuffer *renderbuffer = nullptr;
2770 switch(attachment)
2771 {
2772 case GL_BACK:
2773 attachmentType = framebuffer->getColorbufferType(0);
2774 attachmentHandle = framebuffer->getColorbufferName(0);
2775 attachmentLayer = framebuffer->getColorbufferLayer(0);
2776 renderbuffer = framebuffer->getColorbuffer(0);
2777 break;
2778 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002779 case GL_DEPTH_ATTACHMENT:
2780 attachmentType = framebuffer->getDepthbufferType();
2781 attachmentHandle = framebuffer->getDepthbufferName();
2782 attachmentLayer = framebuffer->getDepthbufferLayer();
2783 renderbuffer = framebuffer->getDepthbuffer();
2784 break;
2785 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002786 case GL_STENCIL_ATTACHMENT:
2787 attachmentType = framebuffer->getStencilbufferType();
2788 attachmentHandle = framebuffer->getStencilbufferName();
2789 attachmentLayer = framebuffer->getStencilbufferLayer();
2790 renderbuffer = framebuffer->getStencilbuffer();
2791 break;
2792 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002793 attachmentType = framebuffer->getDepthbufferType();
2794 attachmentHandle = framebuffer->getDepthbufferName();
2795 attachmentLayer = framebuffer->getDepthbufferLayer();
2796 renderbuffer = framebuffer->getDepthbuffer();
2797
2798 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002799 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002800 // Different attachments to DEPTH and STENCIL, query fails
2801 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002802 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002803 break;
2804 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002805 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2806 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2807 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2808 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2809 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2810 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002811 }
2812
2813 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002814 if(framebufferName == 0)
2815 {
2816 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2817 }
2818 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002819 {
2820 attachmentObjectType = attachmentType;
2821 }
2822 else if(es2::IsTextureTarget(attachmentType))
2823 {
2824 attachmentObjectType = GL_TEXTURE;
2825 }
2826 else UNREACHABLE(attachmentType);
2827
2828 if(attachmentObjectType != GL_NONE)
2829 {
2830 switch(pname)
2831 {
2832 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2833 *params = attachmentObjectType;
2834 break;
2835 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002836 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002837 {
2838 *params = attachmentHandle;
2839 }
2840 else
2841 {
2842 return error(GL_INVALID_ENUM);
2843 }
2844 break;
2845 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2846 if(attachmentObjectType == GL_TEXTURE)
2847 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002848 *params = clientVersion < 3 ? 0 : renderbuffer->getLevel(); // glFramebufferTexture2D does not allow level to be set to anything else in GL ES 2.0
Nicolas Capens0bac2852016-05-07 06:09:58 -04002849 }
2850 else
2851 {
2852 return error(GL_INVALID_ENUM);
2853 }
2854 break;
2855 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2856 if(attachmentObjectType == GL_TEXTURE)
2857 {
2858 if(es2::IsCubemapTextureTarget(attachmentType))
2859 {
2860 *params = attachmentType;
2861 }
2862 else
2863 {
2864 *params = 0;
2865 }
2866 }
2867 else
2868 {
2869 return error(GL_INVALID_ENUM);
2870 }
2871 break;
2872 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2873 if(clientVersion >= 3)
2874 {
2875 *params = attachmentLayer;
2876 }
2877 else return error(GL_INVALID_ENUM);
2878 break;
2879 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2880 if(clientVersion >= 3)
2881 {
2882 *params = renderbuffer->getRedSize();
2883 }
2884 else return error(GL_INVALID_ENUM);
2885 break;
2886 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2887 if(clientVersion >= 3)
2888 {
2889 *params = renderbuffer->getGreenSize();
2890 }
2891 else return error(GL_INVALID_ENUM);
2892 break;
2893 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2894 if(clientVersion >= 3)
2895 {
2896 *params = renderbuffer->getBlueSize();
2897 }
2898 else return error(GL_INVALID_ENUM);
2899 break;
2900 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2901 if(clientVersion >= 3)
2902 {
2903 *params = renderbuffer->getAlphaSize();
2904 }
2905 else return error(GL_INVALID_ENUM);
2906 break;
2907 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2908 if(clientVersion >= 3)
2909 {
2910 *params = renderbuffer->getDepthSize();
2911 }
2912 else return error(GL_INVALID_ENUM);
2913 break;
2914 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2915 if(clientVersion >= 3)
2916 {
2917 *params = renderbuffer->getStencilSize();
2918 }
2919 else return error(GL_INVALID_ENUM);
2920 break;
2921 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002922 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2923 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002924 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002925 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002926 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002927
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002928 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002929 break;
2930 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2931 if(clientVersion >= 3)
2932 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002933 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002934 }
2935 else return error(GL_INVALID_ENUM);
2936 break;
2937 default:
2938 return error(GL_INVALID_ENUM);
2939 }
2940 }
2941 else
2942 {
2943 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2944 // is NONE, then querying any other pname will generate INVALID_ENUM.
2945
2946 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2947 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2948 // INVALID_OPERATION for all other pnames
2949
2950 switch(pname)
2951 {
2952 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2953 *params = GL_NONE;
2954 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002955 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2956 if(clientVersion < 3)
2957 {
2958 return error(GL_INVALID_ENUM);
2959 }
2960 *params = 0;
2961 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002962 default:
2963 if(clientVersion < 3)
2964 {
2965 return error(GL_INVALID_ENUM);
2966 }
2967 else
2968 {
2969 return error(GL_INVALID_OPERATION);
2970 }
2971 }
2972 }
2973 }
2974}
2975
2976GLenum GetGraphicsResetStatusEXT(void)
2977{
2978 TRACE("()");
2979
2980 return GL_NO_ERROR;
2981}
2982
2983void GetIntegerv(GLenum pname, GLint* params)
2984{
2985 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2986
2987 es2::Context *context = es2::getContext();
2988
2989 if(!context)
2990 {
2991 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2992 #ifdef __ANDROID__
2993 ALOGI("expected_badness glGetIntegerv() called without current context.");
2994 #else
2995 ERR("glGetIntegerv() called without current context.");
2996 #endif
2997
2998 // This is not spec compliant! When there is no current GL context, functions should
2999 // have no side effects. Google Maps queries these values before creating a context,
3000 // so we need this as a bug-compatible workaround.
3001 switch(pname)
3002 {
3003 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3004 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3005 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3006 case GL_STENCIL_BITS: *params = 8; return;
3007 case GL_ALIASED_LINE_WIDTH_RANGE:
3008 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3009 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3010 return;
3011 }
3012 }
3013
3014 if(context)
3015 {
3016 if(!(context->getIntegerv(pname, params)))
3017 {
3018 GLenum nativeType;
3019 unsigned int numParams = 0;
3020 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3021 return error(GL_INVALID_ENUM);
3022
3023 if(numParams == 0)
3024 return; // it is known that pname is valid, but there are no parameters to return
3025
3026 if(nativeType == GL_BOOL)
3027 {
3028 GLboolean *boolParams = nullptr;
3029 boolParams = new GLboolean[numParams];
3030
3031 context->getBooleanv(pname, boolParams);
3032
3033 for(unsigned int i = 0; i < numParams; ++i)
3034 {
3035 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3036 }
3037
3038 delete [] boolParams;
3039 }
3040 else if(nativeType == GL_FLOAT)
3041 {
3042 GLfloat *floatParams = nullptr;
3043 floatParams = new GLfloat[numParams];
3044
3045 context->getFloatv(pname, floatParams);
3046
3047 for(unsigned int i = 0; i < numParams; ++i)
3048 {
3049 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3050 {
Alexis Hetu60e20282017-12-13 07:42:22 -05003051 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003052 }
3053 else
3054 {
3055 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3056 }
3057 }
3058
3059 delete [] floatParams;
3060 }
3061 }
3062 }
3063}
3064
3065void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3066{
3067 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3068
3069 es2::Context *context = es2::getContext();
3070
3071 if(context)
3072 {
3073 es2::Program *programObject = context->getProgram(program);
3074
3075 if(!programObject)
3076 {
3077 if(context->getShader(program))
3078 {
3079 return error(GL_INVALID_OPERATION);
3080 }
3081 else
3082 {
3083 return error(GL_INVALID_VALUE);
3084 }
3085 }
3086
3087 GLint clientVersion = egl::getClientVersion();
3088
3089 switch(pname)
3090 {
3091 case GL_DELETE_STATUS:
3092 *params = programObject->isFlaggedForDeletion();
3093 return;
3094 case GL_LINK_STATUS:
3095 *params = programObject->isLinked();
3096 return;
3097 case GL_VALIDATE_STATUS:
3098 *params = programObject->isValidated();
3099 return;
3100 case GL_INFO_LOG_LENGTH:
3101 *params = (GLint)programObject->getInfoLogLength();
3102 return;
3103 case GL_ATTACHED_SHADERS:
3104 *params = programObject->getAttachedShadersCount();
3105 return;
3106 case GL_ACTIVE_ATTRIBUTES:
3107 *params = (GLint)programObject->getActiveAttributeCount();
3108 return;
3109 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3110 *params = programObject->getActiveAttributeMaxLength();
3111 return;
3112 case GL_ACTIVE_UNIFORMS:
3113 *params = (GLint)programObject->getActiveUniformCount();
3114 return;
3115 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3116 *params = programObject->getActiveUniformMaxLength();
3117 return;
3118 case GL_ACTIVE_UNIFORM_BLOCKS:
3119 if(clientVersion >= 3)
3120 {
3121 *params = (GLint)programObject->getActiveUniformBlockCount();
3122 return;
3123 }
3124 else return error(GL_INVALID_ENUM);
3125 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3126 if(clientVersion >= 3)
3127 {
3128 *params = programObject->getActiveUniformBlockMaxLength();
3129 return;
3130 }
3131 else return error(GL_INVALID_ENUM);
3132 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3133 if(clientVersion >= 3)
3134 {
3135 *params = programObject->getTransformFeedbackBufferMode();
3136 return;
3137 }
3138 else return error(GL_INVALID_ENUM);
3139 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3140 if(clientVersion >= 3)
3141 {
3142 *params = programObject->getTransformFeedbackVaryingCount();
3143 return;
3144 }
3145 else return error(GL_INVALID_ENUM);
3146 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3147 if(clientVersion >= 3)
3148 {
3149 *params = programObject->getTransformFeedbackVaryingMaxLength();
3150 return;
3151 }
3152 else return error(GL_INVALID_ENUM);
3153 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3154 if(clientVersion >= 3)
3155 {
3156 *params = programObject->getBinaryRetrievableHint();
3157 return;
3158 }
3159 else return error(GL_INVALID_ENUM);
3160 case GL_PROGRAM_BINARY_LENGTH:
3161 if(clientVersion >= 3)
3162 {
3163 *params = programObject->getBinaryLength();
3164 return;
3165 }
3166 else return error(GL_INVALID_ENUM);
3167 default:
3168 return error(GL_INVALID_ENUM);
3169 }
3170 }
3171}
3172
3173void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3174{
3175 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3176 program, bufsize, length, infolog);
3177
3178 if(bufsize < 0)
3179 {
3180 return error(GL_INVALID_VALUE);
3181 }
3182
3183 es2::Context *context = es2::getContext();
3184
3185 if(context)
3186 {
3187 es2::Program *programObject = context->getProgram(program);
3188
3189 if(!programObject)
3190 {
3191 if(context->getShader(program))
3192 {
3193 return error(GL_INVALID_OPERATION);
3194 }
3195 else
3196 {
3197 return error(GL_INVALID_VALUE);
3198 }
3199 }
3200
3201 programObject->getInfoLog(bufsize, length, infolog);
3202 }
3203}
3204
3205void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3206{
3207 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3208
3209 switch(pname)
3210 {
3211 case GL_CURRENT_QUERY_EXT:
3212 break;
3213 default:
3214 return error(GL_INVALID_ENUM);
3215 }
3216
3217 es2::Context *context = es2::getContext();
3218
3219 if(context)
3220 {
3221 params[0] = context->getActiveQuery(target);
3222 }
3223}
3224
3225void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3226{
3227 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3228
3229 switch(pname)
3230 {
3231 case GL_QUERY_RESULT_EXT:
3232 case GL_QUERY_RESULT_AVAILABLE_EXT:
3233 break;
3234 default:
3235 return error(GL_INVALID_ENUM);
3236 }
3237
3238 es2::Context *context = es2::getContext();
3239
3240 if(context)
3241 {
3242 es2::Query *queryObject = context->getQuery(name);
3243
3244 if(!queryObject)
3245 {
3246 return error(GL_INVALID_OPERATION);
3247 }
3248
3249 if(context->getActiveQuery(queryObject->getType()) == name)
3250 {
3251 return error(GL_INVALID_OPERATION);
3252 }
3253
3254 switch(pname)
3255 {
3256 case GL_QUERY_RESULT_EXT:
3257 params[0] = queryObject->getResult();
3258 break;
3259 case GL_QUERY_RESULT_AVAILABLE_EXT:
3260 params[0] = queryObject->isResultAvailable();
3261 break;
3262 default:
3263 ASSERT(false);
3264 }
3265 }
3266}
3267
3268void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3269{
3270 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3271
3272 es2::Context *context = es2::getContext();
3273
3274 if(context)
3275 {
3276 if(target != GL_RENDERBUFFER)
3277 {
3278 return error(GL_INVALID_ENUM);
3279 }
3280
3281 if(context->getRenderbufferName() == 0)
3282 {
3283 return error(GL_INVALID_OPERATION);
3284 }
3285
3286 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3287
3288 switch(pname)
3289 {
3290 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3291 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003292 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3293 {
3294 GLint internalformat = renderbuffer->getFormat();
3295 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3296 }
3297 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003298 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3299 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3300 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3301 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3302 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3303 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003304 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003305 default:
3306 return error(GL_INVALID_ENUM);
3307 }
3308 }
3309}
3310
3311void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3312{
3313 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3314
3315 es2::Context *context = es2::getContext();
3316
3317 if(context)
3318 {
3319 es2::Shader *shaderObject = context->getShader(shader);
3320
3321 if(!shaderObject)
3322 {
3323 if(context->getProgram(shader))
3324 {
3325 return error(GL_INVALID_OPERATION);
3326 }
3327 else
3328 {
3329 return error(GL_INVALID_VALUE);
3330 }
3331 }
3332
3333 switch(pname)
3334 {
3335 case GL_SHADER_TYPE:
3336 *params = shaderObject->getType();
3337 return;
3338 case GL_DELETE_STATUS:
3339 *params = shaderObject->isFlaggedForDeletion();
3340 return;
3341 case GL_COMPILE_STATUS:
3342 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3343 return;
3344 case GL_INFO_LOG_LENGTH:
3345 *params = (GLint)shaderObject->getInfoLogLength();
3346 return;
3347 case GL_SHADER_SOURCE_LENGTH:
3348 *params = (GLint)shaderObject->getSourceLength();
3349 return;
3350 default:
3351 return error(GL_INVALID_ENUM);
3352 }
3353 }
3354}
3355
3356void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3357{
3358 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3359 shader, bufsize, length, infolog);
3360
3361 if(bufsize < 0)
3362 {
3363 return error(GL_INVALID_VALUE);
3364 }
3365
3366 es2::Context *context = es2::getContext();
3367
3368 if(context)
3369 {
3370 es2::Shader *shaderObject = context->getShader(shader);
3371
3372 if(!shaderObject)
3373 {
3374 if(context->getProgram(shader))
3375 {
3376 return error(GL_INVALID_OPERATION);
3377 }
3378 else
3379 {
3380 return error(GL_INVALID_VALUE);
3381 }
3382 }
3383
3384 shaderObject->getInfoLog(bufsize, length, infolog);
3385 }
3386}
3387
3388void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3389{
3390 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3391 shadertype, precisiontype, range, precision);
3392
3393 switch(shadertype)
3394 {
3395 case GL_VERTEX_SHADER:
3396 case GL_FRAGMENT_SHADER:
3397 break;
3398 default:
3399 return error(GL_INVALID_ENUM);
3400 }
3401
3402 switch(precisiontype)
3403 {
3404 case GL_LOW_FLOAT:
3405 case GL_MEDIUM_FLOAT:
3406 case GL_HIGH_FLOAT:
3407 // IEEE 754 single-precision
3408 range[0] = 127;
3409 range[1] = 127;
3410 *precision = 23;
3411 break;
3412 case GL_LOW_INT:
3413 case GL_MEDIUM_INT:
3414 case GL_HIGH_INT:
3415 // Full integer precision is supported
3416 range[0] = 31;
3417 range[1] = 30;
3418 *precision = 0;
3419 break;
3420 default:
3421 return error(GL_INVALID_ENUM);
3422 }
3423}
3424
3425void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3426{
3427 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3428 shader, bufsize, length, source);
3429
3430 if(bufsize < 0)
3431 {
3432 return error(GL_INVALID_VALUE);
3433 }
3434
3435 es2::Context *context = es2::getContext();
3436
3437 if(context)
3438 {
3439 es2::Shader *shaderObject = context->getShader(shader);
3440
3441 if(!shaderObject)
3442 {
3443 if(context->getProgram(shader))
3444 {
3445 return error(GL_INVALID_OPERATION);
3446 }
3447 else
3448 {
3449 return error(GL_INVALID_VALUE);
3450 }
3451 }
3452
3453 shaderObject->getSource(bufsize, length, source);
3454 }
3455}
3456
3457const GLubyte* GetString(GLenum name)
3458{
3459 TRACE("(GLenum name = 0x%X)", name);
3460
3461 switch(name)
3462 {
3463 case GL_VENDOR:
3464 return (GLubyte*)"Google Inc.";
3465 case GL_RENDERER:
3466 return (GLubyte*)"Google SwiftShader";
3467 case GL_VERSION:
3468 {
3469 es2::Context *context = es2::getContext();
3470 return (context && (context->getClientVersion() >= 3)) ?
3471 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3472 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3473 }
3474 case GL_SHADING_LANGUAGE_VERSION:
3475 {
3476 es2::Context *context = es2::getContext();
3477 return (context && (context->getClientVersion() >= 3)) ?
3478 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3479 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3480 }
3481 case GL_EXTENSIONS:
3482 {
3483 es2::Context *context = es2::getContext();
3484 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3485 }
3486 default:
3487 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3488 }
3489}
3490
3491void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3492{
3493 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3494
3495 es2::Context *context = es2::getContext();
3496
3497 if(context)
3498 {
3499 es2::Texture *texture;
3500
3501 GLint clientVersion = context->getClientVersion();
3502
3503 switch(target)
3504 {
3505 case GL_TEXTURE_2D:
3506 texture = context->getTexture2D();
3507 break;
3508 case GL_TEXTURE_CUBE_MAP:
3509 texture = context->getTextureCubeMap();
3510 break;
3511 case GL_TEXTURE_EXTERNAL_OES:
3512 texture = context->getTextureExternal();
3513 break;
3514 case GL_TEXTURE_2D_ARRAY:
3515 if(clientVersion < 3)
3516 {
3517 return error(GL_INVALID_ENUM);
3518 }
3519 else
3520 {
3521 texture = context->getTexture2DArray();
3522 }
3523 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003524 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003525 texture = context->getTexture3D();
3526 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003527 case GL_TEXTURE_RECTANGLE_ARB:
3528 texture = context->getTexture2DRect();
3529 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003530 default:
3531 return error(GL_INVALID_ENUM);
3532 }
3533
3534 switch(pname)
3535 {
3536 case GL_TEXTURE_MAG_FILTER:
3537 *params = (GLfloat)texture->getMagFilter();
3538 break;
3539 case GL_TEXTURE_MIN_FILTER:
3540 *params = (GLfloat)texture->getMinFilter();
3541 break;
3542 case GL_TEXTURE_WRAP_S:
3543 *params = (GLfloat)texture->getWrapS();
3544 break;
3545 case GL_TEXTURE_WRAP_T:
3546 *params = (GLfloat)texture->getWrapT();
3547 break;
3548 case GL_TEXTURE_WRAP_R_OES:
3549 *params = (GLfloat)texture->getWrapR();
3550 break;
3551 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3552 *params = texture->getMaxAnisotropy();
3553 break;
3554 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3555 *params = (GLfloat)1;
3556 break;
3557 case GL_TEXTURE_BASE_LEVEL:
3558 if(clientVersion >= 3)
3559 {
3560 *params = (GLfloat)texture->getBaseLevel();
3561 break;
3562 }
3563 else return error(GL_INVALID_ENUM);
3564 case GL_TEXTURE_COMPARE_FUNC:
3565 if(clientVersion >= 3)
3566 {
3567 *params = (GLfloat)texture->getCompareFunc();
3568 break;
3569 }
3570 else return error(GL_INVALID_ENUM);
3571 case GL_TEXTURE_COMPARE_MODE:
3572 if(clientVersion >= 3)
3573 {
3574 *params = (GLfloat)texture->getCompareMode();
3575 break;
3576 }
3577 else return error(GL_INVALID_ENUM);
3578 case GL_TEXTURE_IMMUTABLE_FORMAT:
3579 if(clientVersion >= 3)
3580 {
3581 *params = (GLfloat)texture->getImmutableFormat();
3582 break;
3583 }
3584 else return error(GL_INVALID_ENUM);
3585 case GL_TEXTURE_IMMUTABLE_LEVELS:
3586 if(clientVersion >= 3)
3587 {
3588 *params = (GLfloat)texture->getImmutableLevels();
3589 break;
3590 }
3591 else return error(GL_INVALID_ENUM);
3592 case GL_TEXTURE_MAX_LEVEL:
3593 if(clientVersion >= 3)
3594 {
3595 *params = (GLfloat)texture->getMaxLevel();
3596 break;
3597 }
3598 else return error(GL_INVALID_ENUM);
3599 case GL_TEXTURE_MAX_LOD:
3600 if(clientVersion >= 3)
3601 {
3602 *params = texture->getMaxLOD();
3603 break;
3604 }
3605 else return error(GL_INVALID_ENUM);
3606 case GL_TEXTURE_MIN_LOD:
3607 if(clientVersion >= 3)
3608 {
3609 *params = texture->getMinLOD();
3610 break;
3611 }
3612 else return error(GL_INVALID_ENUM);
3613 case GL_TEXTURE_SWIZZLE_R:
3614 if(clientVersion >= 3)
3615 {
3616 *params = (GLfloat)texture->getSwizzleR();
3617 break;
3618 }
3619 else return error(GL_INVALID_ENUM);
3620 case GL_TEXTURE_SWIZZLE_G:
3621 if(clientVersion >= 3)
3622 {
3623 *params = (GLfloat)texture->getSwizzleG();
3624 break;
3625 }
3626 else return error(GL_INVALID_ENUM);
3627 case GL_TEXTURE_SWIZZLE_B:
3628 if(clientVersion >= 3)
3629 {
3630 *params = (GLfloat)texture->getSwizzleB();
3631 break;
3632 }
3633 else return error(GL_INVALID_ENUM);
3634 case GL_TEXTURE_SWIZZLE_A:
3635 if(clientVersion >= 3)
3636 {
3637 *params = (GLfloat)texture->getSwizzleA();
3638 break;
3639 }
3640 else return error(GL_INVALID_ENUM);
3641 default:
3642 return error(GL_INVALID_ENUM);
3643 }
3644 }
3645}
3646
3647void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3648{
3649 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3650
3651 es2::Context *context = es2::getContext();
3652
3653 if(context)
3654 {
3655 es2::Texture *texture;
3656
3657 GLint clientVersion = context->getClientVersion();
3658
3659 switch(target)
3660 {
3661 case GL_TEXTURE_2D:
3662 texture = context->getTexture2D();
3663 break;
3664 case GL_TEXTURE_CUBE_MAP:
3665 texture = context->getTextureCubeMap();
3666 break;
3667 case GL_TEXTURE_EXTERNAL_OES:
3668 texture = context->getTextureExternal();
3669 break;
3670 case GL_TEXTURE_2D_ARRAY:
3671 if(clientVersion < 3)
3672 {
3673 return error(GL_INVALID_ENUM);
3674 }
3675 else
3676 {
3677 texture = context->getTexture2DArray();
3678 }
3679 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003680 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003681 texture = context->getTexture3D();
3682 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003683 case GL_TEXTURE_RECTANGLE_ARB:
3684 texture = context->getTexture2DRect();
3685 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003686 default:
3687 return error(GL_INVALID_ENUM);
3688 }
3689
3690 switch(pname)
3691 {
3692 case GL_TEXTURE_MAG_FILTER:
3693 *params = texture->getMagFilter();
3694 break;
3695 case GL_TEXTURE_MIN_FILTER:
3696 *params = texture->getMinFilter();
3697 break;
3698 case GL_TEXTURE_WRAP_S:
3699 *params = texture->getWrapS();
3700 break;
3701 case GL_TEXTURE_WRAP_T:
3702 *params = texture->getWrapT();
3703 break;
3704 case GL_TEXTURE_WRAP_R_OES:
3705 *params = texture->getWrapR();
3706 break;
3707 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3708 *params = (GLint)texture->getMaxAnisotropy();
3709 break;
3710 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3711 *params = 1;
3712 break;
3713 case GL_TEXTURE_BASE_LEVEL:
3714 if(clientVersion >= 3)
3715 {
3716 *params = texture->getBaseLevel();
3717 break;
3718 }
3719 else return error(GL_INVALID_ENUM);
3720 case GL_TEXTURE_COMPARE_FUNC:
3721 if(clientVersion >= 3)
3722 {
3723 *params = (GLint)texture->getCompareFunc();
3724 break;
3725 }
3726 else return error(GL_INVALID_ENUM);
3727 case GL_TEXTURE_COMPARE_MODE:
3728 if(clientVersion >= 3)
3729 {
3730 *params = (GLint)texture->getCompareMode();
3731 break;
3732 }
3733 else return error(GL_INVALID_ENUM);
3734 case GL_TEXTURE_IMMUTABLE_FORMAT:
3735 if(clientVersion >= 3)
3736 {
3737 *params = (GLint)texture->getImmutableFormat();
3738 break;
3739 }
3740 else return error(GL_INVALID_ENUM);
3741 case GL_TEXTURE_IMMUTABLE_LEVELS:
3742 if(clientVersion >= 3)
3743 {
3744 *params = (GLint)texture->getImmutableLevels();
3745 break;
3746 }
3747 else return error(GL_INVALID_ENUM);
3748 case GL_TEXTURE_MAX_LEVEL:
3749 if(clientVersion >= 3)
3750 {
3751 *params = texture->getMaxLevel();
3752 break;
3753 }
3754 else return error(GL_INVALID_ENUM);
3755 case GL_TEXTURE_MAX_LOD:
3756 if(clientVersion >= 3)
3757 {
3758 *params = (GLint)roundf(texture->getMaxLOD());
3759 break;
3760 }
3761 else return error(GL_INVALID_ENUM);
3762 case GL_TEXTURE_MIN_LOD:
3763 if(clientVersion >= 3)
3764 {
3765 *params = (GLint)roundf(texture->getMinLOD());
3766 break;
3767 }
3768 else return error(GL_INVALID_ENUM);
3769 case GL_TEXTURE_SWIZZLE_R:
3770 if(clientVersion >= 3)
3771 {
3772 *params = (GLint)texture->getSwizzleR();
3773 break;
3774 }
3775 else return error(GL_INVALID_ENUM);
3776 case GL_TEXTURE_SWIZZLE_G:
3777 if(clientVersion >= 3)
3778 {
3779 *params = (GLint)texture->getSwizzleG();
3780 break;
3781 }
3782 else return error(GL_INVALID_ENUM);
3783 case GL_TEXTURE_SWIZZLE_B:
3784 if(clientVersion >= 3)
3785 {
3786 *params = (GLint)texture->getSwizzleB();
3787 break;
3788 }
3789 else return error(GL_INVALID_ENUM);
3790 case GL_TEXTURE_SWIZZLE_A:
3791 if(clientVersion >= 3)
3792 {
3793 *params = (GLint)texture->getSwizzleA();
3794 break;
3795 }
3796 else return error(GL_INVALID_ENUM);
3797 default:
3798 return error(GL_INVALID_ENUM);
3799 }
3800 }
3801}
3802
3803void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3804{
3805 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3806 program, location, bufSize, params);
3807
3808 if(bufSize < 0)
3809 {
3810 return error(GL_INVALID_VALUE);
3811 }
3812
3813 es2::Context *context = es2::getContext();
3814
3815 if(context)
3816 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003817 es2::Program *programObject = context->getProgram(program);
3818
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003819 if(!programObject)
3820 {
3821 if(context->getShader(program))
3822 {
3823 return error(GL_INVALID_OPERATION);
3824 }
3825 else
3826 {
3827 return error(GL_INVALID_VALUE);
3828 }
3829 }
3830
3831 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003832 {
3833 return error(GL_INVALID_OPERATION);
3834 }
3835
3836 if(!programObject->getUniformfv(location, &bufSize, params))
3837 {
3838 return error(GL_INVALID_OPERATION);
3839 }
3840 }
3841}
3842
3843void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3844{
3845 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3846
3847 es2::Context *context = es2::getContext();
3848
3849 if(context)
3850 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003851 es2::Program *programObject = context->getProgram(program);
3852
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003853 if(!programObject)
3854 {
3855 if(context->getShader(program))
3856 {
3857 return error(GL_INVALID_OPERATION);
3858 }
3859 else
3860 {
3861 return error(GL_INVALID_VALUE);
3862 }
3863 }
3864
3865 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003866 {
3867 return error(GL_INVALID_OPERATION);
3868 }
3869
3870 if(!programObject->getUniformfv(location, nullptr, params))
3871 {
3872 return error(GL_INVALID_OPERATION);
3873 }
3874 }
3875}
3876
3877void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3878{
3879 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3880 program, location, bufSize, params);
3881
3882 if(bufSize < 0)
3883 {
3884 return error(GL_INVALID_VALUE);
3885 }
3886
3887 es2::Context *context = es2::getContext();
3888
3889 if(context)
3890 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003891 es2::Program *programObject = context->getProgram(program);
3892
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003893 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003894 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003895 if(context->getShader(program))
3896 {
3897 return error(GL_INVALID_OPERATION);
3898 }
3899 else
3900 {
3901 return error(GL_INVALID_VALUE);
3902 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003903 }
3904
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003905 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003906 {
3907 return error(GL_INVALID_OPERATION);
3908 }
3909
3910 if(!programObject->getUniformiv(location, &bufSize, params))
3911 {
3912 return error(GL_INVALID_OPERATION);
3913 }
3914 }
3915}
3916
3917void GetUniformiv(GLuint program, GLint location, GLint* params)
3918{
3919 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3920
3921 es2::Context *context = es2::getContext();
3922
3923 if(context)
3924 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003925 es2::Program *programObject = context->getProgram(program);
3926
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003927 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003928 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003929 if(context->getShader(program))
3930 {
3931 return error(GL_INVALID_OPERATION);
3932 }
3933 else
3934 {
3935 return error(GL_INVALID_VALUE);
3936 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003937 }
3938
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003939 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003940 {
3941 return error(GL_INVALID_OPERATION);
3942 }
3943
3944 if(!programObject->getUniformiv(location, nullptr, params))
3945 {
3946 return error(GL_INVALID_OPERATION);
3947 }
3948 }
3949}
3950
3951int GetUniformLocation(GLuint program, const GLchar* name)
3952{
3953 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3954
3955 es2::Context *context = es2::getContext();
3956
3957 if(strstr(name, "gl_") == name)
3958 {
3959 return -1;
3960 }
3961
3962 if(context)
3963 {
3964 es2::Program *programObject = context->getProgram(program);
3965
3966 if(!programObject)
3967 {
3968 if(context->getShader(program))
3969 {
3970 return error(GL_INVALID_OPERATION, -1);
3971 }
3972 else
3973 {
3974 return error(GL_INVALID_VALUE, -1);
3975 }
3976 }
3977
3978 if(!programObject->isLinked())
3979 {
3980 return error(GL_INVALID_OPERATION, -1);
3981 }
3982
3983 return programObject->getUniformLocation(name);
3984 }
3985
3986 return -1;
3987}
3988
3989void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3990{
3991 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3992
3993 es2::Context *context = es2::getContext();
3994
3995 if(context)
3996 {
3997 if(index >= es2::MAX_VERTEX_ATTRIBS)
3998 {
3999 return error(GL_INVALID_VALUE);
4000 }
4001
4002 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4003
4004 GLint clientVersion = context->getClientVersion();
4005
4006 switch(pname)
4007 {
4008 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4009 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4010 break;
4011 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4012 *params = (GLfloat)attribState.mSize;
4013 break;
4014 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4015 *params = (GLfloat)attribState.mStride;
4016 break;
4017 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4018 *params = (GLfloat)attribState.mType;
4019 break;
4020 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4021 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4022 break;
4023 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4024 *params = (GLfloat)attribState.mBoundBuffer.name();
4025 break;
4026 case GL_CURRENT_VERTEX_ATTRIB:
4027 {
4028 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4029 for(int i = 0; i < 4; ++i)
4030 {
4031 params[i] = attrib.getCurrentValueF(i);
4032 }
4033 }
4034 break;
4035 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4036 if(clientVersion >= 3)
4037 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004038 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004039 break;
4040 }
4041 else return error(GL_INVALID_ENUM);
4042 default: return error(GL_INVALID_ENUM);
4043 }
4044 }
4045}
4046
4047void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4048{
4049 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4050
4051 es2::Context *context = es2::getContext();
4052
4053 if(context)
4054 {
4055 if(index >= es2::MAX_VERTEX_ATTRIBS)
4056 {
4057 return error(GL_INVALID_VALUE);
4058 }
4059
4060 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4061
4062 GLint clientVersion = context->getClientVersion();
4063
4064 switch(pname)
4065 {
4066 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4067 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4068 break;
4069 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4070 *params = attribState.mSize;
4071 break;
4072 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4073 *params = attribState.mStride;
4074 break;
4075 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4076 *params = attribState.mType;
4077 break;
4078 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4079 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4080 break;
4081 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4082 *params = attribState.mBoundBuffer.name();
4083 break;
4084 case GL_CURRENT_VERTEX_ATTRIB:
4085 {
4086 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4087 for(int i = 0; i < 4; ++i)
4088 {
4089 float currentValue = attrib.getCurrentValueF(i);
4090 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4091 }
4092 }
4093 break;
4094 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4095 if(clientVersion >= 3)
4096 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004097 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004098 break;
4099 }
4100 else return error(GL_INVALID_ENUM);
4101 default: return error(GL_INVALID_ENUM);
4102 }
4103 }
4104}
4105
4106void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4107{
4108 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4109
4110 es2::Context *context = es2::getContext();
4111
4112 if(context)
4113 {
4114 if(index >= es2::MAX_VERTEX_ATTRIBS)
4115 {
4116 return error(GL_INVALID_VALUE);
4117 }
4118
4119 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4120 {
4121 return error(GL_INVALID_ENUM);
4122 }
4123
4124 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4125 }
4126}
4127
4128void Hint(GLenum target, GLenum mode)
4129{
4130 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4131
4132 switch(mode)
4133 {
4134 case GL_FASTEST:
4135 case GL_NICEST:
4136 case GL_DONT_CARE:
4137 break;
4138 default:
4139 return error(GL_INVALID_ENUM);
4140 }
4141
4142 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004143
4144 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004145 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004146 switch(target)
4147 {
4148 case GL_GENERATE_MIPMAP_HINT:
4149 context->setGenerateMipmapHint(mode);
4150 break;
4151 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4152 context->setFragmentShaderDerivativeHint(mode);
4153 break;
4154 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4155 context->setTextureFilteringHint(mode);
4156 break;
4157 default:
4158 return error(GL_INVALID_ENUM);
4159 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004160 }
4161}
4162
4163GLboolean IsBuffer(GLuint buffer)
4164{
4165 TRACE("(GLuint buffer = %d)", buffer);
4166
4167 es2::Context *context = es2::getContext();
4168
4169 if(context && buffer)
4170 {
4171 es2::Buffer *bufferObject = context->getBuffer(buffer);
4172
4173 if(bufferObject)
4174 {
4175 return GL_TRUE;
4176 }
4177 }
4178
4179 return GL_FALSE;
4180}
4181
4182GLboolean IsEnabled(GLenum cap)
4183{
4184 TRACE("(GLenum cap = 0x%X)", cap);
4185
4186 es2::Context *context = es2::getContext();
4187
4188 if(context)
4189 {
4190 GLint clientVersion = context->getClientVersion();
4191
4192 switch(cap)
4193 {
4194 case GL_CULL_FACE: return context->isCullFaceEnabled();
4195 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4196 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4197 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4198 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4199 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4200 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4201 case GL_BLEND: return context->isBlendEnabled();
4202 case GL_DITHER: return context->isDitherEnabled();
4203 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4204 if(clientVersion >= 3)
4205 {
4206 return context->isPrimitiveRestartFixedIndexEnabled();
4207 }
4208 else return error(GL_INVALID_ENUM, false);
4209 case GL_RASTERIZER_DISCARD:
4210 if(clientVersion >= 3)
4211 {
4212 return context->isRasterizerDiscardEnabled();
4213 }
4214 else return error(GL_INVALID_ENUM, false);
4215 default:
4216 return error(GL_INVALID_ENUM, false);
4217 }
4218 }
4219
4220 return false;
4221}
4222
4223GLboolean IsFenceNV(GLuint fence)
4224{
4225 TRACE("(GLuint fence = %d)", fence);
4226
4227 es2::Context *context = es2::getContext();
4228
4229 if(context)
4230 {
4231 es2::Fence *fenceObject = context->getFence(fence);
4232
4233 if(!fenceObject)
4234 {
4235 return GL_FALSE;
4236 }
4237
4238 return fenceObject->isFence();
4239 }
4240
4241 return GL_FALSE;
4242}
4243
4244GLboolean IsFramebuffer(GLuint framebuffer)
4245{
4246 TRACE("(GLuint framebuffer = %d)", framebuffer);
4247
4248 es2::Context *context = es2::getContext();
4249
4250 if(context && framebuffer)
4251 {
4252 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4253
4254 if(framebufferObject)
4255 {
4256 return GL_TRUE;
4257 }
4258 }
4259
4260 return GL_FALSE;
4261}
4262
4263GLboolean IsProgram(GLuint program)
4264{
4265 TRACE("(GLuint program = %d)", program);
4266
4267 es2::Context *context = es2::getContext();
4268
4269 if(context && program)
4270 {
4271 es2::Program *programObject = context->getProgram(program);
4272
4273 if(programObject)
4274 {
4275 return GL_TRUE;
4276 }
4277 }
4278
4279 return GL_FALSE;
4280}
4281
4282GLboolean IsQueryEXT(GLuint name)
4283{
4284 TRACE("(GLuint name = %d)", name);
4285
4286 if(name == 0)
4287 {
4288 return GL_FALSE;
4289 }
4290
4291 es2::Context *context = es2::getContext();
4292
4293 if(context)
4294 {
4295 es2::Query *queryObject = context->getQuery(name);
4296
4297 if(queryObject)
4298 {
4299 return GL_TRUE;
4300 }
4301 }
4302
4303 return GL_FALSE;
4304}
4305
4306GLboolean IsRenderbuffer(GLuint renderbuffer)
4307{
4308 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4309
4310 es2::Context *context = es2::getContext();
4311
4312 if(context && renderbuffer)
4313 {
4314 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4315
4316 if(renderbufferObject)
4317 {
4318 return GL_TRUE;
4319 }
4320 }
4321
4322 return GL_FALSE;
4323}
4324
4325GLboolean IsShader(GLuint shader)
4326{
4327 TRACE("(GLuint shader = %d)", shader);
4328
4329 es2::Context *context = es2::getContext();
4330
4331 if(context && shader)
4332 {
4333 es2::Shader *shaderObject = context->getShader(shader);
4334
4335 if(shaderObject)
4336 {
4337 return GL_TRUE;
4338 }
4339 }
4340
4341 return GL_FALSE;
4342}
4343
4344GLboolean IsTexture(GLuint texture)
4345{
4346 TRACE("(GLuint texture = %d)", texture);
4347
4348 es2::Context *context = es2::getContext();
4349
4350 if(context && texture)
4351 {
4352 es2::Texture *textureObject = context->getTexture(texture);
4353
4354 if(textureObject)
4355 {
4356 return GL_TRUE;
4357 }
4358 }
4359
4360 return GL_FALSE;
4361}
4362
4363void LineWidth(GLfloat width)
4364{
4365 TRACE("(GLfloat width = %f)", width);
4366
4367 if(width <= 0.0f)
4368 {
4369 return error(GL_INVALID_VALUE);
4370 }
4371
4372 es2::Context *context = es2::getContext();
4373
4374 if(context)
4375 {
4376 context->setLineWidth(width);
4377 }
4378}
4379
4380void LinkProgram(GLuint program)
4381{
4382 TRACE("(GLuint program = %d)", program);
4383
4384 es2::Context *context = es2::getContext();
4385
4386 if(context)
4387 {
4388 es2::Program *programObject = context->getProgram(program);
4389
4390 if(!programObject)
4391 {
4392 if(context->getShader(program))
4393 {
4394 return error(GL_INVALID_OPERATION);
4395 }
4396 else
4397 {
4398 return error(GL_INVALID_VALUE);
4399 }
4400 }
4401
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004402 if(programObject == context->getCurrentProgram())
4403 {
4404 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4405 if(transformFeedback && transformFeedback->isActive())
4406 {
4407 return error(GL_INVALID_OPERATION);
4408 }
4409 }
4410
Nicolas Capens0bac2852016-05-07 06:09:58 -04004411 programObject->link();
4412 }
4413}
4414
4415void PixelStorei(GLenum pname, GLint param)
4416{
4417 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4418
4419 es2::Context *context = es2::getContext();
4420
4421 if(context)
4422 {
4423 GLint clientVersion = context->getClientVersion();
4424
4425 switch(pname)
4426 {
4427 case GL_UNPACK_ALIGNMENT:
4428 if(param != 1 && param != 2 && param != 4 && param != 8)
4429 {
4430 return error(GL_INVALID_VALUE);
4431 }
4432 context->setUnpackAlignment(param);
4433 break;
4434 case GL_PACK_ALIGNMENT:
4435 if(param != 1 && param != 2 && param != 4 && param != 8)
4436 {
4437 return error(GL_INVALID_VALUE);
4438 }
4439 context->setPackAlignment(param);
4440 break;
4441 case GL_PACK_ROW_LENGTH:
4442 if(clientVersion >= 3)
4443 {
4444 if(param < 0)
4445 {
4446 return error(GL_INVALID_VALUE);
4447 }
4448 context->setPackRowLength(param);
4449 break;
4450 }
4451 else return error(GL_INVALID_ENUM);
4452 case GL_PACK_SKIP_PIXELS:
4453 if(clientVersion >= 3)
4454 {
4455 if(param < 0)
4456 {
4457 return error(GL_INVALID_VALUE);
4458 }
4459 context->setPackSkipPixels(param);
4460 break;
4461 }
4462 else return error(GL_INVALID_ENUM);
4463 case GL_PACK_SKIP_ROWS:
4464 if(clientVersion >= 3)
4465 {
4466 if(param < 0)
4467 {
4468 return error(GL_INVALID_VALUE);
4469 }
4470 context->setPackSkipRows(param);
4471 break;
4472 }
4473 else return error(GL_INVALID_ENUM);
4474 case GL_UNPACK_ROW_LENGTH:
4475 if(clientVersion >= 3)
4476 {
4477 if(param < 0)
4478 {
4479 return error(GL_INVALID_VALUE);
4480 }
4481 context->setUnpackRowLength(param);
4482 break;
4483 }
4484 else return error(GL_INVALID_ENUM);
4485 case GL_UNPACK_IMAGE_HEIGHT:
4486 if(clientVersion >= 3)
4487 {
4488 if(param < 0)
4489 {
4490 return error(GL_INVALID_VALUE);
4491 }
4492 context->setUnpackImageHeight(param);
4493 break;
4494 }
4495 else return error(GL_INVALID_ENUM);
4496 case GL_UNPACK_SKIP_PIXELS:
4497 if(clientVersion >= 3)
4498 {
4499 if(param < 0)
4500 {
4501 return error(GL_INVALID_VALUE);
4502 }
4503 context->setUnpackSkipPixels(param);
4504 break;
4505 }
4506 else return error(GL_INVALID_ENUM);
4507 case GL_UNPACK_SKIP_ROWS:
4508 if(clientVersion >= 3)
4509 {
4510 if(param < 0)
4511 {
4512 return error(GL_INVALID_VALUE);
4513 }
4514 context->setUnpackSkipRows(param);
4515 break;
4516 }
4517 else return error(GL_INVALID_ENUM);
4518 case GL_UNPACK_SKIP_IMAGES:
4519 if(clientVersion >= 3) {
4520 if(param < 0)
4521 {
4522 return error(GL_INVALID_VALUE);
4523 }
4524 context->setUnpackSkipImages(param);
4525 break;
4526 }
4527 else return error(GL_INVALID_ENUM);
4528 default:
4529 return error(GL_INVALID_ENUM);
4530 }
4531 }
4532}
4533
4534void PolygonOffset(GLfloat factor, GLfloat units)
4535{
4536 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4537
4538 es2::Context *context = es2::getContext();
4539
4540 if(context)
4541 {
4542 context->setPolygonOffsetParams(factor, units);
4543 }
4544}
4545
4546void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4547 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4548{
4549 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4550 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4551 x, y, width, height, format, type, bufSize, data);
4552
4553 if(width < 0 || height < 0 || bufSize < 0)
4554 {
4555 return error(GL_INVALID_VALUE);
4556 }
4557
4558 es2::Context *context = es2::getContext();
4559
4560 if(context)
4561 {
4562 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4563 }
4564}
4565
4566void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4567{
4568 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4569 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4570 x, y, width, height, format, type, pixels);
4571
4572 if(width < 0 || height < 0)
4573 {
4574 return error(GL_INVALID_VALUE);
4575 }
4576
4577 es2::Context *context = es2::getContext();
4578
4579 if(context)
4580 {
4581 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4582 }
4583}
4584
4585void ReleaseShaderCompiler(void)
4586{
4587 TRACE("()");
4588
4589 es2::Shader::releaseCompiler();
4590}
4591
Nicolas Capens400667e2017-03-29 14:40:14 -04004592void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004593{
4594 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4595 target, samples, internalformat, width, height);
4596
4597 switch(target)
4598 {
4599 case GL_RENDERBUFFER:
4600 break;
4601 default:
4602 return error(GL_INVALID_ENUM);
4603 }
4604
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004605 if(width < 0 || height < 0 || samples < 0 ||
4606 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4607 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004608 {
4609 return error(GL_INVALID_VALUE);
4610 }
4611
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004612 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004613 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004614 {
4615 return error(GL_INVALID_OPERATION);
4616 }
4617
Nicolas Capens0bac2852016-05-07 06:09:58 -04004618 es2::Context *context = es2::getContext();
4619
4620 if(context)
4621 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004622 GLuint handle = context->getRenderbufferName();
4623 if(handle == 0)
4624 {
4625 return error(GL_INVALID_OPERATION);
4626 }
4627
4628 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004629
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004630 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004631 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004632 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004633 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004634 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4635 {
4636 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4637 }
4638 else if(IsDepthRenderable(internalformat, clientVersion))
4639 {
4640 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4641 }
4642 else if(IsStencilRenderable(internalformat, clientVersion))
4643 {
4644 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4645 }
4646 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004647 }
4648}
4649
Nicolas Capens400667e2017-03-29 14:40:14 -04004650void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4651{
4652 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4653}
4654
Nicolas Capens0bac2852016-05-07 06:09:58 -04004655void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4656{
Nicolas Capens400667e2017-03-29 14:40:14 -04004657 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004658}
4659
4660void SampleCoverage(GLclampf value, GLboolean invert)
4661{
4662 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4663
4664 es2::Context* context = es2::getContext();
4665
4666 if(context)
4667 {
4668 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4669 }
4670}
4671
4672void SetFenceNV(GLuint fence, GLenum condition)
4673{
4674 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4675
4676 if(condition != GL_ALL_COMPLETED_NV)
4677 {
4678 return error(GL_INVALID_ENUM);
4679 }
4680
4681 es2::Context *context = es2::getContext();
4682
4683 if(context)
4684 {
4685 es2::Fence *fenceObject = context->getFence(fence);
4686
4687 if(!fenceObject)
4688 {
4689 return error(GL_INVALID_OPERATION);
4690 }
4691
4692 fenceObject->setFence(condition);
4693 }
4694}
4695
4696void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4697{
4698 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4699
4700 if(width < 0 || height < 0)
4701 {
4702 return error(GL_INVALID_VALUE);
4703 }
4704
4705 es2::Context* context = es2::getContext();
4706
4707 if(context)
4708 {
4709 context->setScissorParams(x, y, width, height);
4710 }
4711}
4712
4713void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4714{
4715 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4716 "const GLvoid* binary = %p, GLsizei length = %d)",
4717 n, shaders, binaryformat, binary, length);
4718
4719 // No binary shader formats are supported.
4720 return error(GL_INVALID_ENUM);
4721}
4722
4723void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4724{
4725 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4726 shader, count, string, length);
4727
4728 if(count < 0)
4729 {
4730 return error(GL_INVALID_VALUE);
4731 }
4732
4733 es2::Context *context = es2::getContext();
4734
4735 if(context)
4736 {
4737 es2::Shader *shaderObject = context->getShader(shader);
4738
4739 if(!shaderObject)
4740 {
4741 if(context->getProgram(shader))
4742 {
4743 return error(GL_INVALID_OPERATION);
4744 }
4745 else
4746 {
4747 return error(GL_INVALID_VALUE);
4748 }
4749 }
4750
4751 shaderObject->setSource(count, string, length);
4752 }
4753}
4754
4755void StencilFunc(GLenum func, GLint ref, GLuint mask)
4756{
4757 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4758}
4759
4760void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4761{
4762 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4763
4764 switch(face)
4765 {
4766 case GL_FRONT:
4767 case GL_BACK:
4768 case GL_FRONT_AND_BACK:
4769 break;
4770 default:
4771 return error(GL_INVALID_ENUM);
4772 }
4773
4774 switch(func)
4775 {
4776 case GL_NEVER:
4777 case GL_ALWAYS:
4778 case GL_LESS:
4779 case GL_LEQUAL:
4780 case GL_EQUAL:
4781 case GL_GEQUAL:
4782 case GL_GREATER:
4783 case GL_NOTEQUAL:
4784 break;
4785 default:
4786 return error(GL_INVALID_ENUM);
4787 }
4788
4789 es2::Context *context = es2::getContext();
4790
4791 if(context)
4792 {
4793 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4794 {
4795 context->setStencilParams(func, ref, mask);
4796 }
4797
4798 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4799 {
4800 context->setStencilBackParams(func, ref, mask);
4801 }
4802 }
4803}
4804
4805void StencilMask(GLuint mask)
4806{
4807 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4808}
4809
4810void StencilMaskSeparate(GLenum face, GLuint mask)
4811{
4812 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4813
4814 switch(face)
4815 {
4816 case GL_FRONT:
4817 case GL_BACK:
4818 case GL_FRONT_AND_BACK:
4819 break;
4820 default:
4821 return error(GL_INVALID_ENUM);
4822 }
4823
4824 es2::Context *context = es2::getContext();
4825
4826 if(context)
4827 {
4828 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4829 {
4830 context->setStencilWritemask(mask);
4831 }
4832
4833 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4834 {
4835 context->setStencilBackWritemask(mask);
4836 }
4837 }
4838}
4839
4840void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4841{
4842 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4843}
4844
4845void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4846{
4847 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4848 face, fail, zfail, zpass);
4849
4850 switch(face)
4851 {
4852 case GL_FRONT:
4853 case GL_BACK:
4854 case GL_FRONT_AND_BACK:
4855 break;
4856 default:
4857 return error(GL_INVALID_ENUM);
4858 }
4859
4860 switch(fail)
4861 {
4862 case GL_ZERO:
4863 case GL_KEEP:
4864 case GL_REPLACE:
4865 case GL_INCR:
4866 case GL_DECR:
4867 case GL_INVERT:
4868 case GL_INCR_WRAP:
4869 case GL_DECR_WRAP:
4870 break;
4871 default:
4872 return error(GL_INVALID_ENUM);
4873 }
4874
4875 switch(zfail)
4876 {
4877 case GL_ZERO:
4878 case GL_KEEP:
4879 case GL_REPLACE:
4880 case GL_INCR:
4881 case GL_DECR:
4882 case GL_INVERT:
4883 case GL_INCR_WRAP:
4884 case GL_DECR_WRAP:
4885 break;
4886 default:
4887 return error(GL_INVALID_ENUM);
4888 }
4889
4890 switch(zpass)
4891 {
4892 case GL_ZERO:
4893 case GL_KEEP:
4894 case GL_REPLACE:
4895 case GL_INCR:
4896 case GL_DECR:
4897 case GL_INVERT:
4898 case GL_INCR_WRAP:
4899 case GL_DECR_WRAP:
4900 break;
4901 default:
4902 return error(GL_INVALID_ENUM);
4903 }
4904
4905 es2::Context *context = es2::getContext();
4906
4907 if(context)
4908 {
4909 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4910 {
4911 context->setStencilOperations(fail, zfail, zpass);
4912 }
4913
4914 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4915 {
4916 context->setStencilBackOperations(fail, zfail, zpass);
4917 }
4918 }
4919}
4920
4921GLboolean TestFenceNV(GLuint fence)
4922{
4923 TRACE("(GLuint fence = %d)", fence);
4924
4925 es2::Context *context = es2::getContext();
4926
4927 if(context)
4928 {
4929 es2::Fence *fenceObject = context->getFence(fence);
4930
4931 if(!fenceObject)
4932 {
4933 return error(GL_INVALID_OPERATION, GL_TRUE);
4934 }
4935
4936 return fenceObject->testFence();
4937 }
4938
4939 return GL_TRUE;
4940}
4941
4942void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004943 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004944{
4945 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004946 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4947 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004948
4949 if(!validImageSize(level, width, height))
4950 {
4951 return error(GL_INVALID_VALUE);
4952 }
4953
4954 es2::Context *context = es2::getContext();
4955
4956 if(context)
4957 {
4958 GLint clientVersion = context->getClientVersion();
4959 if(clientVersion < 3)
4960 {
4961 if(internalformat != (GLint)format)
4962 {
4963 return error(GL_INVALID_OPERATION);
4964 }
4965 }
4966
Nicolas Capens03589982018-02-01 17:28:32 -05004967 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, context->getClientVersion());
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004968 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004969 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004970 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004971 }
4972
4973 if(border != 0)
4974 {
4975 return error(GL_INVALID_VALUE);
4976 }
4977
4978 switch(target)
4979 {
4980 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05004981 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004982 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4983 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4984 {
4985 return error(GL_INVALID_VALUE);
4986 }
4987 break;
4988 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4989 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4990 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4991 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4992 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4993 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4994 if(width != height)
4995 {
4996 return error(GL_INVALID_VALUE);
4997 }
4998
4999 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5000 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5001 {
5002 return error(GL_INVALID_VALUE);
5003 }
5004 break;
5005 default:
5006 return error(GL_INVALID_ENUM);
5007 }
5008
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005009 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005010
Nicolas Capens5555af42017-12-14 13:14:03 -05005011 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005012 if(validationError != GL_NONE)
5013 {
5014 return error(validationError);
5015 }
5016
Alexis Hetu46768622018-01-16 22:09:28 -05005017 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005018 {
Alexis Hetu46768622018-01-16 22:09:28 -05005019 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005020
5021 if(!texture)
5022 {
5023 return error(GL_INVALID_OPERATION);
5024 }
5025
Nicolas Capens648b5822018-01-18 00:04:26 -05005026 texture->setImage(context, level, width, height, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005027 }
5028 else
5029 {
5030 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5031
5032 if(!texture)
5033 {
5034 return error(GL_INVALID_OPERATION);
5035 }
5036
Nicolas Capens648b5822018-01-18 00:04:26 -05005037 texture->setImage(context, target, level, width, height, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005038 }
5039 }
5040}
5041
5042void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5043{
5044 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5045
5046 es2::Context *context = es2::getContext();
5047
5048 if(context)
5049 {
5050 es2::Texture *texture;
5051
5052 GLint clientVersion = context->getClientVersion();
5053
5054 switch(target)
5055 {
5056 case GL_TEXTURE_2D:
5057 texture = context->getTexture2D();
5058 break;
5059 case GL_TEXTURE_2D_ARRAY:
5060 if(clientVersion < 3)
5061 {
5062 return error(GL_INVALID_ENUM);
5063 }
5064 else
5065 {
5066 texture = context->getTexture2DArray();
5067 }
5068 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005069 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005070 texture = context->getTexture3D();
5071 break;
5072 case GL_TEXTURE_CUBE_MAP:
5073 texture = context->getTextureCubeMap();
5074 break;
5075 case GL_TEXTURE_EXTERNAL_OES:
5076 texture = context->getTextureExternal();
5077 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005078 case GL_TEXTURE_RECTANGLE_ARB:
5079 texture = context->getTexture2DRect();
5080 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005081 default:
5082 return error(GL_INVALID_ENUM);
5083 }
5084
5085 switch(pname)
5086 {
5087 case GL_TEXTURE_WRAP_S:
5088 if(!texture->setWrapS((GLenum)param))
5089 {
5090 return error(GL_INVALID_ENUM);
5091 }
5092 break;
5093 case GL_TEXTURE_WRAP_T:
5094 if(!texture->setWrapT((GLenum)param))
5095 {
5096 return error(GL_INVALID_ENUM);
5097 }
5098 break;
5099 case GL_TEXTURE_WRAP_R_OES:
5100 if(!texture->setWrapR((GLenum)param))
5101 {
5102 return error(GL_INVALID_ENUM);
5103 }
5104 break;
5105 case GL_TEXTURE_MIN_FILTER:
5106 if(!texture->setMinFilter((GLenum)param))
5107 {
5108 return error(GL_INVALID_ENUM);
5109 }
5110 break;
5111 case GL_TEXTURE_MAG_FILTER:
5112 if(!texture->setMagFilter((GLenum)param))
5113 {
5114 return error(GL_INVALID_ENUM);
5115 }
5116 break;
5117 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5118 if(!texture->setMaxAnisotropy(param))
5119 {
5120 return error(GL_INVALID_VALUE);
5121 }
5122 break;
5123 case GL_TEXTURE_BASE_LEVEL:
5124 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5125 {
5126 return error(GL_INVALID_VALUE);
5127 }
5128 break;
5129 case GL_TEXTURE_COMPARE_FUNC:
5130 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5131 {
5132 return error(GL_INVALID_VALUE);
5133 }
5134 break;
5135 case GL_TEXTURE_COMPARE_MODE:
5136 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5137 {
5138 return error(GL_INVALID_VALUE);
5139 }
5140 break;
5141 case GL_TEXTURE_MAX_LEVEL:
5142 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5143 {
5144 return error(GL_INVALID_VALUE);
5145 }
5146 break;
5147 case GL_TEXTURE_MAX_LOD:
5148 if(clientVersion < 3 || !texture->setMaxLOD(param))
5149 {
5150 return error(GL_INVALID_VALUE);
5151 }
5152 break;
5153 case GL_TEXTURE_MIN_LOD:
5154 if(clientVersion < 3 || !texture->setMinLOD(param))
5155 {
5156 return error(GL_INVALID_VALUE);
5157 }
5158 break;
5159 case GL_TEXTURE_SWIZZLE_R:
5160 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5161 {
5162 return error(GL_INVALID_VALUE);
5163 }
5164 break;
5165 case GL_TEXTURE_SWIZZLE_G:
5166 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5167 {
5168 return error(GL_INVALID_VALUE);
5169 }
5170 break;
5171 case GL_TEXTURE_SWIZZLE_B:
5172 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5173 {
5174 return error(GL_INVALID_VALUE);
5175 }
5176 break;
5177 case GL_TEXTURE_SWIZZLE_A:
5178 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5179 {
5180 return error(GL_INVALID_VALUE);
5181 }
5182 break;
5183 default:
5184 return error(GL_INVALID_ENUM);
5185 }
5186 }
5187}
5188
5189void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5190{
5191 glTexParameterf(target, pname, *params);
5192}
5193
5194void TexParameteri(GLenum target, GLenum pname, GLint param)
5195{
5196 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5197
5198 es2::Context *context = es2::getContext();
5199
5200 if(context)
5201 {
5202 es2::Texture *texture;
5203
5204 GLint clientVersion = context->getClientVersion();
5205
5206 switch(target)
5207 {
5208 case GL_TEXTURE_2D:
5209 texture = context->getTexture2D();
5210 break;
5211 case GL_TEXTURE_2D_ARRAY:
5212 if(clientVersion < 3)
5213 {
5214 return error(GL_INVALID_ENUM);
5215 }
5216 else
5217 {
5218 texture = context->getTexture2DArray();
5219 }
5220 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005221 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005222 texture = context->getTexture3D();
5223 break;
5224 case GL_TEXTURE_CUBE_MAP:
5225 texture = context->getTextureCubeMap();
5226 break;
5227 case GL_TEXTURE_EXTERNAL_OES:
5228 texture = context->getTextureExternal();
5229 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005230 case GL_TEXTURE_RECTANGLE_ARB:
5231 texture = context->getTexture2DRect();
5232 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005233 default:
5234 return error(GL_INVALID_ENUM);
5235 }
5236
5237 switch(pname)
5238 {
5239 case GL_TEXTURE_WRAP_S:
5240 if(!texture->setWrapS((GLenum)param))
5241 {
5242 return error(GL_INVALID_ENUM);
5243 }
5244 break;
5245 case GL_TEXTURE_WRAP_T:
5246 if(!texture->setWrapT((GLenum)param))
5247 {
5248 return error(GL_INVALID_ENUM);
5249 }
5250 break;
5251 case GL_TEXTURE_WRAP_R_OES:
5252 if(!texture->setWrapR((GLenum)param))
5253 {
5254 return error(GL_INVALID_ENUM);
5255 }
5256 break;
5257 case GL_TEXTURE_MIN_FILTER:
5258 if(!texture->setMinFilter((GLenum)param))
5259 {
5260 return error(GL_INVALID_ENUM);
5261 }
5262 break;
5263 case GL_TEXTURE_MAG_FILTER:
5264 if(!texture->setMagFilter((GLenum)param))
5265 {
5266 return error(GL_INVALID_ENUM);
5267 }
5268 break;
5269 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5270 if(!texture->setMaxAnisotropy((GLfloat)param))
5271 {
5272 return error(GL_INVALID_VALUE);
5273 }
5274 break;
5275 case GL_TEXTURE_BASE_LEVEL:
5276 if(clientVersion < 3 || !texture->setBaseLevel(param))
5277 {
5278 return error(GL_INVALID_VALUE);
5279 }
5280 break;
5281 case GL_TEXTURE_COMPARE_FUNC:
5282 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5283 {
5284 return error(GL_INVALID_VALUE);
5285 }
5286 break;
5287 case GL_TEXTURE_COMPARE_MODE:
5288 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5289 {
5290 return error(GL_INVALID_VALUE);
5291 }
5292 break;
5293 case GL_TEXTURE_MAX_LEVEL:
5294 if(clientVersion < 3 || !texture->setMaxLevel(param))
5295 {
5296 return error(GL_INVALID_VALUE);
5297 }
5298 break;
5299 case GL_TEXTURE_MAX_LOD:
5300 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5301 {
5302 return error(GL_INVALID_VALUE);
5303 }
5304 break;
5305 case GL_TEXTURE_MIN_LOD:
5306 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5307 {
5308 return error(GL_INVALID_VALUE);
5309 }
5310 break;
5311 case GL_TEXTURE_SWIZZLE_R:
5312 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5313 {
5314 return error(GL_INVALID_VALUE);
5315 }
5316 break;
5317 case GL_TEXTURE_SWIZZLE_G:
5318 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5319 {
5320 return error(GL_INVALID_VALUE);
5321 }
5322 break;
5323 case GL_TEXTURE_SWIZZLE_B:
5324 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5325 {
5326 return error(GL_INVALID_VALUE);
5327 }
5328 break;
5329 case GL_TEXTURE_SWIZZLE_A:
5330 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5331 {
5332 return error(GL_INVALID_VALUE);
5333 }
5334 break;
5335 default:
5336 return error(GL_INVALID_ENUM);
5337 }
5338 }
5339}
5340
5341void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5342{
5343 glTexParameteri(target, pname, *params);
5344}
5345
5346void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005347 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005348{
5349 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5350 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005351 "const GLvoid* data = %p)",
5352 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005353
5354 if(!es2::IsTextureTarget(target))
5355 {
5356 return error(GL_INVALID_ENUM);
5357 }
5358
5359 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5360 {
5361 return error(GL_INVALID_VALUE);
5362 }
5363
5364 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5365 {
5366 return error(GL_INVALID_VALUE);
5367 }
5368
5369 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5370 {
5371 return error(GL_INVALID_VALUE);
5372 }
5373
Nicolas Capens0bac2852016-05-07 06:09:58 -04005374 es2::Context *context = es2::getContext();
5375
5376 if(context)
5377 {
Alexis Hetu46768622018-01-16 22:09:28 -05005378 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005379 {
Alexis Hetu46768622018-01-16 22:09:28 -05005380 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005381
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005382 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5383 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005384 {
5385 return error(validationError);
5386 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005387
Nicolas Capens5555af42017-12-14 13:14:03 -05005388 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005389 if(validationError != GL_NONE)
5390 {
5391 return error(validationError);
5392 }
5393
Nicolas Capens5555af42017-12-14 13:14:03 -05005394 texture->subImage(context, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005395 }
5396 else if(es2::IsCubemapTextureTarget(target))
5397 {
5398 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5399
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005400 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5401 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005402 {
5403 return error(validationError);
5404 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005405
Nicolas Capens5555af42017-12-14 13:14:03 -05005406 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005407 if(validationError != GL_NONE)
5408 {
5409 return error(validationError);
5410 }
5411
Nicolas Capens5555af42017-12-14 13:14:03 -05005412 texture->subImage(context, target, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005413 }
5414 else UNREACHABLE(target);
5415 }
5416}
5417
5418void Uniform1f(GLint location, GLfloat x)
5419{
5420 glUniform1fv(location, 1, &x);
5421}
5422
5423void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5424{
5425 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5426
5427 if(count < 0)
5428 {
5429 return error(GL_INVALID_VALUE);
5430 }
5431
Nicolas Capens0bac2852016-05-07 06:09:58 -04005432 es2::Context *context = es2::getContext();
5433
5434 if(context)
5435 {
5436 es2::Program *program = context->getCurrentProgram();
5437
5438 if(!program)
5439 {
5440 return error(GL_INVALID_OPERATION);
5441 }
5442
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005443 if(location == -1)
5444 {
5445 return;
5446 }
5447
Nicolas Capens0bac2852016-05-07 06:09:58 -04005448 if(!program->setUniform1fv(location, count, v))
5449 {
5450 return error(GL_INVALID_OPERATION);
5451 }
5452 }
5453}
5454
5455void Uniform1i(GLint location, GLint x)
5456{
5457 glUniform1iv(location, 1, &x);
5458}
5459
5460void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5461{
5462 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5463
5464 if(count < 0)
5465 {
5466 return error(GL_INVALID_VALUE);
5467 }
5468
Nicolas Capens0bac2852016-05-07 06:09:58 -04005469 es2::Context *context = es2::getContext();
5470
5471 if(context)
5472 {
5473 es2::Program *program = context->getCurrentProgram();
5474
5475 if(!program)
5476 {
5477 return error(GL_INVALID_OPERATION);
5478 }
5479
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005480 if(location == -1)
5481 {
5482 return;
5483 }
5484
Nicolas Capens0bac2852016-05-07 06:09:58 -04005485 if(!program->setUniform1iv(location, count, v))
5486 {
5487 return error(GL_INVALID_OPERATION);
5488 }
5489 }
5490}
5491
5492void Uniform2f(GLint location, GLfloat x, GLfloat y)
5493{
5494 GLfloat xy[2] = {x, y};
5495
5496 glUniform2fv(location, 1, (GLfloat*)&xy);
5497}
5498
5499void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5500{
5501 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5502
5503 if(count < 0)
5504 {
5505 return error(GL_INVALID_VALUE);
5506 }
5507
Nicolas Capens0bac2852016-05-07 06:09:58 -04005508 es2::Context *context = es2::getContext();
5509
5510 if(context)
5511 {
5512 es2::Program *program = context->getCurrentProgram();
5513
5514 if(!program)
5515 {
5516 return error(GL_INVALID_OPERATION);
5517 }
5518
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005519 if(location == -1)
5520 {
5521 return;
5522 }
5523
Nicolas Capens0bac2852016-05-07 06:09:58 -04005524 if(!program->setUniform2fv(location, count, v))
5525 {
5526 return error(GL_INVALID_OPERATION);
5527 }
5528 }
5529}
5530
5531void Uniform2i(GLint location, GLint x, GLint y)
5532{
5533 GLint xy[4] = {x, y};
5534
5535 glUniform2iv(location, 1, (GLint*)&xy);
5536}
5537
5538void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5539{
5540 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5541
5542 if(count < 0)
5543 {
5544 return error(GL_INVALID_VALUE);
5545 }
5546
Nicolas Capens0bac2852016-05-07 06:09:58 -04005547 es2::Context *context = es2::getContext();
5548
5549 if(context)
5550 {
5551 es2::Program *program = context->getCurrentProgram();
5552
5553 if(!program)
5554 {
5555 return error(GL_INVALID_OPERATION);
5556 }
5557
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005558 if(location == -1)
5559 {
5560 return;
5561 }
5562
Nicolas Capens0bac2852016-05-07 06:09:58 -04005563 if(!program->setUniform2iv(location, count, v))
5564 {
5565 return error(GL_INVALID_OPERATION);
5566 }
5567 }
5568}
5569
5570void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5571{
5572 GLfloat xyz[3] = {x, y, z};
5573
5574 glUniform3fv(location, 1, (GLfloat*)&xyz);
5575}
5576
5577void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5578{
5579 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5580
5581 if(count < 0)
5582 {
5583 return error(GL_INVALID_VALUE);
5584 }
5585
Nicolas Capens0bac2852016-05-07 06:09:58 -04005586 es2::Context *context = es2::getContext();
5587
5588 if(context)
5589 {
5590 es2::Program *program = context->getCurrentProgram();
5591
5592 if(!program)
5593 {
5594 return error(GL_INVALID_OPERATION);
5595 }
5596
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005597 if(location == -1)
5598 {
5599 return;
5600 }
5601
Nicolas Capens0bac2852016-05-07 06:09:58 -04005602 if(!program->setUniform3fv(location, count, v))
5603 {
5604 return error(GL_INVALID_OPERATION);
5605 }
5606 }
5607}
5608
5609void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5610{
5611 GLint xyz[3] = {x, y, z};
5612
5613 glUniform3iv(location, 1, (GLint*)&xyz);
5614}
5615
5616void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5617{
5618 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5619
5620 if(count < 0)
5621 {
5622 return error(GL_INVALID_VALUE);
5623 }
5624
Nicolas Capens0bac2852016-05-07 06:09:58 -04005625 es2::Context *context = es2::getContext();
5626
5627 if(context)
5628 {
5629 es2::Program *program = context->getCurrentProgram();
5630
5631 if(!program)
5632 {
5633 return error(GL_INVALID_OPERATION);
5634 }
5635
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005636 if(location == -1)
5637 {
5638 return;
5639 }
5640
Nicolas Capens0bac2852016-05-07 06:09:58 -04005641 if(!program->setUniform3iv(location, count, v))
5642 {
5643 return error(GL_INVALID_OPERATION);
5644 }
5645 }
5646}
5647
5648void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5649{
5650 GLfloat xyzw[4] = {x, y, z, w};
5651
5652 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5653}
5654
5655void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5656{
5657 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5658
5659 if(count < 0)
5660 {
5661 return error(GL_INVALID_VALUE);
5662 }
5663
Nicolas Capens0bac2852016-05-07 06:09:58 -04005664 es2::Context *context = es2::getContext();
5665
5666 if(context)
5667 {
5668 es2::Program *program = context->getCurrentProgram();
5669
5670 if(!program)
5671 {
5672 return error(GL_INVALID_OPERATION);
5673 }
5674
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005675 if(location == -1)
5676 {
5677 return;
5678 }
5679
Nicolas Capens0bac2852016-05-07 06:09:58 -04005680 if(!program->setUniform4fv(location, count, v))
5681 {
5682 return error(GL_INVALID_OPERATION);
5683 }
5684 }
5685}
5686
5687void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5688{
5689 GLint xyzw[4] = {x, y, z, w};
5690
5691 glUniform4iv(location, 1, (GLint*)&xyzw);
5692}
5693
5694void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5695{
5696 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5697
5698 if(count < 0)
5699 {
5700 return error(GL_INVALID_VALUE);
5701 }
5702
Nicolas Capens0bac2852016-05-07 06:09:58 -04005703 es2::Context *context = es2::getContext();
5704
5705 if(context)
5706 {
5707 es2::Program *program = context->getCurrentProgram();
5708
5709 if(!program)
5710 {
5711 return error(GL_INVALID_OPERATION);
5712 }
5713
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005714 if(location == -1)
5715 {
5716 return;
5717 }
5718
Nicolas Capens0bac2852016-05-07 06:09:58 -04005719 if(!program->setUniform4iv(location, count, v))
5720 {
5721 return error(GL_INVALID_OPERATION);
5722 }
5723 }
5724}
5725
5726void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5727{
5728 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5729 location, count, transpose, value);
5730
5731 if(count < 0)
5732 {
5733 return error(GL_INVALID_VALUE);
5734 }
5735
Nicolas Capens0bac2852016-05-07 06:09:58 -04005736 es2::Context *context = es2::getContext();
5737
5738 if(context)
5739 {
5740 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5741 {
5742 return error(GL_INVALID_VALUE);
5743 }
5744
5745 es2::Program *program = context->getCurrentProgram();
5746
5747 if(!program)
5748 {
5749 return error(GL_INVALID_OPERATION);
5750 }
5751
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005752 if(location == -1)
5753 {
5754 return;
5755 }
5756
Nicolas Capens0bac2852016-05-07 06:09:58 -04005757 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5758 {
5759 return error(GL_INVALID_OPERATION);
5760 }
5761 }
5762}
5763
5764void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5765{
5766 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5767 location, count, transpose, value);
5768
5769 if(count < 0)
5770 {
5771 return error(GL_INVALID_VALUE);
5772 }
5773
Nicolas Capens0bac2852016-05-07 06:09:58 -04005774 es2::Context *context = es2::getContext();
5775
5776 if(context)
5777 {
5778 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5779 {
5780 return error(GL_INVALID_VALUE);
5781 }
5782
5783 es2::Program *program = context->getCurrentProgram();
5784
5785 if(!program)
5786 {
5787 return error(GL_INVALID_OPERATION);
5788 }
5789
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005790 if(location == -1)
5791 {
5792 return;
5793 }
5794
Nicolas Capens0bac2852016-05-07 06:09:58 -04005795 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5796 {
5797 return error(GL_INVALID_OPERATION);
5798 }
5799 }
5800}
5801
5802void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5803{
5804 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5805 location, count, transpose, value);
5806
5807 if(count < 0)
5808 {
5809 return error(GL_INVALID_VALUE);
5810 }
5811
Nicolas Capens0bac2852016-05-07 06:09:58 -04005812 es2::Context *context = es2::getContext();
5813
5814 if(context)
5815 {
5816 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5817 {
5818 return error(GL_INVALID_VALUE);
5819 }
5820
5821 es2::Program *program = context->getCurrentProgram();
5822
5823 if(!program)
5824 {
5825 return error(GL_INVALID_OPERATION);
5826 }
5827
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005828 if(location == -1)
5829 {
5830 return;
5831 }
5832
Nicolas Capens0bac2852016-05-07 06:09:58 -04005833 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5834 {
5835 return error(GL_INVALID_OPERATION);
5836 }
5837 }
5838}
5839
5840void UseProgram(GLuint program)
5841{
5842 TRACE("(GLuint program = %d)", program);
5843
5844 es2::Context *context = es2::getContext();
5845
5846 if(context)
5847 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005848 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5849 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5850 {
5851 return error(GL_INVALID_OPERATION);
5852 }
5853
Nicolas Capens0bac2852016-05-07 06:09:58 -04005854 es2::Program *programObject = context->getProgram(program);
5855
5856 if(!programObject && program != 0)
5857 {
5858 if(context->getShader(program))
5859 {
5860 return error(GL_INVALID_OPERATION);
5861 }
5862 else
5863 {
5864 return error(GL_INVALID_VALUE);
5865 }
5866 }
5867
5868 if(program != 0 && !programObject->isLinked())
5869 {
5870 return error(GL_INVALID_OPERATION);
5871 }
5872
5873 context->useProgram(program);
5874 }
5875}
5876
5877void ValidateProgram(GLuint program)
5878{
5879 TRACE("(GLuint program = %d)", program);
5880
5881 es2::Context *context = es2::getContext();
5882
5883 if(context)
5884 {
5885 es2::Program *programObject = context->getProgram(program);
5886
5887 if(!programObject)
5888 {
5889 if(context->getShader(program))
5890 {
5891 return error(GL_INVALID_OPERATION);
5892 }
5893 else
5894 {
5895 return error(GL_INVALID_VALUE);
5896 }
5897 }
5898
Ben Vanik1fd3b282017-07-10 14:08:12 -07005899 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005900 }
5901}
5902
5903void VertexAttrib1f(GLuint index, GLfloat x)
5904{
5905 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5906
5907 if(index >= es2::MAX_VERTEX_ATTRIBS)
5908 {
5909 return error(GL_INVALID_VALUE);
5910 }
5911
5912 es2::Context *context = es2::getContext();
5913
5914 if(context)
5915 {
5916 GLfloat vals[4] = { x, 0, 0, 1 };
5917 context->setVertexAttrib(index, vals);
5918 }
5919}
5920
5921void VertexAttrib1fv(GLuint index, const GLfloat* values)
5922{
5923 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5924
5925 if(index >= es2::MAX_VERTEX_ATTRIBS)
5926 {
5927 return error(GL_INVALID_VALUE);
5928 }
5929
5930 es2::Context *context = es2::getContext();
5931
5932 if(context)
5933 {
5934 GLfloat vals[4] = { values[0], 0, 0, 1 };
5935 context->setVertexAttrib(index, vals);
5936 }
5937}
5938
5939void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5940{
5941 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5942
5943 if(index >= es2::MAX_VERTEX_ATTRIBS)
5944 {
5945 return error(GL_INVALID_VALUE);
5946 }
5947
5948 es2::Context *context = es2::getContext();
5949
5950 if(context)
5951 {
5952 GLfloat vals[4] = { x, y, 0, 1 };
5953 context->setVertexAttrib(index, vals);
5954 }
5955}
5956
5957void VertexAttrib2fv(GLuint index, const GLfloat* values)
5958{
5959 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5960
5961 if(index >= es2::MAX_VERTEX_ATTRIBS)
5962 {
5963 return error(GL_INVALID_VALUE);
5964 }
5965
5966 es2::Context *context = es2::getContext();
5967
5968 if(context)
5969 {
5970 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5971 context->setVertexAttrib(index, vals);
5972 }
5973}
5974
5975void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5976{
5977 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5978
5979 if(index >= es2::MAX_VERTEX_ATTRIBS)
5980 {
5981 return error(GL_INVALID_VALUE);
5982 }
5983
5984 es2::Context *context = es2::getContext();
5985
5986 if(context)
5987 {
5988 GLfloat vals[4] = { x, y, z, 1 };
5989 context->setVertexAttrib(index, vals);
5990 }
5991}
5992
5993void VertexAttrib3fv(GLuint index, const GLfloat* values)
5994{
5995 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5996
5997 if(index >= es2::MAX_VERTEX_ATTRIBS)
5998 {
5999 return error(GL_INVALID_VALUE);
6000 }
6001
6002 es2::Context *context = es2::getContext();
6003
6004 if(context)
6005 {
6006 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6007 context->setVertexAttrib(index, vals);
6008 }
6009}
6010
6011void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6012{
6013 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6014
6015 if(index >= es2::MAX_VERTEX_ATTRIBS)
6016 {
6017 return error(GL_INVALID_VALUE);
6018 }
6019
6020 es2::Context *context = es2::getContext();
6021
6022 if(context)
6023 {
6024 GLfloat vals[4] = { x, y, z, w };
6025 context->setVertexAttrib(index, vals);
6026 }
6027}
6028
6029void VertexAttrib4fv(GLuint index, const GLfloat* values)
6030{
6031 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6032
6033 if(index >= es2::MAX_VERTEX_ATTRIBS)
6034 {
6035 return error(GL_INVALID_VALUE);
6036 }
6037
6038 es2::Context *context = es2::getContext();
6039
6040 if(context)
6041 {
6042 context->setVertexAttrib(index, values);
6043 }
6044}
6045
6046void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6047{
6048 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6049 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6050 index, size, type, normalized, stride, ptr);
6051
6052 if(index >= es2::MAX_VERTEX_ATTRIBS)
6053 {
6054 return error(GL_INVALID_VALUE);
6055 }
6056
6057 if(size < 1 || size > 4)
6058 {
6059 return error(GL_INVALID_VALUE);
6060 }
6061
6062 GLint clientVersion = egl::getClientVersion();
6063
6064 switch(type)
6065 {
6066 case GL_BYTE:
6067 case GL_UNSIGNED_BYTE:
6068 case GL_SHORT:
6069 case GL_UNSIGNED_SHORT:
6070 case GL_FIXED:
6071 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006072 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006073 break;
6074 case GL_INT_2_10_10_10_REV:
6075 case GL_UNSIGNED_INT_2_10_10_10_REV:
6076 if(clientVersion >= 3)
6077 {
6078 if(size != 4)
6079 {
6080 return error(GL_INVALID_OPERATION);
6081 }
6082 break;
6083 }
6084 else return error(GL_INVALID_ENUM);
6085 case GL_INT:
6086 case GL_UNSIGNED_INT:
6087 case GL_HALF_FLOAT:
6088 if(clientVersion >= 3)
6089 {
6090 break;
6091 }
6092 else return error(GL_INVALID_ENUM);
6093 default:
6094 return error(GL_INVALID_ENUM);
6095 }
6096
6097 if(stride < 0)
6098 {
6099 return error(GL_INVALID_VALUE);
6100 }
6101
6102 es2::Context *context = es2::getContext();
6103
6104 if(context)
6105 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006106 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6107 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6108 {
6109 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6110 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6111 return error(GL_INVALID_OPERATION);
6112 }
6113
Alexis Hetu6f284032017-12-11 15:19:36 -05006114 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006115 }
6116}
6117
6118void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6119{
6120 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6121
6122 if(width < 0 || height < 0)
6123 {
6124 return error(GL_INVALID_VALUE);
6125 }
6126
6127 es2::Context *context = es2::getContext();
6128
6129 if(context)
6130 {
6131 context->setViewportParams(x, y, width, height);
6132 }
6133}
6134
Alexis Hetub9dda642016-10-06 11:25:32 -04006135static 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 -04006136{
6137 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6138 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6139 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6140 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6141
6142 switch(filter)
6143 {
6144 case GL_NEAREST:
6145 break;
6146 default:
6147 return error(GL_INVALID_ENUM);
6148 }
6149
6150 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6151 {
6152 return error(GL_INVALID_VALUE);
6153 }
6154
6155 es2::Context *context = es2::getContext();
6156
6157 if(context)
6158 {
6159 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6160 {
6161 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6162 return error(GL_INVALID_OPERATION);
6163 }
6164
Alexis Hetub9dda642016-10-06 11:25:32 -04006165 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006166 }
6167}
6168
Alexis Hetub9dda642016-10-06 11:25:32 -04006169void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6170{
6171 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6172}
6173
Nicolas Capens0bac2852016-05-07 06:09:58 -04006174void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6175 GLbitfield mask, GLenum filter)
6176{
6177 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6178 {
6179 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6180 return error(GL_INVALID_OPERATION);
6181 }
6182
Alexis Hetub9dda642016-10-06 11:25:32 -04006183 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006184}
6185
6186void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006187 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006188{
6189 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6190 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006191 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6192 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006193
6194 switch(target)
6195 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006196 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006197 switch(format)
6198 {
6199 case GL_DEPTH_COMPONENT:
6200 case GL_DEPTH_STENCIL_OES:
6201 return error(GL_INVALID_OPERATION);
6202 default:
6203 break;
6204 }
6205 break;
6206 default:
6207 return error(GL_INVALID_ENUM);
6208 }
6209
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006210 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006211 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006212 return error(GL_INVALID_OPERATION);
6213 }
6214
6215 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion());
6216 if(validationError != GL_NONE)
6217 {
6218 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006219 }
6220
6221 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6222 {
6223 return error(GL_INVALID_VALUE);
6224 }
6225
6226 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6227 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6228 {
6229 return error(GL_INVALID_VALUE);
6230 }
6231
6232 if(border != 0)
6233 {
6234 return error(GL_INVALID_VALUE);
6235 }
6236
6237 es2::Context *context = es2::getContext();
6238
6239 if(context)
6240 {
6241 es2::Texture3D *texture = context->getTexture3D();
6242
6243 if(!texture)
6244 {
6245 return error(GL_INVALID_OPERATION);
6246 }
6247
Nicolas Capens2fc90512018-01-23 22:24:22 +00006248 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006249 if(validationError != GL_NONE)
6250 {
6251 return error(validationError);
6252 }
6253
Nicolas Capens2fc90512018-01-23 22:24:22 +00006254 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Nicolas Capens648b5822018-01-18 00:04:26 -05006255 texture->setImage(context, level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006256 }
6257}
6258
Alexis Hetu53f48092016-06-17 14:08:06 -04006259void 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 -04006260{
6261 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6262 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006263 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6264 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006265
6266 switch(target)
6267 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006268 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006269 break;
6270 default:
6271 return error(GL_INVALID_ENUM);
6272 }
6273
6274 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6275 {
6276 return;
6277 }
6278
6279 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6280 {
6281 return error(GL_INVALID_VALUE);
6282 }
6283
6284 if((width < 0) || (height < 0) || (depth < 0))
6285 {
6286 return error(GL_INVALID_VALUE);
6287 }
6288
6289 es2::Context *context = es2::getContext();
6290
6291 if(context)
6292 {
6293 es2::Texture3D *texture = context->getTexture3D();
6294
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006295 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
6296 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006297 {
6298 return error(validationError);
6299 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006300
Nicolas Capens5555af42017-12-14 13:14:03 -05006301 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006302 if(validationError != GL_NONE)
6303 {
6304 return error(validationError);
6305 }
6306
Nicolas Capens5555af42017-12-14 13:14:03 -05006307 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006308 }
6309}
6310
6311void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6312{
6313 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6314 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6315 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6316
6317 switch(target)
6318 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006319 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006320 break;
6321 default:
6322 return error(GL_INVALID_ENUM);
6323 }
6324
6325 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6326 {
6327 return error(GL_INVALID_VALUE);
6328 }
6329
6330 es2::Context *context = es2::getContext();
6331
6332 if(context)
6333 {
6334 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6335
6336 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6337 {
6338 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6339 }
6340
6341 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6342
6343 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6344 {
6345 return error(GL_INVALID_OPERATION);
6346 }
6347
6348 es2::Texture3D *texture = context->getTexture3D();
6349
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006350 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capens0bac2852016-05-07 06:09:58 -04006351 if(validationError != GL_NONE)
6352 {
6353 return error(validationError);
6354 }
6355
Nicolas Capens1529c2c2018-02-06 14:44:47 -05006356 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006357 }
6358}
6359
6360void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6361{
6362 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6363 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6364 target, level, internalformat, width, height, depth, border, imageSize, data);
6365
6366 switch(target)
6367 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006368 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006369 break;
6370 default:
6371 return error(GL_INVALID_ENUM);
6372 }
6373
6374 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6375 {
6376 return error(GL_INVALID_VALUE);
6377 }
6378
6379 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6380 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6381 {
6382 return error(GL_INVALID_VALUE);
6383 }
6384
Nicolas Capens03589982018-02-01 17:28:32 -05006385 if(!IsCompressed(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006386 {
Nicolas Capens03589982018-02-01 17:28:32 -05006387 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006388 }
6389
6390 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6391 {
6392 return error(GL_INVALID_VALUE);
6393 }
6394
6395 es2::Context *context = es2::getContext();
6396
6397 if(context)
6398 {
6399 es2::Texture3D *texture = context->getTexture3D();
6400
6401 if(!texture)
6402 {
6403 return error(GL_INVALID_OPERATION);
6404 }
6405
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006406 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006407
6408 if(validationError != GL_NONE)
6409 {
6410 return error(validationError);
6411 }
6412
Nicolas Capens0bac2852016-05-07 06:09:58 -04006413 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6414 }
6415}
6416
6417void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6418{
6419 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6420 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6421 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6422 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6423
6424 switch(target)
6425 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006426 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006427 break;
6428 default:
6429 return error(GL_INVALID_ENUM);
6430 }
6431
6432 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6433 {
6434 return error(GL_INVALID_VALUE);
6435 }
6436
6437 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6438 {
6439 return error(GL_INVALID_VALUE);
6440 }
6441
Nicolas Capens03589982018-02-01 17:28:32 -05006442 if(!IsCompressed(format, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006443 {
Nicolas Capens03589982018-02-01 17:28:32 -05006444 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006445 }
6446
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006447 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006448 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006449 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006450 }
6451
6452 es2::Context *context = es2::getContext();
6453
6454 if(context)
6455 {
6456 es2::Texture3D *texture = context->getTexture3D();
6457
6458 if(!texture)
6459 {
6460 return error(GL_INVALID_OPERATION);
6461 }
6462
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006463 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006464 if(validationError != GL_NONE)
6465 {
6466 return error(validationError);
6467 }
6468
6469 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006470 }
6471}
6472
6473void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6474{
6475 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6476 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6477
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006478 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006479 {
6480 return error(GL_INVALID_ENUM);
6481 }
6482
6483 es2::Context *context = es2::getContext();
6484
6485 if(context)
6486 {
6487 if(texture == 0)
6488 {
6489 textarget = GL_NONE;
6490 }
6491 else
6492 {
6493 es2::Texture *tex = context->getTexture(texture);
6494
6495 if(!tex)
6496 {
6497 return error(GL_INVALID_OPERATION);
6498 }
6499
6500 if(tex->isCompressed(textarget, level))
6501 {
6502 return error(GL_INVALID_OPERATION);
6503 }
6504
6505 switch(textarget)
6506 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006507 case GL_TEXTURE_3D:
6508 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006509 {
6510 return error(GL_INVALID_OPERATION);
6511 }
6512 break;
6513 default:
6514 return error(GL_INVALID_ENUM);
6515 }
6516
6517 if(level != 0)
6518 {
6519 return error(GL_INVALID_VALUE);
6520 }
6521 }
6522
6523 es2::Framebuffer *framebuffer = nullptr;
6524 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006525 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006526 {
6527 framebuffer = context->getReadFramebuffer();
6528 framebufferName = context->getReadFramebufferName();
6529 }
6530 else
6531 {
6532 framebuffer = context->getDrawFramebuffer();
6533 framebufferName = context->getDrawFramebufferName();
6534 }
6535
6536 if(framebufferName == 0 || !framebuffer)
6537 {
6538 return error(GL_INVALID_OPERATION);
6539 }
6540
6541 GLint clientVersion = context->getClientVersion();
6542
6543 switch(attachment)
6544 {
6545 case GL_COLOR_ATTACHMENT1:
6546 case GL_COLOR_ATTACHMENT2:
6547 case GL_COLOR_ATTACHMENT3:
6548 case GL_COLOR_ATTACHMENT4:
6549 case GL_COLOR_ATTACHMENT5:
6550 case GL_COLOR_ATTACHMENT6:
6551 case GL_COLOR_ATTACHMENT7:
6552 case GL_COLOR_ATTACHMENT8:
6553 case GL_COLOR_ATTACHMENT9:
6554 case GL_COLOR_ATTACHMENT10:
6555 case GL_COLOR_ATTACHMENT11:
6556 case GL_COLOR_ATTACHMENT12:
6557 case GL_COLOR_ATTACHMENT13:
6558 case GL_COLOR_ATTACHMENT14:
6559 case GL_COLOR_ATTACHMENT15:
6560 case GL_COLOR_ATTACHMENT16:
6561 case GL_COLOR_ATTACHMENT17:
6562 case GL_COLOR_ATTACHMENT18:
6563 case GL_COLOR_ATTACHMENT19:
6564 case GL_COLOR_ATTACHMENT20:
6565 case GL_COLOR_ATTACHMENT21:
6566 case GL_COLOR_ATTACHMENT22:
6567 case GL_COLOR_ATTACHMENT23:
6568 case GL_COLOR_ATTACHMENT24:
6569 case GL_COLOR_ATTACHMENT25:
6570 case GL_COLOR_ATTACHMENT26:
6571 case GL_COLOR_ATTACHMENT27:
6572 case GL_COLOR_ATTACHMENT28:
6573 case GL_COLOR_ATTACHMENT29:
6574 case GL_COLOR_ATTACHMENT30:
6575 case GL_COLOR_ATTACHMENT31:
6576 if(clientVersion < 3)
6577 {
6578 return error(GL_INVALID_ENUM);
6579 }
6580 // fall through
6581 case GL_COLOR_ATTACHMENT0:
6582 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6583 {
6584 return error(GL_INVALID_ENUM);
6585 }
6586 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6587 break;
6588 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6589 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6590 default:
6591 return error(GL_INVALID_ENUM);
6592 }
6593 }
6594}
6595
6596void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6597{
6598 if(egl::getClientVersion() == 1)
6599 {
6600 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6601 }
6602
6603 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6604
6605 switch(target)
6606 {
6607 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006608 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006609 case GL_TEXTURE_EXTERNAL_OES:
6610 break;
6611 default:
6612 return error(GL_INVALID_ENUM);
6613 }
6614
Nicolas Capens0bac2852016-05-07 06:09:58 -04006615 es2::Context *context = es2::getContext();
6616
6617 if(context)
6618 {
Alexis Hetu46768622018-01-16 22:09:28 -05006619 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006620
6621 if(!texture)
6622 {
6623 return error(GL_INVALID_OPERATION);
6624 }
6625
Nicolas Capens58df2f62016-06-07 14:48:56 -04006626 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006627
Nicolas Capens58df2f62016-06-07 14:48:56 -04006628 if(!eglImage)
6629 {
6630 return error(GL_INVALID_OPERATION);
6631 }
6632
6633 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006634 }
6635}
6636
6637void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6638{
6639 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6640
6641 UNIMPLEMENTED();
6642}
6643
6644GLboolean IsRenderbufferOES(GLuint renderbuffer)
6645{
6646 return IsRenderbuffer(renderbuffer);
6647}
6648
6649void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6650{
6651 BindRenderbuffer(target, renderbuffer);
6652}
6653
6654void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6655{
6656 DeleteRenderbuffers(n, renderbuffers);
6657}
6658
6659void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6660{
6661 GenRenderbuffers(n, renderbuffers);
6662}
6663
6664void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6665{
6666 RenderbufferStorage(target, internalformat, width, height);
6667}
6668
6669void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6670{
6671 GetRenderbufferParameteriv(target, pname, params);
6672}
6673
6674GLboolean IsFramebufferOES(GLuint framebuffer)
6675{
6676 return IsFramebuffer(framebuffer);
6677}
6678
6679void BindFramebufferOES(GLenum target, GLuint framebuffer)
6680{
6681 BindFramebuffer(target, framebuffer);
6682}
6683
6684void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6685{
6686 DeleteFramebuffers(n, framebuffers);
6687}
6688
6689void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6690{
6691 GenFramebuffers(n, framebuffers);
6692}
6693
6694GLenum CheckFramebufferStatusOES(GLenum target)
6695{
6696 return CheckFramebufferStatus(target);
6697}
6698
6699void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6700{
6701 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6702}
6703
6704void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6705{
6706 FramebufferTexture2D(target, attachment, textarget, texture, level);
6707}
6708
6709void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6710{
6711 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6712}
6713
6714void GenerateMipmapOES(GLenum target)
6715{
6716 GenerateMipmap(target);
6717}
6718
6719void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6720{
6721 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6722
6723 if(n < 0 || n > MAX_DRAW_BUFFERS)
6724 {
6725 return error(GL_INVALID_VALUE);
6726 }
6727
6728 es2::Context *context = es2::getContext();
6729
6730 if(context)
6731 {
6732 GLuint drawFramebufferName = context->getDrawFramebufferName();
6733
6734 if((drawFramebufferName == 0) && (n != 1))
6735 {
6736 return error(GL_INVALID_OPERATION);
6737 }
6738
6739 for(unsigned int i = 0; i < (unsigned)n; i++)
6740 {
6741 switch(bufs[i])
6742 {
6743 case GL_BACK:
6744 if(drawFramebufferName != 0)
6745 {
6746 return error(GL_INVALID_OPERATION);
6747 }
6748 break;
6749 case GL_NONE:
6750 break;
6751 case GL_COLOR_ATTACHMENT0_EXT:
6752 case GL_COLOR_ATTACHMENT1_EXT:
6753 case GL_COLOR_ATTACHMENT2_EXT:
6754 case GL_COLOR_ATTACHMENT3_EXT:
6755 case GL_COLOR_ATTACHMENT4_EXT:
6756 case GL_COLOR_ATTACHMENT5_EXT:
6757 case GL_COLOR_ATTACHMENT6_EXT:
6758 case GL_COLOR_ATTACHMENT7_EXT:
6759 case GL_COLOR_ATTACHMENT8_EXT:
6760 case GL_COLOR_ATTACHMENT9_EXT:
6761 case GL_COLOR_ATTACHMENT10_EXT:
6762 case GL_COLOR_ATTACHMENT11_EXT:
6763 case GL_COLOR_ATTACHMENT12_EXT:
6764 case GL_COLOR_ATTACHMENT13_EXT:
6765 case GL_COLOR_ATTACHMENT14_EXT:
6766 case GL_COLOR_ATTACHMENT15_EXT:
6767 {
6768 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6769
6770 if(index >= MAX_COLOR_ATTACHMENTS)
6771 {
6772 return error(GL_INVALID_OPERATION);
6773 }
6774
6775 if(index != i)
6776 {
6777 return error(GL_INVALID_OPERATION);
6778 }
6779
6780 if(drawFramebufferName == 0)
6781 {
6782 return error(GL_INVALID_OPERATION);
6783 }
6784 }
6785 break;
6786 default:
6787 return error(GL_INVALID_ENUM);
6788 }
6789 }
6790
6791 context->setFramebufferDrawBuffers(n, bufs);
6792 }
6793}
6794
6795}
6796
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006797extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006798{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006799 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006800 {
6801 const char *name;
6802 __eglMustCastToProperFunctionPointerType address;
6803 };
6804
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006805 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006806 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006807 bool operator()(const Function &a, const Function &b) const
6808 {
6809 return strcmp(a.name, b.name) < 0;
6810 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006811 };
6812
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006813 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6814 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6815 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006816 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006817 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6818
6819 FUNCTION(glActiveTexture),
6820 FUNCTION(glAttachShader),
6821 FUNCTION(glBeginQuery),
6822 FUNCTION(glBeginQueryEXT),
6823 FUNCTION(glBeginTransformFeedback),
6824 FUNCTION(glBindAttribLocation),
6825 FUNCTION(glBindBuffer),
6826 FUNCTION(glBindBufferBase),
6827 FUNCTION(glBindBufferRange),
6828 FUNCTION(glBindFramebuffer),
6829 FUNCTION(glBindFramebufferOES),
6830 FUNCTION(glBindRenderbuffer),
6831 FUNCTION(glBindRenderbufferOES),
6832 FUNCTION(glBindSampler),
6833 FUNCTION(glBindTexture),
6834 FUNCTION(glBindTransformFeedback),
6835 FUNCTION(glBindVertexArray),
6836 FUNCTION(glBlendColor),
6837 FUNCTION(glBlendEquation),
6838 FUNCTION(glBlendEquationSeparate),
6839 FUNCTION(glBlendFunc),
6840 FUNCTION(glBlendFuncSeparate),
6841 FUNCTION(glBlitFramebuffer),
6842 FUNCTION(glBlitFramebufferANGLE),
6843 FUNCTION(glBufferData),
6844 FUNCTION(glBufferSubData),
6845 FUNCTION(glCheckFramebufferStatus),
6846 FUNCTION(glCheckFramebufferStatusOES),
6847 FUNCTION(glClear),
6848 FUNCTION(glClearBufferfi),
6849 FUNCTION(glClearBufferfv),
6850 FUNCTION(glClearBufferiv),
6851 FUNCTION(glClearBufferuiv),
6852 FUNCTION(glClearColor),
6853 FUNCTION(glClearDepthf),
6854 FUNCTION(glClearStencil),
6855 FUNCTION(glClientWaitSync),
6856 FUNCTION(glColorMask),
6857 FUNCTION(glCompileShader),
6858 FUNCTION(glCompressedTexImage2D),
6859 FUNCTION(glCompressedTexImage3D),
6860 FUNCTION(glCompressedTexSubImage2D),
6861 FUNCTION(glCompressedTexSubImage3D),
6862 FUNCTION(glCopyBufferSubData),
6863 FUNCTION(glCopyTexImage2D),
6864 FUNCTION(glCopyTexSubImage2D),
6865 FUNCTION(glCopyTexSubImage3D),
6866 FUNCTION(glCreateProgram),
6867 FUNCTION(glCreateShader),
6868 FUNCTION(glCullFace),
6869 FUNCTION(glDeleteBuffers),
6870 FUNCTION(glDeleteFencesNV),
6871 FUNCTION(glDeleteFramebuffers),
6872 FUNCTION(glDeleteFramebuffersOES),
6873 FUNCTION(glDeleteProgram),
6874 FUNCTION(glDeleteQueries),
6875 FUNCTION(glDeleteQueriesEXT),
6876 FUNCTION(glDeleteRenderbuffers),
6877 FUNCTION(glDeleteRenderbuffersOES),
6878 FUNCTION(glDeleteSamplers),
6879 FUNCTION(glDeleteShader),
6880 FUNCTION(glDeleteSync),
6881 FUNCTION(glDeleteTextures),
6882 FUNCTION(glDeleteTransformFeedbacks),
6883 FUNCTION(glDeleteVertexArrays),
6884 FUNCTION(glDepthFunc),
6885 FUNCTION(glDepthMask),
6886 FUNCTION(glDepthRangef),
6887 FUNCTION(glDetachShader),
6888 FUNCTION(glDisable),
6889 FUNCTION(glDisableVertexAttribArray),
6890 FUNCTION(glDrawArrays),
6891 FUNCTION(glDrawArraysInstanced),
6892 FUNCTION(glDrawBuffers),
6893 FUNCTION(glDrawBuffersEXT),
6894 FUNCTION(glDrawElements),
6895 FUNCTION(glDrawElementsInstanced),
6896 FUNCTION(glDrawRangeElements),
6897 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6898 FUNCTION(glEGLImageTargetTexture2DOES),
6899 FUNCTION(glEnable),
6900 FUNCTION(glEnableVertexAttribArray),
6901 FUNCTION(glEndQuery),
6902 FUNCTION(glEndQueryEXT),
6903 FUNCTION(glEndTransformFeedback),
6904 FUNCTION(glFenceSync),
6905 FUNCTION(glFinish),
6906 FUNCTION(glFinishFenceNV),
6907 FUNCTION(glFlush),
6908 FUNCTION(glFlushMappedBufferRange),
6909 FUNCTION(glFramebufferRenderbuffer),
6910 FUNCTION(glFramebufferRenderbufferOES),
6911 FUNCTION(glFramebufferTexture2D),
6912 FUNCTION(glFramebufferTexture2DOES),
6913 FUNCTION(glFramebufferTextureLayer),
6914 FUNCTION(glFrontFace),
6915 FUNCTION(glGenBuffers),
6916 FUNCTION(glGenFencesNV),
6917 FUNCTION(glGenFramebuffers),
6918 FUNCTION(glGenFramebuffersOES),
6919 FUNCTION(glGenQueries),
6920 FUNCTION(glGenQueriesEXT),
6921 FUNCTION(glGenRenderbuffers),
6922 FUNCTION(glGenRenderbuffersOES),
6923 FUNCTION(glGenSamplers),
6924 FUNCTION(glGenTextures),
6925 FUNCTION(glGenTransformFeedbacks),
6926 FUNCTION(glGenVertexArrays),
6927 FUNCTION(glGenerateMipmap),
6928 FUNCTION(glGenerateMipmapOES),
6929 FUNCTION(glGetActiveAttrib),
6930 FUNCTION(glGetActiveUniform),
6931 FUNCTION(glGetActiveUniformBlockName),
6932 FUNCTION(glGetActiveUniformBlockiv),
6933 FUNCTION(glGetActiveUniformsiv),
6934 FUNCTION(glGetAttachedShaders),
6935 FUNCTION(glGetAttribLocation),
6936 FUNCTION(glGetBooleanv),
6937 FUNCTION(glGetBufferParameteri64v),
6938 FUNCTION(glGetBufferParameteriv),
6939 FUNCTION(glGetBufferPointerv),
6940 FUNCTION(glGetError),
6941 FUNCTION(glGetFenceivNV),
6942 FUNCTION(glGetFloatv),
6943 FUNCTION(glGetFragDataLocation),
6944 FUNCTION(glGetFramebufferAttachmentParameteriv),
6945 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6946 FUNCTION(glGetGraphicsResetStatusEXT),
6947 FUNCTION(glGetInteger64i_v),
6948 FUNCTION(glGetInteger64v),
6949 FUNCTION(glGetIntegeri_v),
6950 FUNCTION(glGetIntegerv),
6951 FUNCTION(glGetInternalformativ),
6952 FUNCTION(glGetProgramBinary),
6953 FUNCTION(glGetProgramInfoLog),
6954 FUNCTION(glGetProgramiv),
6955 FUNCTION(glGetQueryObjectuiv),
6956 FUNCTION(glGetQueryObjectuivEXT),
6957 FUNCTION(glGetQueryiv),
6958 FUNCTION(glGetQueryivEXT),
6959 FUNCTION(glGetRenderbufferParameteriv),
6960 FUNCTION(glGetRenderbufferParameterivOES),
6961 FUNCTION(glGetSamplerParameterfv),
6962 FUNCTION(glGetSamplerParameteriv),
6963 FUNCTION(glGetShaderInfoLog),
6964 FUNCTION(glGetShaderPrecisionFormat),
6965 FUNCTION(glGetShaderSource),
6966 FUNCTION(glGetShaderiv),
6967 FUNCTION(glGetString),
6968 FUNCTION(glGetStringi),
6969 FUNCTION(glGetSynciv),
6970 FUNCTION(glGetTexParameterfv),
6971 FUNCTION(glGetTexParameteriv),
6972 FUNCTION(glGetTransformFeedbackVarying),
6973 FUNCTION(glGetUniformBlockIndex),
6974 FUNCTION(glGetUniformIndices),
6975 FUNCTION(glGetUniformLocation),
6976 FUNCTION(glGetUniformfv),
6977 FUNCTION(glGetUniformiv),
6978 FUNCTION(glGetUniformuiv),
6979 FUNCTION(glGetVertexAttribIiv),
6980 FUNCTION(glGetVertexAttribIuiv),
6981 FUNCTION(glGetVertexAttribPointerv),
6982 FUNCTION(glGetVertexAttribfv),
6983 FUNCTION(glGetVertexAttribiv),
6984 FUNCTION(glGetnUniformfvEXT),
6985 FUNCTION(glGetnUniformivEXT),
6986 FUNCTION(glHint),
6987 FUNCTION(glInvalidateFramebuffer),
6988 FUNCTION(glInvalidateSubFramebuffer),
6989 FUNCTION(glIsBuffer),
6990 FUNCTION(glIsEnabled),
6991 FUNCTION(glIsFenceNV),
6992 FUNCTION(glIsFramebuffer),
6993 FUNCTION(glIsFramebufferOES),
6994 FUNCTION(glIsProgram),
6995 FUNCTION(glIsQuery),
6996 FUNCTION(glIsQueryEXT),
6997 FUNCTION(glIsRenderbuffer),
6998 FUNCTION(glIsRenderbufferOES),
6999 FUNCTION(glIsSampler),
7000 FUNCTION(glIsShader),
7001 FUNCTION(glIsSync),
7002 FUNCTION(glIsTexture),
7003 FUNCTION(glIsTransformFeedback),
7004 FUNCTION(glIsVertexArray),
7005 FUNCTION(glLineWidth),
7006 FUNCTION(glLinkProgram),
7007 FUNCTION(glMapBufferRange),
7008 FUNCTION(glPauseTransformFeedback),
7009 FUNCTION(glPixelStorei),
7010 FUNCTION(glPolygonOffset),
7011 FUNCTION(glProgramBinary),
7012 FUNCTION(glProgramParameteri),
7013 FUNCTION(glReadBuffer),
7014 FUNCTION(glReadPixels),
7015 FUNCTION(glReadnPixelsEXT),
7016 FUNCTION(glReleaseShaderCompiler),
7017 FUNCTION(glRenderbufferStorage),
7018 FUNCTION(glRenderbufferStorageMultisample),
7019 FUNCTION(glRenderbufferStorageMultisampleANGLE),
7020 FUNCTION(glRenderbufferStorageOES),
7021 FUNCTION(glResumeTransformFeedback),
7022 FUNCTION(glSampleCoverage),
7023 FUNCTION(glSamplerParameterf),
7024 FUNCTION(glSamplerParameterfv),
7025 FUNCTION(glSamplerParameteri),
7026 FUNCTION(glSamplerParameteriv),
7027 FUNCTION(glScissor),
7028 FUNCTION(glSetFenceNV),
7029 FUNCTION(glShaderBinary),
7030 FUNCTION(glShaderSource),
7031 FUNCTION(glStencilFunc),
7032 FUNCTION(glStencilFuncSeparate),
7033 FUNCTION(glStencilMask),
7034 FUNCTION(glStencilMaskSeparate),
7035 FUNCTION(glStencilOp),
7036 FUNCTION(glStencilOpSeparate),
7037 FUNCTION(glTestFenceNV),
7038 FUNCTION(glTexImage2D),
7039 FUNCTION(glTexImage3D),
7040 FUNCTION(glTexImage3DOES),
7041 FUNCTION(glTexParameterf),
7042 FUNCTION(glTexParameterfv),
7043 FUNCTION(glTexParameteri),
7044 FUNCTION(glTexParameteriv),
7045 FUNCTION(glTexStorage2D),
7046 FUNCTION(glTexStorage3D),
7047 FUNCTION(glTexSubImage2D),
7048 FUNCTION(glTexSubImage3D),
7049 FUNCTION(glTransformFeedbackVaryings),
7050 FUNCTION(glUniform1f),
7051 FUNCTION(glUniform1fv),
7052 FUNCTION(glUniform1i),
7053 FUNCTION(glUniform1iv),
7054 FUNCTION(glUniform1ui),
7055 FUNCTION(glUniform1uiv),
7056 FUNCTION(glUniform2f),
7057 FUNCTION(glUniform2fv),
7058 FUNCTION(glUniform2i),
7059 FUNCTION(glUniform2iv),
7060 FUNCTION(glUniform2ui),
7061 FUNCTION(glUniform2uiv),
7062 FUNCTION(glUniform3f),
7063 FUNCTION(glUniform3fv),
7064 FUNCTION(glUniform3i),
7065 FUNCTION(glUniform3iv),
7066 FUNCTION(glUniform3ui),
7067 FUNCTION(glUniform3uiv),
7068 FUNCTION(glUniform4f),
7069 FUNCTION(glUniform4fv),
7070 FUNCTION(glUniform4i),
7071 FUNCTION(glUniform4iv),
7072 FUNCTION(glUniform4ui),
7073 FUNCTION(glUniform4uiv),
7074 FUNCTION(glUniformBlockBinding),
7075 FUNCTION(glUniformMatrix2fv),
7076 FUNCTION(glUniformMatrix2x3fv),
7077 FUNCTION(glUniformMatrix2x4fv),
7078 FUNCTION(glUniformMatrix3fv),
7079 FUNCTION(glUniformMatrix3x2fv),
7080 FUNCTION(glUniformMatrix3x4fv),
7081 FUNCTION(glUniformMatrix4fv),
7082 FUNCTION(glUniformMatrix4x2fv),
7083 FUNCTION(glUniformMatrix4x3fv),
7084 FUNCTION(glUnmapBuffer),
7085 FUNCTION(glUseProgram),
7086 FUNCTION(glValidateProgram),
7087 FUNCTION(glVertexAttrib1f),
7088 FUNCTION(glVertexAttrib1fv),
7089 FUNCTION(glVertexAttrib2f),
7090 FUNCTION(glVertexAttrib2fv),
7091 FUNCTION(glVertexAttrib3f),
7092 FUNCTION(glVertexAttrib3fv),
7093 FUNCTION(glVertexAttrib4f),
7094 FUNCTION(glVertexAttrib4fv),
7095 FUNCTION(glVertexAttribDivisor),
7096 FUNCTION(glVertexAttribI4i),
7097 FUNCTION(glVertexAttribI4iv),
7098 FUNCTION(glVertexAttribI4ui),
7099 FUNCTION(glVertexAttribI4uiv),
7100 FUNCTION(glVertexAttribIPointer),
7101 FUNCTION(glVertexAttribPointer),
7102 FUNCTION(glViewport),
7103 FUNCTION(glWaitSync),
7104
7105 #undef FUNCTION
7106 };
7107
7108 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
7109 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
7110
7111 Function needle;
7112 needle.name = procname;
7113
7114 if(procname && strncmp("gl", procname, 2) == 0)
7115 {
7116 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
7117 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04007118 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01007119 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04007120 }
7121 }
7122
7123 return nullptr;
7124}