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