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