blob: 507f9894c64914e304c6ca58f7cb74ed2c687147 [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
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500792 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400793 {
794 return error(GL_INVALID_VALUE);
795 }
796
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500797 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500798 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500799 {
800 return error(validationError);
801 }
802
Alexis Hetu46768622018-01-16 22:09:28 -0500803 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400804 {
Alexis Hetu46768622018-01-16 22:09:28 -0500805 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400806
807 if(!texture)
808 {
809 return error(GL_INVALID_OPERATION);
810 }
811
812 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
813 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500814 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400815 {
816 es2::TextureCubeMap *texture = context->getTextureCubeMap();
817
818 if(!texture)
819 {
820 return error(GL_INVALID_OPERATION);
821 }
822
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500823 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400824 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500825 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400826 }
827}
828
829void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
830 GLenum format, GLsizei imageSize, const GLvoid* data)
831{
832 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
833 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
834 "GLsizei imageSize = %d, const GLvoid* data = %p)",
835 target, level, xoffset, yoffset, width, height, format, imageSize, data);
836
837 if(!es2::IsTextureTarget(target))
838 {
839 return error(GL_INVALID_ENUM);
840 }
841
842 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
843 {
844 return error(GL_INVALID_VALUE);
845 }
846
847 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
848 {
849 return error(GL_INVALID_VALUE);
850 }
851
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500852 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400853 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500854 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400855 }
856
857 es2::Context *context = es2::getContext();
858
859 if(context)
860 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400861 if(xoffset % 4 != 0 || yoffset % 4 != 0)
862 {
863 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
864 return error(GL_INVALID_OPERATION);
865 }
866
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500867 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500868 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500869 {
870 return error(validationError);
871 }
872
Alexis Hetu46768622018-01-16 22:09:28 -0500873 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400874 {
Alexis Hetu46768622018-01-16 22:09:28 -0500875 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400876
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500877 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -0500878 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400879 {
880 return error(validationError);
881 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500882
Nicolas Capenseab70762018-02-06 16:49:36 -0500883 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400884 }
885 else if(es2::IsCubemapTextureTarget(target))
886 {
887 es2::TextureCubeMap *texture = context->getTextureCubeMap();
888
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());
Nicolas Capense65f5642018-02-26 17:47:06 -0500890 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400891 {
892 return error(validationError);
893 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500894
Nicolas Capenseab70762018-02-06 16:49:36 -0500895 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400896 }
897 else UNREACHABLE(target);
898 }
899}
900
901void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
902{
903 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
904 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
905 target, level, internalformat, x, y, width, height, border);
906
907 if(!validImageSize(level, width, height))
908 {
909 return error(GL_INVALID_VALUE);
910 }
911
912 if(border != 0)
913 {
914 return error(GL_INVALID_VALUE);
915 }
916
917 es2::Context *context = es2::getContext();
918
919 if(context)
920 {
921 switch(target)
922 {
923 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -0500924 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400925 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
926 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
927 {
928 return error(GL_INVALID_VALUE);
929 }
930 break;
931 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
932 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
933 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
934 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
935 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
936 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
937 if(width != height)
938 {
939 return error(GL_INVALID_VALUE);
940 }
941
942 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
943 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
944 {
945 return error(GL_INVALID_VALUE);
946 }
947 break;
948 default:
949 return error(GL_INVALID_ENUM);
950 }
951
952 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
953
954 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
955 {
956 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
957 }
958
959 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
960
961 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
962 {
963 return error(GL_INVALID_OPERATION);
964 }
965
966 GLenum colorbufferFormat = source->getFormat();
967
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500968 // Determine the sized internal format.
969 if(gl::IsUnsizedInternalFormat(internalformat))
970 {
971 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
972 {
973 internalformat = colorbufferFormat;
974 }
975 else if(GetRedSize(colorbufferFormat) == 8)
976 {
977 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
978 }
979 else
980 {
981 UNIMPLEMENTED();
982
983 return error(GL_INVALID_OPERATION);
984 }
985 }
986
Nicolas Capens8f215a42018-02-02 13:25:53 -0500987 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400988 {
989 return;
990 }
991
Alexis Hetu46768622018-01-16 22:09:28 -0500992 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400993 {
Alexis Hetu46768622018-01-16 22:09:28 -0500994 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400995
996 if(!texture)
997 {
998 return error(GL_INVALID_OPERATION);
999 }
1000
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001001 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001002 }
1003 else if(es2::IsCubemapTextureTarget(target))
1004 {
1005 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1006
1007 if(!texture)
1008 {
1009 return error(GL_INVALID_OPERATION);
1010 }
1011
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001012 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001013 }
1014 else UNREACHABLE(target);
1015 }
1016}
1017
1018void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1019{
1020 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1021 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1022 target, level, xoffset, yoffset, x, y, width, height);
1023
1024 if(!es2::IsTextureTarget(target))
1025 {
1026 return error(GL_INVALID_ENUM);
1027 }
1028
1029 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1030 {
1031 return error(GL_INVALID_VALUE);
1032 }
1033
1034 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1035 {
1036 return error(GL_INVALID_VALUE);
1037 }
1038
1039 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1040 {
1041 return error(GL_INVALID_VALUE);
1042 }
1043
Nicolas Capens0bac2852016-05-07 06:09:58 -04001044 es2::Context *context = es2::getContext();
1045
1046 if(context)
1047 {
1048 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1049
1050 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1051 {
1052 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1053 }
1054
1055 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1056
1057 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1058 {
1059 return error(GL_INVALID_OPERATION);
1060 }
1061
1062 es2::Texture *texture = nullptr;
1063
Alexis Hetu46768622018-01-16 22:09:28 -05001064 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001065 {
Alexis Hetu46768622018-01-16 22:09:28 -05001066 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001067 }
1068 else if(es2::IsCubemapTextureTarget(target))
1069 {
1070 texture = context->getTextureCubeMap();
1071 }
1072 else UNREACHABLE(target);
1073
Nicolas Capensd2faaa92017-12-04 11:15:51 -05001074 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05001075 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001076 {
1077 return error(validationError);
1078 }
1079
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001080 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001081 }
1082}
1083
1084GLuint CreateProgram(void)
1085{
1086 TRACE("()");
1087
1088 es2::Context *context = es2::getContext();
1089
1090 if(context)
1091 {
1092 return context->createProgram();
1093 }
1094
1095 return 0;
1096}
1097
1098GLuint CreateShader(GLenum type)
1099{
1100 TRACE("(GLenum type = 0x%X)", type);
1101
1102 es2::Context *context = es2::getContext();
1103
1104 if(context)
1105 {
1106 switch(type)
1107 {
1108 case GL_FRAGMENT_SHADER:
1109 case GL_VERTEX_SHADER:
1110 return context->createShader(type);
1111 default:
1112 return error(GL_INVALID_ENUM, 0);
1113 }
1114 }
1115
1116 return 0;
1117}
1118
1119void CullFace(GLenum mode)
1120{
1121 TRACE("(GLenum mode = 0x%X)", mode);
1122
1123 switch(mode)
1124 {
1125 case GL_FRONT:
1126 case GL_BACK:
1127 case GL_FRONT_AND_BACK:
1128 {
1129 es2::Context *context = es2::getContext();
1130
1131 if(context)
1132 {
1133 context->setCullMode(mode);
1134 }
1135 }
1136 break;
1137 default:
1138 return error(GL_INVALID_ENUM);
1139 }
1140}
1141
1142void DeleteBuffers(GLsizei n, const GLuint* buffers)
1143{
1144 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1145
1146 if(n < 0)
1147 {
1148 return error(GL_INVALID_VALUE);
1149 }
1150
1151 es2::Context *context = es2::getContext();
1152
1153 if(context)
1154 {
1155 for(int i = 0; i < n; i++)
1156 {
1157 context->deleteBuffer(buffers[i]);
1158 }
1159 }
1160}
1161
1162void DeleteFencesNV(GLsizei n, const GLuint* fences)
1163{
1164 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1165
1166 if(n < 0)
1167 {
1168 return error(GL_INVALID_VALUE);
1169 }
1170
1171 es2::Context *context = es2::getContext();
1172
1173 if(context)
1174 {
1175 for(int i = 0; i < n; i++)
1176 {
1177 context->deleteFence(fences[i]);
1178 }
1179 }
1180}
1181
1182void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1183{
1184 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1185
1186 if(n < 0)
1187 {
1188 return error(GL_INVALID_VALUE);
1189 }
1190
1191 es2::Context *context = es2::getContext();
1192
1193 if(context)
1194 {
1195 for(int i = 0; i < n; i++)
1196 {
1197 if(framebuffers[i] != 0)
1198 {
1199 context->deleteFramebuffer(framebuffers[i]);
1200 }
1201 }
1202 }
1203}
1204
1205void DeleteProgram(GLuint program)
1206{
1207 TRACE("(GLuint program = %d)", program);
1208
1209 if(program == 0)
1210 {
1211 return;
1212 }
1213
1214 es2::Context *context = es2::getContext();
1215
1216 if(context)
1217 {
1218 if(!context->getProgram(program))
1219 {
1220 if(context->getShader(program))
1221 {
1222 return error(GL_INVALID_OPERATION);
1223 }
1224 else
1225 {
1226 return error(GL_INVALID_VALUE);
1227 }
1228 }
1229
1230 context->deleteProgram(program);
1231 }
1232}
1233
1234void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1235{
1236 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1237
1238 if(n < 0)
1239 {
1240 return error(GL_INVALID_VALUE);
1241 }
1242
1243 es2::Context *context = es2::getContext();
1244
1245 if(context)
1246 {
1247 for(int i = 0; i < n; i++)
1248 {
1249 context->deleteQuery(ids[i]);
1250 }
1251 }
1252}
1253
1254void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1255{
1256 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1257
1258 if(n < 0)
1259 {
1260 return error(GL_INVALID_VALUE);
1261 }
1262
1263 es2::Context *context = es2::getContext();
1264
1265 if(context)
1266 {
1267 for(int i = 0; i < n; i++)
1268 {
1269 context->deleteRenderbuffer(renderbuffers[i]);
1270 }
1271 }
1272}
1273
1274void DeleteShader(GLuint shader)
1275{
1276 TRACE("(GLuint shader = %d)", shader);
1277
1278 if(shader == 0)
1279 {
1280 return;
1281 }
1282
1283 es2::Context *context = es2::getContext();
1284
1285 if(context)
1286 {
1287 if(!context->getShader(shader))
1288 {
1289 if(context->getProgram(shader))
1290 {
1291 return error(GL_INVALID_OPERATION);
1292 }
1293 else
1294 {
1295 return error(GL_INVALID_VALUE);
1296 }
1297 }
1298
1299 context->deleteShader(shader);
1300 }
1301}
1302
1303void DeleteTextures(GLsizei n, const GLuint* textures)
1304{
1305 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1306
1307 if(n < 0)
1308 {
1309 return error(GL_INVALID_VALUE);
1310 }
1311
1312 es2::Context *context = es2::getContext();
1313
1314 if(context)
1315 {
1316 for(int i = 0; i < n; i++)
1317 {
1318 if(textures[i] != 0)
1319 {
1320 context->deleteTexture(textures[i]);
1321 }
1322 }
1323 }
1324}
1325
1326void DepthFunc(GLenum func)
1327{
1328 TRACE("(GLenum func = 0x%X)", func);
1329
1330 switch(func)
1331 {
1332 case GL_NEVER:
1333 case GL_ALWAYS:
1334 case GL_LESS:
1335 case GL_LEQUAL:
1336 case GL_EQUAL:
1337 case GL_GREATER:
1338 case GL_GEQUAL:
1339 case GL_NOTEQUAL:
1340 break;
1341 default:
1342 return error(GL_INVALID_ENUM);
1343 }
1344
1345 es2::Context *context = es2::getContext();
1346
1347 if(context)
1348 {
1349 context->setDepthFunc(func);
1350 }
1351}
1352
1353void DepthMask(GLboolean flag)
1354{
1355 TRACE("(GLboolean flag = %d)", flag);
1356
1357 es2::Context *context = es2::getContext();
1358
1359 if(context)
1360 {
1361 context->setDepthMask(flag != GL_FALSE);
1362 }
1363}
1364
1365void DepthRangef(GLclampf zNear, GLclampf zFar)
1366{
1367 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1368
1369 es2::Context *context = es2::getContext();
1370
1371 if(context)
1372 {
1373 context->setDepthRange(zNear, zFar);
1374 }
1375}
1376
1377void DetachShader(GLuint program, GLuint shader)
1378{
1379 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1380
1381 es2::Context *context = es2::getContext();
1382
1383 if(context)
1384 {
1385
1386 es2::Program *programObject = context->getProgram(program);
1387 es2::Shader *shaderObject = context->getShader(shader);
1388
1389 if(!programObject)
1390 {
1391 es2::Shader *shaderByProgramHandle;
1392 shaderByProgramHandle = context->getShader(program);
1393 if(!shaderByProgramHandle)
1394 {
1395 return error(GL_INVALID_VALUE);
1396 }
1397 else
1398 {
1399 return error(GL_INVALID_OPERATION);
1400 }
1401 }
1402
1403 if(!shaderObject)
1404 {
1405 es2::Program *programByShaderHandle = context->getProgram(shader);
1406 if(!programByShaderHandle)
1407 {
1408 return error(GL_INVALID_VALUE);
1409 }
1410 else
1411 {
1412 return error(GL_INVALID_OPERATION);
1413 }
1414 }
1415
1416 if(!programObject->detachShader(shaderObject))
1417 {
1418 return error(GL_INVALID_OPERATION);
1419 }
1420 }
1421}
1422
1423void Disable(GLenum cap)
1424{
1425 TRACE("(GLenum cap = 0x%X)", cap);
1426
1427 es2::Context *context = es2::getContext();
1428
1429 if(context)
1430 {
1431 switch(cap)
1432 {
1433 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1434 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1435 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1436 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1437 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1438 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1439 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1440 case GL_BLEND: context->setBlendEnabled(false); break;
1441 case GL_DITHER: context->setDitherEnabled(false); break;
1442 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1443 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1444 default:
1445 return error(GL_INVALID_ENUM);
1446 }
1447 }
1448}
1449
1450void DisableVertexAttribArray(GLuint index)
1451{
1452 TRACE("(GLuint index = %d)", index);
1453
1454 if(index >= es2::MAX_VERTEX_ATTRIBS)
1455 {
1456 return error(GL_INVALID_VALUE);
1457 }
1458
1459 es2::Context *context = es2::getContext();
1460
1461 if(context)
1462 {
1463 context->setVertexAttribArrayEnabled(index, false);
1464 }
1465}
1466
1467void DrawArrays(GLenum mode, GLint first, GLsizei count)
1468{
1469 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1470
1471 switch(mode)
1472 {
1473 case GL_POINTS:
1474 case GL_LINES:
1475 case GL_LINE_LOOP:
1476 case GL_LINE_STRIP:
1477 case GL_TRIANGLES:
1478 case GL_TRIANGLE_FAN:
1479 case GL_TRIANGLE_STRIP:
1480 break;
1481 default:
1482 return error(GL_INVALID_ENUM);
1483 }
1484
1485 if(count < 0 || first < 0)
1486 {
1487 return error(GL_INVALID_VALUE);
1488 }
1489
1490 es2::Context *context = es2::getContext();
1491
1492 if(context)
1493 {
1494 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1495 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1496 {
1497 return error(GL_INVALID_OPERATION);
1498 }
1499
1500 context->drawArrays(mode, first, count);
1501 }
1502}
1503
1504void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1505{
1506 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1507 mode, count, type, indices);
1508
1509 switch(mode)
1510 {
1511 case GL_POINTS:
1512 case GL_LINES:
1513 case GL_LINE_LOOP:
1514 case GL_LINE_STRIP:
1515 case GL_TRIANGLES:
1516 case GL_TRIANGLE_FAN:
1517 case GL_TRIANGLE_STRIP:
1518 break;
1519 default:
1520 return error(GL_INVALID_ENUM);
1521 }
1522
1523 if(count < 0)
1524 {
1525 return error(GL_INVALID_VALUE);
1526 }
1527
1528 es2::Context *context = es2::getContext();
1529
1530 if(context)
1531 {
1532 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1533 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1534 {
1535 return error(GL_INVALID_OPERATION);
1536 }
1537
1538 switch(type)
1539 {
1540 case GL_UNSIGNED_BYTE:
1541 case GL_UNSIGNED_SHORT:
1542 case GL_UNSIGNED_INT:
1543 break;
1544 default:
1545 return error(GL_INVALID_ENUM);
1546 }
1547
1548 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1549 }
1550}
1551
1552void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1553{
1554 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1555 mode, first, count, instanceCount);
1556
1557 switch(mode)
1558 {
1559 case GL_POINTS:
1560 case GL_LINES:
1561 case GL_LINE_LOOP:
1562 case GL_LINE_STRIP:
1563 case GL_TRIANGLES:
1564 case GL_TRIANGLE_FAN:
1565 case GL_TRIANGLE_STRIP:
1566 break;
1567 default:
1568 return error(GL_INVALID_ENUM);
1569 }
1570
1571 if(count < 0 || instanceCount < 0)
1572 {
1573 return error(GL_INVALID_VALUE);
1574 }
1575
1576 es2::Context *context = es2::getContext();
1577
1578 if(context)
1579 {
1580 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1581 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1582 {
1583 return error(GL_INVALID_OPERATION);
1584 }
1585
1586 context->drawArrays(mode, first, count, instanceCount);
1587 }
1588}
1589
1590void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1591{
1592 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1593 mode, count, type, indices, instanceCount);
1594
1595 switch(mode)
1596 {
1597 case GL_POINTS:
1598 case GL_LINES:
1599 case GL_LINE_LOOP:
1600 case GL_LINE_STRIP:
1601 case GL_TRIANGLES:
1602 case GL_TRIANGLE_FAN:
1603 case GL_TRIANGLE_STRIP:
1604 break;
1605 default:
1606 return error(GL_INVALID_ENUM);
1607 }
1608
1609 switch(type)
1610 {
1611 case GL_UNSIGNED_BYTE:
1612 case GL_UNSIGNED_SHORT:
1613 case GL_UNSIGNED_INT:
1614 break;
1615 default:
1616 return error(GL_INVALID_ENUM);
1617 }
1618
1619 if(count < 0 || instanceCount < 0)
1620 {
1621 return error(GL_INVALID_VALUE);
1622 }
1623
1624 es2::Context *context = es2::getContext();
1625
1626 if(context)
1627 {
1628 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1629 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1630 {
1631 return error(GL_INVALID_OPERATION);
1632 }
1633
1634 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1635 }
1636}
1637
1638void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1639{
1640 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1641
1642 es2::Context *context = es2::getContext();
1643
1644 if(context)
1645 {
1646 if(index >= es2::MAX_VERTEX_ATTRIBS)
1647 {
1648 return error(GL_INVALID_VALUE);
1649 }
1650
1651 context->setVertexAttribDivisor(index, divisor);
1652 }
1653}
1654
1655void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1656{
1657 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1658 mode, first, count, instanceCount);
1659
1660 switch(mode)
1661 {
1662 case GL_POINTS:
1663 case GL_LINES:
1664 case GL_LINE_LOOP:
1665 case GL_LINE_STRIP:
1666 case GL_TRIANGLES:
1667 case GL_TRIANGLE_FAN:
1668 case GL_TRIANGLE_STRIP:
1669 break;
1670 default:
1671 return error(GL_INVALID_ENUM);
1672 }
1673
1674 if(count < 0 || instanceCount < 0)
1675 {
1676 return error(GL_INVALID_VALUE);
1677 }
1678
1679 es2::Context *context = es2::getContext();
1680
1681 if(context)
1682 {
1683 if(!context->hasZeroDivisor())
1684 {
1685 return error(GL_INVALID_OPERATION);
1686 }
1687
1688 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1689 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1690 {
1691 return error(GL_INVALID_OPERATION);
1692 }
1693
1694 context->drawArrays(mode, first, count, instanceCount);
1695 }
1696}
1697
1698void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1699{
1700 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1701 mode, count, type, indices, instanceCount);
1702
1703 switch(mode)
1704 {
1705 case GL_POINTS:
1706 case GL_LINES:
1707 case GL_LINE_LOOP:
1708 case GL_LINE_STRIP:
1709 case GL_TRIANGLES:
1710 case GL_TRIANGLE_FAN:
1711 case GL_TRIANGLE_STRIP:
1712 break;
1713 default:
1714 return error(GL_INVALID_ENUM);
1715 }
1716
1717 switch(type)
1718 {
1719 case GL_UNSIGNED_BYTE:
1720 case GL_UNSIGNED_SHORT:
1721 case GL_UNSIGNED_INT:
1722 break;
1723 default:
1724 return error(GL_INVALID_ENUM);
1725 }
1726
1727 if(count < 0 || instanceCount < 0)
1728 {
1729 return error(GL_INVALID_VALUE);
1730 }
1731
1732 es2::Context *context = es2::getContext();
1733
1734 if(context)
1735 {
1736 if(!context->hasZeroDivisor())
1737 {
1738 return error(GL_INVALID_OPERATION);
1739 }
1740
1741 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1742 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1743 {
1744 return error(GL_INVALID_OPERATION);
1745 }
1746
1747 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1748 }
1749}
1750
1751void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1752{
1753 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1754
1755 es2::Context *context = es2::getContext();
1756
1757 if(context)
1758 {
1759 if(index >= MAX_VERTEX_ATTRIBS)
1760 {
1761 return error(GL_INVALID_VALUE);
1762 }
1763
1764 context->setVertexAttribDivisor(index, divisor);
1765 }
1766}
1767
1768void Enable(GLenum cap)
1769{
1770 TRACE("(GLenum cap = 0x%X)", cap);
1771
1772 es2::Context *context = es2::getContext();
1773
1774 if(context)
1775 {
1776 switch(cap)
1777 {
1778 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1779 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1780 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1781 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1782 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1783 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1784 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1785 case GL_BLEND: context->setBlendEnabled(true); break;
1786 case GL_DITHER: context->setDitherEnabled(true); break;
1787 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1788 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1789 default:
1790 return error(GL_INVALID_ENUM);
1791 }
1792 }
1793}
1794
1795void EnableVertexAttribArray(GLuint index)
1796{
1797 TRACE("(GLuint index = %d)", index);
1798
1799 if(index >= es2::MAX_VERTEX_ATTRIBS)
1800 {
1801 return error(GL_INVALID_VALUE);
1802 }
1803
1804 es2::Context *context = es2::getContext();
1805
1806 if(context)
1807 {
1808 context->setVertexAttribArrayEnabled(index, true);
1809 }
1810}
1811
1812void EndQueryEXT(GLenum target)
1813{
1814 TRACE("GLenum target = 0x%X)", target);
1815
1816 switch(target)
1817 {
1818 case GL_ANY_SAMPLES_PASSED_EXT:
1819 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1820 break;
1821 default:
1822 return error(GL_INVALID_ENUM);
1823 }
1824
1825 es2::Context *context = es2::getContext();
1826
1827 if(context)
1828 {
1829 context->endQuery(target);
1830 }
1831}
1832
1833void FinishFenceNV(GLuint fence)
1834{
1835 TRACE("(GLuint fence = %d)", fence);
1836
1837 es2::Context *context = es2::getContext();
1838
1839 if(context)
1840 {
1841 es2::Fence *fenceObject = context->getFence(fence);
1842
1843 if(!fenceObject)
1844 {
1845 return error(GL_INVALID_OPERATION);
1846 }
1847
1848 fenceObject->finishFence();
1849 }
1850}
1851
1852void Finish(void)
1853{
1854 TRACE("()");
1855
1856 es2::Context *context = es2::getContext();
1857
1858 if(context)
1859 {
1860 context->finish();
1861 }
1862}
1863
1864void Flush(void)
1865{
1866 TRACE("()");
1867
1868 es2::Context *context = es2::getContext();
1869
1870 if(context)
1871 {
1872 context->flush();
1873 }
1874}
1875
1876void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1877{
1878 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1879 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1880
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001881 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001882 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1883 {
1884 return error(GL_INVALID_ENUM);
1885 }
1886
1887 es2::Context *context = es2::getContext();
1888
1889 if(context)
1890 {
1891 es2::Framebuffer *framebuffer = nullptr;
1892 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001893 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001894 {
1895 framebuffer = context->getReadFramebuffer();
1896 framebufferName = context->getReadFramebufferName();
1897 }
1898 else
1899 {
1900 framebuffer = context->getDrawFramebuffer();
1901 framebufferName = context->getDrawFramebufferName();
1902 }
1903
1904 if(!framebuffer || framebufferName == 0)
1905 {
1906 return error(GL_INVALID_OPERATION);
1907 }
1908
1909 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1910 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1911 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1912 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1913 if(renderbuffer != 0)
1914 {
1915 if(!context->getRenderbuffer(renderbuffer))
1916 {
1917 return error(GL_INVALID_OPERATION);
1918 }
1919 }
1920
1921 GLint clientVersion = context->getClientVersion();
1922
1923 switch(attachment)
1924 {
1925 case GL_COLOR_ATTACHMENT0:
1926 case GL_COLOR_ATTACHMENT1:
1927 case GL_COLOR_ATTACHMENT2:
1928 case GL_COLOR_ATTACHMENT3:
1929 case GL_COLOR_ATTACHMENT4:
1930 case GL_COLOR_ATTACHMENT5:
1931 case GL_COLOR_ATTACHMENT6:
1932 case GL_COLOR_ATTACHMENT7:
1933 case GL_COLOR_ATTACHMENT8:
1934 case GL_COLOR_ATTACHMENT9:
1935 case GL_COLOR_ATTACHMENT10:
1936 case GL_COLOR_ATTACHMENT11:
1937 case GL_COLOR_ATTACHMENT12:
1938 case GL_COLOR_ATTACHMENT13:
1939 case GL_COLOR_ATTACHMENT14:
1940 case GL_COLOR_ATTACHMENT15:
1941 case GL_COLOR_ATTACHMENT16:
1942 case GL_COLOR_ATTACHMENT17:
1943 case GL_COLOR_ATTACHMENT18:
1944 case GL_COLOR_ATTACHMENT19:
1945 case GL_COLOR_ATTACHMENT20:
1946 case GL_COLOR_ATTACHMENT21:
1947 case GL_COLOR_ATTACHMENT22:
1948 case GL_COLOR_ATTACHMENT23:
1949 case GL_COLOR_ATTACHMENT24:
1950 case GL_COLOR_ATTACHMENT25:
1951 case GL_COLOR_ATTACHMENT26:
1952 case GL_COLOR_ATTACHMENT27:
1953 case GL_COLOR_ATTACHMENT28:
1954 case GL_COLOR_ATTACHMENT29:
1955 case GL_COLOR_ATTACHMENT30:
1956 case GL_COLOR_ATTACHMENT31:
1957 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1958 {
1959 return error(GL_INVALID_ENUM);
1960 }
1961 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1962 break;
1963 case GL_DEPTH_ATTACHMENT:
1964 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1965 break;
1966 case GL_STENCIL_ATTACHMENT:
1967 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1968 break;
1969 case GL_DEPTH_STENCIL_ATTACHMENT:
1970 if(clientVersion >= 3)
1971 {
1972 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1973 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1974 break;
1975 }
1976 else return error(GL_INVALID_ENUM);
1977 default:
1978 return error(GL_INVALID_ENUM);
1979 }
1980 }
1981}
1982
1983void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1984{
1985 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1986 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1987
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001988 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001989 {
1990 return error(GL_INVALID_ENUM);
1991 }
1992
1993 es2::Context *context = es2::getContext();
1994
1995 if(context)
1996 {
Nicolas Capensd5401e22017-03-16 17:32:43 -04001997 GLint clientVersion = context->getClientVersion();
1998
Nicolas Capens0bac2852016-05-07 06:09:58 -04001999 if(texture == 0)
2000 {
2001 textarget = GL_NONE;
2002 }
2003 else
2004 {
2005 es2::Texture *tex = context->getTexture(texture);
2006
2007 if(!tex)
2008 {
2009 return error(GL_INVALID_OPERATION);
2010 }
2011
2012 switch(textarget)
2013 {
2014 case GL_TEXTURE_2D:
2015 if(tex->getTarget() != GL_TEXTURE_2D)
2016 {
2017 return error(GL_INVALID_OPERATION);
2018 }
2019 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002020 case GL_TEXTURE_RECTANGLE_ARB:
2021 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
2022 {
2023 return error(GL_INVALID_OPERATION);
2024 }
2025 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002026 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2027 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2028 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2029 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2030 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2031 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2032 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2033 {
2034 return error(GL_INVALID_OPERATION);
2035 }
2036 break;
2037 default:
2038 return error(GL_INVALID_ENUM);
2039 }
2040
Nicolas Capensd5401e22017-03-16 17:32:43 -04002041 if((level != 0) && (clientVersion < 3))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002042 {
2043 return error(GL_INVALID_VALUE);
2044 }
2045
2046 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2047 {
2048 return error(GL_INVALID_VALUE);
2049 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002050
2051 if(tex->isCompressed(textarget, level))
2052 {
2053 return error(GL_INVALID_OPERATION);
2054 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002055 }
2056
2057 es2::Framebuffer *framebuffer = nullptr;
2058 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002059 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002060 {
2061 framebuffer = context->getReadFramebuffer();
2062 framebufferName = context->getReadFramebufferName();
2063 }
2064 else
2065 {
2066 framebuffer = context->getDrawFramebuffer();
2067 framebufferName = context->getDrawFramebufferName();
2068 }
2069
2070 if(framebufferName == 0 || !framebuffer)
2071 {
2072 return error(GL_INVALID_OPERATION);
2073 }
2074
2075 switch(attachment)
2076 {
2077 case GL_COLOR_ATTACHMENT0:
2078 case GL_COLOR_ATTACHMENT1:
2079 case GL_COLOR_ATTACHMENT2:
2080 case GL_COLOR_ATTACHMENT3:
2081 case GL_COLOR_ATTACHMENT4:
2082 case GL_COLOR_ATTACHMENT5:
2083 case GL_COLOR_ATTACHMENT6:
2084 case GL_COLOR_ATTACHMENT7:
2085 case GL_COLOR_ATTACHMENT8:
2086 case GL_COLOR_ATTACHMENT9:
2087 case GL_COLOR_ATTACHMENT10:
2088 case GL_COLOR_ATTACHMENT11:
2089 case GL_COLOR_ATTACHMENT12:
2090 case GL_COLOR_ATTACHMENT13:
2091 case GL_COLOR_ATTACHMENT14:
2092 case GL_COLOR_ATTACHMENT15:
2093 case GL_COLOR_ATTACHMENT16:
2094 case GL_COLOR_ATTACHMENT17:
2095 case GL_COLOR_ATTACHMENT18:
2096 case GL_COLOR_ATTACHMENT19:
2097 case GL_COLOR_ATTACHMENT20:
2098 case GL_COLOR_ATTACHMENT21:
2099 case GL_COLOR_ATTACHMENT22:
2100 case GL_COLOR_ATTACHMENT23:
2101 case GL_COLOR_ATTACHMENT24:
2102 case GL_COLOR_ATTACHMENT25:
2103 case GL_COLOR_ATTACHMENT26:
2104 case GL_COLOR_ATTACHMENT27:
2105 case GL_COLOR_ATTACHMENT28:
2106 case GL_COLOR_ATTACHMENT29:
2107 case GL_COLOR_ATTACHMENT30:
2108 case GL_COLOR_ATTACHMENT31:
2109 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2110 {
2111 return error(GL_INVALID_ENUM);
2112 }
2113 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2114 break;
2115 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2116 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capensd5401e22017-03-16 17:32:43 -04002117 case GL_DEPTH_STENCIL_ATTACHMENT:
2118 if(clientVersion >= 3)
2119 {
2120 framebuffer->setDepthbuffer(textarget, texture, level);
2121 framebuffer->setStencilbuffer(textarget, texture, level);
2122 break;
2123 }
2124 else return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002125 default:
2126 return error(GL_INVALID_ENUM);
2127 }
2128 }
2129}
2130
2131void FrontFace(GLenum mode)
2132{
2133 TRACE("(GLenum mode = 0x%X)", mode);
2134
2135 switch(mode)
2136 {
2137 case GL_CW:
2138 case GL_CCW:
2139 {
2140 es2::Context *context = es2::getContext();
2141
2142 if(context)
2143 {
2144 context->setFrontFace(mode);
2145 }
2146 }
2147 break;
2148 default:
2149 return error(GL_INVALID_ENUM);
2150 }
2151}
2152
2153void GenBuffers(GLsizei n, GLuint* buffers)
2154{
2155 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2156
2157 if(n < 0)
2158 {
2159 return error(GL_INVALID_VALUE);
2160 }
2161
2162 es2::Context *context = es2::getContext();
2163
2164 if(context)
2165 {
2166 for(int i = 0; i < n; i++)
2167 {
2168 buffers[i] = context->createBuffer();
2169 }
2170 }
2171}
2172
2173void GenerateMipmap(GLenum target)
2174{
2175 TRACE("(GLenum target = 0x%X)", target);
2176
2177 es2::Context *context = es2::getContext();
2178
2179 if(context)
2180 {
2181 es2::Texture *texture = nullptr;
2182
2183 GLint clientVersion = context->getClientVersion();
2184
2185 switch(target)
2186 {
2187 case GL_TEXTURE_2D:
2188 texture = context->getTexture2D();
2189 break;
2190 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002191 {
2192 TextureCubeMap *cube = context->getTextureCubeMap();
2193 texture = cube;
2194
2195 if(!cube->isCubeComplete())
2196 {
2197 return error(GL_INVALID_OPERATION);
2198 }
2199 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002200 break;
2201 case GL_TEXTURE_2D_ARRAY:
2202 if(clientVersion < 3)
2203 {
2204 return error(GL_INVALID_ENUM);
2205 }
2206 else
2207 {
2208 texture = context->getTexture2DArray();
2209 }
2210 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002211 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002212 texture = context->getTexture3D();
2213 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002214 case GL_TEXTURE_RECTANGLE_ARB:
2215 texture = context->getTexture2DRect();
2216 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002217 default:
2218 return error(GL_INVALID_ENUM);
2219 }
2220
Nicolas Capense6115342017-12-18 15:58:46 -05002221 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel()), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002222 {
2223 return error(GL_INVALID_OPERATION);
2224 }
2225
Nicolas Capens0bac2852016-05-07 06:09:58 -04002226 texture->generateMipmaps();
2227 }
2228}
2229
2230void GenFencesNV(GLsizei n, GLuint* fences)
2231{
2232 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2233
2234 if(n < 0)
2235 {
2236 return error(GL_INVALID_VALUE);
2237 }
2238
2239 es2::Context *context = es2::getContext();
2240
2241 if(context)
2242 {
2243 for(int i = 0; i < n; i++)
2244 {
2245 fences[i] = context->createFence();
2246 }
2247 }
2248}
2249
2250void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2251{
2252 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2253
2254 if(n < 0)
2255 {
2256 return error(GL_INVALID_VALUE);
2257 }
2258
2259 es2::Context *context = es2::getContext();
2260
2261 if(context)
2262 {
2263 for(int i = 0; i < n; i++)
2264 {
2265 framebuffers[i] = context->createFramebuffer();
2266 }
2267 }
2268}
2269
2270void GenQueriesEXT(GLsizei n, GLuint* ids)
2271{
2272 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2273
2274 if(n < 0)
2275 {
2276 return error(GL_INVALID_VALUE);
2277 }
2278
2279 es2::Context *context = es2::getContext();
2280
2281 if(context)
2282 {
2283 for(int i = 0; i < n; i++)
2284 {
2285 ids[i] = context->createQuery();
2286 }
2287 }
2288}
2289
2290void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2291{
2292 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2293
2294 if(n < 0)
2295 {
2296 return error(GL_INVALID_VALUE);
2297 }
2298
2299 es2::Context *context = es2::getContext();
2300
2301 if(context)
2302 {
2303 for(int i = 0; i < n; i++)
2304 {
2305 renderbuffers[i] = context->createRenderbuffer();
2306 }
2307 }
2308}
2309
2310void GenTextures(GLsizei n, GLuint* textures)
2311{
2312 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2313
2314 if(n < 0)
2315 {
2316 return error(GL_INVALID_VALUE);
2317 }
2318
2319 es2::Context *context = es2::getContext();
2320
2321 if(context)
2322 {
2323 for(int i = 0; i < n; i++)
2324 {
2325 textures[i] = context->createTexture();
2326 }
2327 }
2328}
2329
2330void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2331{
2332 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2333 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2334 program, index, bufsize, length, size, type, name);
2335
2336 if(bufsize < 0)
2337 {
2338 return error(GL_INVALID_VALUE);
2339 }
2340
2341 es2::Context *context = es2::getContext();
2342
2343 if(context)
2344 {
2345 es2::Program *programObject = context->getProgram(program);
2346
2347 if(!programObject)
2348 {
2349 if(context->getShader(program))
2350 {
2351 return error(GL_INVALID_OPERATION);
2352 }
2353 else
2354 {
2355 return error(GL_INVALID_VALUE);
2356 }
2357 }
2358
2359 if(index >= programObject->getActiveAttributeCount())
2360 {
2361 return error(GL_INVALID_VALUE);
2362 }
2363
2364 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2365 }
2366}
2367
2368void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2369{
2370 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2371 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2372 program, index, bufsize, length, size, type, name);
2373
2374 if(bufsize < 0)
2375 {
2376 return error(GL_INVALID_VALUE);
2377 }
2378
2379 es2::Context *context = es2::getContext();
2380
2381 if(context)
2382 {
2383 es2::Program *programObject = context->getProgram(program);
2384
2385 if(!programObject)
2386 {
2387 if(context->getShader(program))
2388 {
2389 return error(GL_INVALID_OPERATION);
2390 }
2391 else
2392 {
2393 return error(GL_INVALID_VALUE);
2394 }
2395 }
2396
2397 if(index >= programObject->getActiveUniformCount())
2398 {
2399 return error(GL_INVALID_VALUE);
2400 }
2401
2402 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2403 }
2404}
2405
2406void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2407{
2408 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2409 program, maxcount, count, shaders);
2410
2411 if(maxcount < 0)
2412 {
2413 return error(GL_INVALID_VALUE);
2414 }
2415
2416 es2::Context *context = es2::getContext();
2417
2418 if(context)
2419 {
2420 es2::Program *programObject = context->getProgram(program);
2421
2422 if(!programObject)
2423 {
2424 if(context->getShader(program))
2425 {
2426 return error(GL_INVALID_OPERATION);
2427 }
2428 else
2429 {
2430 return error(GL_INVALID_VALUE);
2431 }
2432 }
2433
2434 return programObject->getAttachedShaders(maxcount, count, shaders);
2435 }
2436}
2437
2438int GetAttribLocation(GLuint program, const GLchar* name)
2439{
2440 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2441
2442 es2::Context *context = es2::getContext();
2443
2444 if(context)
2445 {
2446
2447 es2::Program *programObject = context->getProgram(program);
2448
2449 if(!programObject)
2450 {
2451 if(context->getShader(program))
2452 {
2453 return error(GL_INVALID_OPERATION, -1);
2454 }
2455 else
2456 {
2457 return error(GL_INVALID_VALUE, -1);
2458 }
2459 }
2460
2461 if(!programObject->isLinked())
2462 {
2463 return error(GL_INVALID_OPERATION, -1);
2464 }
2465
2466 return programObject->getAttributeLocation(name);
2467 }
2468
2469 return -1;
2470}
2471
2472void GetBooleanv(GLenum pname, GLboolean* params)
2473{
2474 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2475
2476 es2::Context *context = es2::getContext();
2477
2478 if(context)
2479 {
2480 if(!(context->getBooleanv(pname, params)))
2481 {
2482 GLenum nativeType;
2483 unsigned int numParams = 0;
2484 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2485 return error(GL_INVALID_ENUM);
2486
2487 if(numParams == 0)
2488 return; // it is known that the pname is valid, but there are no parameters to return
2489
2490 if(nativeType == GL_FLOAT)
2491 {
2492 GLfloat *floatParams = nullptr;
2493 floatParams = new GLfloat[numParams];
2494
2495 context->getFloatv(pname, floatParams);
2496
2497 for(unsigned int i = 0; i < numParams; ++i)
2498 {
2499 if(floatParams[i] == 0.0f)
2500 params[i] = GL_FALSE;
2501 else
2502 params[i] = GL_TRUE;
2503 }
2504
2505 delete [] floatParams;
2506 }
2507 else if(nativeType == GL_INT)
2508 {
2509 GLint *intParams = nullptr;
2510 intParams = new GLint[numParams];
2511
2512 context->getIntegerv(pname, intParams);
2513
2514 for(unsigned int i = 0; i < numParams; ++i)
2515 {
2516 if(intParams[i] == 0)
2517 params[i] = GL_FALSE;
2518 else
2519 params[i] = GL_TRUE;
2520 }
2521
2522 delete [] intParams;
2523 }
2524 }
2525 }
2526}
2527
2528void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2529{
2530 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2531
2532 es2::Context *context = es2::getContext();
2533
2534 if(context)
2535 {
2536 es2::Buffer *buffer;
2537 if(!context->getBuffer(target, &buffer))
2538 {
2539 return error(GL_INVALID_ENUM);
2540 }
2541
2542 if(!buffer)
2543 {
2544 // A null buffer means that "0" is bound to the requested buffer target
2545 return error(GL_INVALID_OPERATION);
2546 }
2547
2548 GLint clientVersion = context->getClientVersion();
2549
2550 switch(pname)
2551 {
2552 case GL_BUFFER_USAGE:
2553 *params = buffer->usage();
2554 break;
2555 case GL_BUFFER_SIZE:
2556 *params = (GLint)buffer->size();
2557 break;
2558 case GL_BUFFER_ACCESS_FLAGS:
2559 if(clientVersion >= 3)
2560 {
2561 *params = buffer->access();
2562 break;
2563 }
2564 else return error(GL_INVALID_ENUM);
2565 case GL_BUFFER_MAPPED:
2566 if(clientVersion >= 3)
2567 {
2568 *params = buffer->isMapped();
2569 break;
2570 }
2571 else return error(GL_INVALID_ENUM);
2572 case GL_BUFFER_MAP_LENGTH:
2573 if(clientVersion >= 3)
2574 {
2575 *params = (GLint)buffer->length();
2576 break;
2577 }
2578 else return error(GL_INVALID_ENUM);
2579 case GL_BUFFER_MAP_OFFSET:
2580 if(clientVersion >= 3)
2581 {
2582 *params = (GLint)buffer->offset();
2583 break;
2584 }
2585 else return error(GL_INVALID_ENUM);
2586 default:
2587 return error(GL_INVALID_ENUM);
2588 }
2589 }
2590}
2591
2592GLenum GetError(void)
2593{
2594 TRACE("()");
2595
2596 es2::Context *context = es2::getContext();
2597
2598 if(context)
2599 {
2600 return context->getError();
2601 }
2602
2603 return GL_NO_ERROR;
2604}
2605
2606void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2607{
2608 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2609
2610 es2::Context *context = es2::getContext();
2611
2612 if(context)
2613 {
2614 es2::Fence *fenceObject = context->getFence(fence);
2615
2616 if(!fenceObject)
2617 {
2618 return error(GL_INVALID_OPERATION);
2619 }
2620
2621 fenceObject->getFenceiv(pname, params);
2622 }
2623}
2624
2625void GetFloatv(GLenum pname, GLfloat* params)
2626{
2627 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2628
2629 es2::Context *context = es2::getContext();
2630
2631 if(context)
2632 {
2633 if(!(context->getFloatv(pname, params)))
2634 {
2635 GLenum nativeType;
2636 unsigned int numParams = 0;
2637 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2638 return error(GL_INVALID_ENUM);
2639
2640 if(numParams == 0)
2641 return; // it is known that the pname is valid, but that there are no parameters to return.
2642
2643 if(nativeType == GL_BOOL)
2644 {
2645 GLboolean *boolParams = nullptr;
2646 boolParams = new GLboolean[numParams];
2647
2648 context->getBooleanv(pname, boolParams);
2649
2650 for(unsigned int i = 0; i < numParams; ++i)
2651 {
2652 if(boolParams[i] == GL_FALSE)
2653 params[i] = 0.0f;
2654 else
2655 params[i] = 1.0f;
2656 }
2657
2658 delete [] boolParams;
2659 }
2660 else if(nativeType == GL_INT)
2661 {
2662 GLint *intParams = nullptr;
2663 intParams = new GLint[numParams];
2664
2665 context->getIntegerv(pname, intParams);
2666
2667 for(unsigned int i = 0; i < numParams; ++i)
2668 {
2669 params[i] = (GLfloat)intParams[i];
2670 }
2671
2672 delete [] intParams;
2673 }
2674 }
2675 }
2676}
2677
2678void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2679{
2680 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2681 target, attachment, pname, params);
2682
2683 es2::Context *context = es2::getContext();
2684
2685 if(context)
2686 {
2687 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2688 {
2689 return error(GL_INVALID_ENUM);
2690 }
2691
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002692 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002693
Nicolas Capens0bac2852016-05-07 06:09:58 -04002694 if(target == GL_READ_FRAMEBUFFER)
2695 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002696 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002697 }
2698 else
2699 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002700 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002701 }
2702
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002703 GLint clientVersion = context->getClientVersion();
2704
2705 if(framebufferName == 0) // Default framebuffer.
2706 {
2707 if(clientVersion < 3)
2708 {
2709 return error(GL_INVALID_OPERATION);
2710 }
2711 }
2712
Nicolas Capens0bac2852016-05-07 06:09:58 -04002713 switch(attachment)
2714 {
2715 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002716 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002717 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002718 if(clientVersion < 3)
2719 {
2720 return error(GL_INVALID_ENUM);
2721 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002722
2723 if(framebufferName != 0)
2724 {
2725 return error(GL_INVALID_OPERATION);
2726 }
2727 break;
2728 case GL_DEPTH_ATTACHMENT:
2729 case GL_STENCIL_ATTACHMENT:
2730 if(framebufferName == 0)
2731 {
2732 return error(GL_INVALID_OPERATION);
2733 }
2734 break;
2735 case GL_DEPTH_STENCIL_ATTACHMENT:
2736 if(clientVersion < 3)
2737 {
2738 return error(GL_INVALID_ENUM);
2739 }
2740
2741 if(framebufferName == 0)
2742 {
2743 return error(GL_INVALID_OPERATION);
2744 }
2745 break;
2746 default:
2747 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2748 {
2749 if(framebufferName == 0)
2750 {
2751 return error(GL_INVALID_OPERATION);
2752 }
2753 }
2754 else return error(GL_INVALID_ENUM);
2755 }
2756
2757 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2758
2759 GLenum attachmentType;
2760 GLuint attachmentHandle;
2761 GLint attachmentLayer;
2762 Renderbuffer *renderbuffer = nullptr;
2763 switch(attachment)
2764 {
2765 case GL_BACK:
2766 attachmentType = framebuffer->getColorbufferType(0);
2767 attachmentHandle = framebuffer->getColorbufferName(0);
2768 attachmentLayer = framebuffer->getColorbufferLayer(0);
2769 renderbuffer = framebuffer->getColorbuffer(0);
2770 break;
2771 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002772 case GL_DEPTH_ATTACHMENT:
2773 attachmentType = framebuffer->getDepthbufferType();
2774 attachmentHandle = framebuffer->getDepthbufferName();
2775 attachmentLayer = framebuffer->getDepthbufferLayer();
2776 renderbuffer = framebuffer->getDepthbuffer();
2777 break;
2778 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002779 case GL_STENCIL_ATTACHMENT:
2780 attachmentType = framebuffer->getStencilbufferType();
2781 attachmentHandle = framebuffer->getStencilbufferName();
2782 attachmentLayer = framebuffer->getStencilbufferLayer();
2783 renderbuffer = framebuffer->getStencilbuffer();
2784 break;
2785 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002786 attachmentType = framebuffer->getDepthbufferType();
2787 attachmentHandle = framebuffer->getDepthbufferName();
2788 attachmentLayer = framebuffer->getDepthbufferLayer();
2789 renderbuffer = framebuffer->getDepthbuffer();
2790
2791 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002792 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002793 // Different attachments to DEPTH and STENCIL, query fails
2794 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002795 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002796 break;
2797 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002798 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2799 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2800 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2801 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2802 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2803 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002804 }
2805
2806 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002807 if(framebufferName == 0)
2808 {
2809 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2810 }
2811 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002812 {
2813 attachmentObjectType = attachmentType;
2814 }
2815 else if(es2::IsTextureTarget(attachmentType))
2816 {
2817 attachmentObjectType = GL_TEXTURE;
2818 }
2819 else UNREACHABLE(attachmentType);
2820
2821 if(attachmentObjectType != GL_NONE)
2822 {
2823 switch(pname)
2824 {
2825 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2826 *params = attachmentObjectType;
2827 break;
2828 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002829 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002830 {
2831 *params = attachmentHandle;
2832 }
2833 else
2834 {
2835 return error(GL_INVALID_ENUM);
2836 }
2837 break;
2838 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2839 if(attachmentObjectType == GL_TEXTURE)
2840 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002841 *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 -04002842 }
2843 else
2844 {
2845 return error(GL_INVALID_ENUM);
2846 }
2847 break;
2848 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2849 if(attachmentObjectType == GL_TEXTURE)
2850 {
2851 if(es2::IsCubemapTextureTarget(attachmentType))
2852 {
2853 *params = attachmentType;
2854 }
2855 else
2856 {
2857 *params = 0;
2858 }
2859 }
2860 else
2861 {
2862 return error(GL_INVALID_ENUM);
2863 }
2864 break;
2865 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2866 if(clientVersion >= 3)
2867 {
2868 *params = attachmentLayer;
2869 }
2870 else return error(GL_INVALID_ENUM);
2871 break;
2872 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2873 if(clientVersion >= 3)
2874 {
2875 *params = renderbuffer->getRedSize();
2876 }
2877 else return error(GL_INVALID_ENUM);
2878 break;
2879 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2880 if(clientVersion >= 3)
2881 {
2882 *params = renderbuffer->getGreenSize();
2883 }
2884 else return error(GL_INVALID_ENUM);
2885 break;
2886 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2887 if(clientVersion >= 3)
2888 {
2889 *params = renderbuffer->getBlueSize();
2890 }
2891 else return error(GL_INVALID_ENUM);
2892 break;
2893 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2894 if(clientVersion >= 3)
2895 {
2896 *params = renderbuffer->getAlphaSize();
2897 }
2898 else return error(GL_INVALID_ENUM);
2899 break;
2900 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2901 if(clientVersion >= 3)
2902 {
2903 *params = renderbuffer->getDepthSize();
2904 }
2905 else return error(GL_INVALID_ENUM);
2906 break;
2907 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2908 if(clientVersion >= 3)
2909 {
2910 *params = renderbuffer->getStencilSize();
2911 }
2912 else return error(GL_INVALID_ENUM);
2913 break;
2914 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002915 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2916 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002917 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002918 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002919 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002920
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002921 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002922 break;
2923 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2924 if(clientVersion >= 3)
2925 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002926 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002927 }
2928 else return error(GL_INVALID_ENUM);
2929 break;
2930 default:
2931 return error(GL_INVALID_ENUM);
2932 }
2933 }
2934 else
2935 {
2936 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2937 // is NONE, then querying any other pname will generate INVALID_ENUM.
2938
2939 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2940 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2941 // INVALID_OPERATION for all other pnames
2942
2943 switch(pname)
2944 {
2945 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2946 *params = GL_NONE;
2947 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002948 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2949 if(clientVersion < 3)
2950 {
2951 return error(GL_INVALID_ENUM);
2952 }
2953 *params = 0;
2954 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002955 default:
2956 if(clientVersion < 3)
2957 {
2958 return error(GL_INVALID_ENUM);
2959 }
2960 else
2961 {
2962 return error(GL_INVALID_OPERATION);
2963 }
2964 }
2965 }
2966 }
2967}
2968
2969GLenum GetGraphicsResetStatusEXT(void)
2970{
2971 TRACE("()");
2972
2973 return GL_NO_ERROR;
2974}
2975
2976void GetIntegerv(GLenum pname, GLint* params)
2977{
2978 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2979
2980 es2::Context *context = es2::getContext();
2981
2982 if(!context)
2983 {
2984 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2985 #ifdef __ANDROID__
2986 ALOGI("expected_badness glGetIntegerv() called without current context.");
2987 #else
2988 ERR("glGetIntegerv() called without current context.");
2989 #endif
2990
2991 // This is not spec compliant! When there is no current GL context, functions should
2992 // have no side effects. Google Maps queries these values before creating a context,
2993 // so we need this as a bug-compatible workaround.
2994 switch(pname)
2995 {
2996 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2997 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2998 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2999 case GL_STENCIL_BITS: *params = 8; return;
3000 case GL_ALIASED_LINE_WIDTH_RANGE:
3001 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3002 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3003 return;
3004 }
3005 }
3006
3007 if(context)
3008 {
3009 if(!(context->getIntegerv(pname, params)))
3010 {
3011 GLenum nativeType;
3012 unsigned int numParams = 0;
3013 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3014 return error(GL_INVALID_ENUM);
3015
3016 if(numParams == 0)
3017 return; // it is known that pname is valid, but there are no parameters to return
3018
3019 if(nativeType == GL_BOOL)
3020 {
3021 GLboolean *boolParams = nullptr;
3022 boolParams = new GLboolean[numParams];
3023
3024 context->getBooleanv(pname, boolParams);
3025
3026 for(unsigned int i = 0; i < numParams; ++i)
3027 {
3028 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3029 }
3030
3031 delete [] boolParams;
3032 }
3033 else if(nativeType == GL_FLOAT)
3034 {
3035 GLfloat *floatParams = nullptr;
3036 floatParams = new GLfloat[numParams];
3037
3038 context->getFloatv(pname, floatParams);
3039
3040 for(unsigned int i = 0; i < numParams; ++i)
3041 {
3042 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3043 {
Alexis Hetu60e20282017-12-13 07:42:22 -05003044 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003045 }
3046 else
3047 {
3048 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3049 }
3050 }
3051
3052 delete [] floatParams;
3053 }
3054 }
3055 }
3056}
3057
3058void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3059{
3060 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3061
3062 es2::Context *context = es2::getContext();
3063
3064 if(context)
3065 {
3066 es2::Program *programObject = context->getProgram(program);
3067
3068 if(!programObject)
3069 {
3070 if(context->getShader(program))
3071 {
3072 return error(GL_INVALID_OPERATION);
3073 }
3074 else
3075 {
3076 return error(GL_INVALID_VALUE);
3077 }
3078 }
3079
3080 GLint clientVersion = egl::getClientVersion();
3081
3082 switch(pname)
3083 {
3084 case GL_DELETE_STATUS:
3085 *params = programObject->isFlaggedForDeletion();
3086 return;
3087 case GL_LINK_STATUS:
3088 *params = programObject->isLinked();
3089 return;
3090 case GL_VALIDATE_STATUS:
3091 *params = programObject->isValidated();
3092 return;
3093 case GL_INFO_LOG_LENGTH:
3094 *params = (GLint)programObject->getInfoLogLength();
3095 return;
3096 case GL_ATTACHED_SHADERS:
3097 *params = programObject->getAttachedShadersCount();
3098 return;
3099 case GL_ACTIVE_ATTRIBUTES:
3100 *params = (GLint)programObject->getActiveAttributeCount();
3101 return;
3102 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3103 *params = programObject->getActiveAttributeMaxLength();
3104 return;
3105 case GL_ACTIVE_UNIFORMS:
3106 *params = (GLint)programObject->getActiveUniformCount();
3107 return;
3108 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3109 *params = programObject->getActiveUniformMaxLength();
3110 return;
3111 case GL_ACTIVE_UNIFORM_BLOCKS:
3112 if(clientVersion >= 3)
3113 {
3114 *params = (GLint)programObject->getActiveUniformBlockCount();
3115 return;
3116 }
3117 else return error(GL_INVALID_ENUM);
3118 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3119 if(clientVersion >= 3)
3120 {
3121 *params = programObject->getActiveUniformBlockMaxLength();
3122 return;
3123 }
3124 else return error(GL_INVALID_ENUM);
3125 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3126 if(clientVersion >= 3)
3127 {
3128 *params = programObject->getTransformFeedbackBufferMode();
3129 return;
3130 }
3131 else return error(GL_INVALID_ENUM);
3132 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3133 if(clientVersion >= 3)
3134 {
3135 *params = programObject->getTransformFeedbackVaryingCount();
3136 return;
3137 }
3138 else return error(GL_INVALID_ENUM);
3139 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3140 if(clientVersion >= 3)
3141 {
3142 *params = programObject->getTransformFeedbackVaryingMaxLength();
3143 return;
3144 }
3145 else return error(GL_INVALID_ENUM);
3146 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3147 if(clientVersion >= 3)
3148 {
3149 *params = programObject->getBinaryRetrievableHint();
3150 return;
3151 }
3152 else return error(GL_INVALID_ENUM);
3153 case GL_PROGRAM_BINARY_LENGTH:
3154 if(clientVersion >= 3)
3155 {
3156 *params = programObject->getBinaryLength();
3157 return;
3158 }
3159 else return error(GL_INVALID_ENUM);
3160 default:
3161 return error(GL_INVALID_ENUM);
3162 }
3163 }
3164}
3165
3166void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3167{
3168 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3169 program, bufsize, length, infolog);
3170
3171 if(bufsize < 0)
3172 {
3173 return error(GL_INVALID_VALUE);
3174 }
3175
3176 es2::Context *context = es2::getContext();
3177
3178 if(context)
3179 {
3180 es2::Program *programObject = context->getProgram(program);
3181
3182 if(!programObject)
3183 {
3184 if(context->getShader(program))
3185 {
3186 return error(GL_INVALID_OPERATION);
3187 }
3188 else
3189 {
3190 return error(GL_INVALID_VALUE);
3191 }
3192 }
3193
3194 programObject->getInfoLog(bufsize, length, infolog);
3195 }
3196}
3197
3198void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3199{
3200 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3201
3202 switch(pname)
3203 {
3204 case GL_CURRENT_QUERY_EXT:
3205 break;
3206 default:
3207 return error(GL_INVALID_ENUM);
3208 }
3209
3210 es2::Context *context = es2::getContext();
3211
3212 if(context)
3213 {
3214 params[0] = context->getActiveQuery(target);
3215 }
3216}
3217
3218void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3219{
3220 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3221
3222 switch(pname)
3223 {
3224 case GL_QUERY_RESULT_EXT:
3225 case GL_QUERY_RESULT_AVAILABLE_EXT:
3226 break;
3227 default:
3228 return error(GL_INVALID_ENUM);
3229 }
3230
3231 es2::Context *context = es2::getContext();
3232
3233 if(context)
3234 {
3235 es2::Query *queryObject = context->getQuery(name);
3236
3237 if(!queryObject)
3238 {
3239 return error(GL_INVALID_OPERATION);
3240 }
3241
3242 if(context->getActiveQuery(queryObject->getType()) == name)
3243 {
3244 return error(GL_INVALID_OPERATION);
3245 }
3246
3247 switch(pname)
3248 {
3249 case GL_QUERY_RESULT_EXT:
3250 params[0] = queryObject->getResult();
3251 break;
3252 case GL_QUERY_RESULT_AVAILABLE_EXT:
3253 params[0] = queryObject->isResultAvailable();
3254 break;
3255 default:
3256 ASSERT(false);
3257 }
3258 }
3259}
3260
3261void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3262{
3263 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3264
3265 es2::Context *context = es2::getContext();
3266
3267 if(context)
3268 {
3269 if(target != GL_RENDERBUFFER)
3270 {
3271 return error(GL_INVALID_ENUM);
3272 }
3273
3274 if(context->getRenderbufferName() == 0)
3275 {
3276 return error(GL_INVALID_OPERATION);
3277 }
3278
3279 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3280
3281 switch(pname)
3282 {
3283 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3284 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003285 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3286 {
3287 GLint internalformat = renderbuffer->getFormat();
3288 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3289 }
3290 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003291 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3292 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3293 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3294 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3295 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3296 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003297 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003298 default:
3299 return error(GL_INVALID_ENUM);
3300 }
3301 }
3302}
3303
3304void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3305{
3306 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3307
3308 es2::Context *context = es2::getContext();
3309
3310 if(context)
3311 {
3312 es2::Shader *shaderObject = context->getShader(shader);
3313
3314 if(!shaderObject)
3315 {
3316 if(context->getProgram(shader))
3317 {
3318 return error(GL_INVALID_OPERATION);
3319 }
3320 else
3321 {
3322 return error(GL_INVALID_VALUE);
3323 }
3324 }
3325
3326 switch(pname)
3327 {
3328 case GL_SHADER_TYPE:
3329 *params = shaderObject->getType();
3330 return;
3331 case GL_DELETE_STATUS:
3332 *params = shaderObject->isFlaggedForDeletion();
3333 return;
3334 case GL_COMPILE_STATUS:
3335 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3336 return;
3337 case GL_INFO_LOG_LENGTH:
3338 *params = (GLint)shaderObject->getInfoLogLength();
3339 return;
3340 case GL_SHADER_SOURCE_LENGTH:
3341 *params = (GLint)shaderObject->getSourceLength();
3342 return;
3343 default:
3344 return error(GL_INVALID_ENUM);
3345 }
3346 }
3347}
3348
3349void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3350{
3351 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3352 shader, bufsize, length, infolog);
3353
3354 if(bufsize < 0)
3355 {
3356 return error(GL_INVALID_VALUE);
3357 }
3358
3359 es2::Context *context = es2::getContext();
3360
3361 if(context)
3362 {
3363 es2::Shader *shaderObject = context->getShader(shader);
3364
3365 if(!shaderObject)
3366 {
3367 if(context->getProgram(shader))
3368 {
3369 return error(GL_INVALID_OPERATION);
3370 }
3371 else
3372 {
3373 return error(GL_INVALID_VALUE);
3374 }
3375 }
3376
3377 shaderObject->getInfoLog(bufsize, length, infolog);
3378 }
3379}
3380
3381void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3382{
3383 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3384 shadertype, precisiontype, range, precision);
3385
3386 switch(shadertype)
3387 {
3388 case GL_VERTEX_SHADER:
3389 case GL_FRAGMENT_SHADER:
3390 break;
3391 default:
3392 return error(GL_INVALID_ENUM);
3393 }
3394
3395 switch(precisiontype)
3396 {
3397 case GL_LOW_FLOAT:
3398 case GL_MEDIUM_FLOAT:
3399 case GL_HIGH_FLOAT:
3400 // IEEE 754 single-precision
3401 range[0] = 127;
3402 range[1] = 127;
3403 *precision = 23;
3404 break;
3405 case GL_LOW_INT:
3406 case GL_MEDIUM_INT:
3407 case GL_HIGH_INT:
3408 // Full integer precision is supported
3409 range[0] = 31;
3410 range[1] = 30;
3411 *precision = 0;
3412 break;
3413 default:
3414 return error(GL_INVALID_ENUM);
3415 }
3416}
3417
3418void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3419{
3420 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3421 shader, bufsize, length, source);
3422
3423 if(bufsize < 0)
3424 {
3425 return error(GL_INVALID_VALUE);
3426 }
3427
3428 es2::Context *context = es2::getContext();
3429
3430 if(context)
3431 {
3432 es2::Shader *shaderObject = context->getShader(shader);
3433
3434 if(!shaderObject)
3435 {
3436 if(context->getProgram(shader))
3437 {
3438 return error(GL_INVALID_OPERATION);
3439 }
3440 else
3441 {
3442 return error(GL_INVALID_VALUE);
3443 }
3444 }
3445
3446 shaderObject->getSource(bufsize, length, source);
3447 }
3448}
3449
3450const GLubyte* GetString(GLenum name)
3451{
3452 TRACE("(GLenum name = 0x%X)", name);
3453
3454 switch(name)
3455 {
3456 case GL_VENDOR:
3457 return (GLubyte*)"Google Inc.";
3458 case GL_RENDERER:
3459 return (GLubyte*)"Google SwiftShader";
3460 case GL_VERSION:
3461 {
3462 es2::Context *context = es2::getContext();
3463 return (context && (context->getClientVersion() >= 3)) ?
3464 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3465 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3466 }
3467 case GL_SHADING_LANGUAGE_VERSION:
3468 {
3469 es2::Context *context = es2::getContext();
3470 return (context && (context->getClientVersion() >= 3)) ?
3471 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3472 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3473 }
3474 case GL_EXTENSIONS:
3475 {
3476 es2::Context *context = es2::getContext();
3477 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3478 }
3479 default:
3480 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3481 }
3482}
3483
3484void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3485{
3486 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3487
3488 es2::Context *context = es2::getContext();
3489
3490 if(context)
3491 {
3492 es2::Texture *texture;
3493
3494 GLint clientVersion = context->getClientVersion();
3495
3496 switch(target)
3497 {
3498 case GL_TEXTURE_2D:
3499 texture = context->getTexture2D();
3500 break;
3501 case GL_TEXTURE_CUBE_MAP:
3502 texture = context->getTextureCubeMap();
3503 break;
3504 case GL_TEXTURE_EXTERNAL_OES:
3505 texture = context->getTextureExternal();
3506 break;
3507 case GL_TEXTURE_2D_ARRAY:
3508 if(clientVersion < 3)
3509 {
3510 return error(GL_INVALID_ENUM);
3511 }
3512 else
3513 {
3514 texture = context->getTexture2DArray();
3515 }
3516 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003517 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003518 texture = context->getTexture3D();
3519 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003520 case GL_TEXTURE_RECTANGLE_ARB:
3521 texture = context->getTexture2DRect();
3522 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003523 default:
3524 return error(GL_INVALID_ENUM);
3525 }
3526
3527 switch(pname)
3528 {
3529 case GL_TEXTURE_MAG_FILTER:
3530 *params = (GLfloat)texture->getMagFilter();
3531 break;
3532 case GL_TEXTURE_MIN_FILTER:
3533 *params = (GLfloat)texture->getMinFilter();
3534 break;
3535 case GL_TEXTURE_WRAP_S:
3536 *params = (GLfloat)texture->getWrapS();
3537 break;
3538 case GL_TEXTURE_WRAP_T:
3539 *params = (GLfloat)texture->getWrapT();
3540 break;
3541 case GL_TEXTURE_WRAP_R_OES:
3542 *params = (GLfloat)texture->getWrapR();
3543 break;
3544 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3545 *params = texture->getMaxAnisotropy();
3546 break;
3547 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3548 *params = (GLfloat)1;
3549 break;
3550 case GL_TEXTURE_BASE_LEVEL:
3551 if(clientVersion >= 3)
3552 {
3553 *params = (GLfloat)texture->getBaseLevel();
3554 break;
3555 }
3556 else return error(GL_INVALID_ENUM);
3557 case GL_TEXTURE_COMPARE_FUNC:
3558 if(clientVersion >= 3)
3559 {
3560 *params = (GLfloat)texture->getCompareFunc();
3561 break;
3562 }
3563 else return error(GL_INVALID_ENUM);
3564 case GL_TEXTURE_COMPARE_MODE:
3565 if(clientVersion >= 3)
3566 {
3567 *params = (GLfloat)texture->getCompareMode();
3568 break;
3569 }
3570 else return error(GL_INVALID_ENUM);
3571 case GL_TEXTURE_IMMUTABLE_FORMAT:
3572 if(clientVersion >= 3)
3573 {
3574 *params = (GLfloat)texture->getImmutableFormat();
3575 break;
3576 }
3577 else return error(GL_INVALID_ENUM);
3578 case GL_TEXTURE_IMMUTABLE_LEVELS:
3579 if(clientVersion >= 3)
3580 {
3581 *params = (GLfloat)texture->getImmutableLevels();
3582 break;
3583 }
3584 else return error(GL_INVALID_ENUM);
3585 case GL_TEXTURE_MAX_LEVEL:
3586 if(clientVersion >= 3)
3587 {
3588 *params = (GLfloat)texture->getMaxLevel();
3589 break;
3590 }
3591 else return error(GL_INVALID_ENUM);
3592 case GL_TEXTURE_MAX_LOD:
3593 if(clientVersion >= 3)
3594 {
3595 *params = texture->getMaxLOD();
3596 break;
3597 }
3598 else return error(GL_INVALID_ENUM);
3599 case GL_TEXTURE_MIN_LOD:
3600 if(clientVersion >= 3)
3601 {
3602 *params = texture->getMinLOD();
3603 break;
3604 }
3605 else return error(GL_INVALID_ENUM);
3606 case GL_TEXTURE_SWIZZLE_R:
3607 if(clientVersion >= 3)
3608 {
3609 *params = (GLfloat)texture->getSwizzleR();
3610 break;
3611 }
3612 else return error(GL_INVALID_ENUM);
3613 case GL_TEXTURE_SWIZZLE_G:
3614 if(clientVersion >= 3)
3615 {
3616 *params = (GLfloat)texture->getSwizzleG();
3617 break;
3618 }
3619 else return error(GL_INVALID_ENUM);
3620 case GL_TEXTURE_SWIZZLE_B:
3621 if(clientVersion >= 3)
3622 {
3623 *params = (GLfloat)texture->getSwizzleB();
3624 break;
3625 }
3626 else return error(GL_INVALID_ENUM);
3627 case GL_TEXTURE_SWIZZLE_A:
3628 if(clientVersion >= 3)
3629 {
3630 *params = (GLfloat)texture->getSwizzleA();
3631 break;
3632 }
3633 else return error(GL_INVALID_ENUM);
3634 default:
3635 return error(GL_INVALID_ENUM);
3636 }
3637 }
3638}
3639
3640void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3641{
3642 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3643
3644 es2::Context *context = es2::getContext();
3645
3646 if(context)
3647 {
3648 es2::Texture *texture;
3649
3650 GLint clientVersion = context->getClientVersion();
3651
3652 switch(target)
3653 {
3654 case GL_TEXTURE_2D:
3655 texture = context->getTexture2D();
3656 break;
3657 case GL_TEXTURE_CUBE_MAP:
3658 texture = context->getTextureCubeMap();
3659 break;
3660 case GL_TEXTURE_EXTERNAL_OES:
3661 texture = context->getTextureExternal();
3662 break;
3663 case GL_TEXTURE_2D_ARRAY:
3664 if(clientVersion < 3)
3665 {
3666 return error(GL_INVALID_ENUM);
3667 }
3668 else
3669 {
3670 texture = context->getTexture2DArray();
3671 }
3672 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003673 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003674 texture = context->getTexture3D();
3675 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003676 case GL_TEXTURE_RECTANGLE_ARB:
3677 texture = context->getTexture2DRect();
3678 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003679 default:
3680 return error(GL_INVALID_ENUM);
3681 }
3682
3683 switch(pname)
3684 {
3685 case GL_TEXTURE_MAG_FILTER:
3686 *params = texture->getMagFilter();
3687 break;
3688 case GL_TEXTURE_MIN_FILTER:
3689 *params = texture->getMinFilter();
3690 break;
3691 case GL_TEXTURE_WRAP_S:
3692 *params = texture->getWrapS();
3693 break;
3694 case GL_TEXTURE_WRAP_T:
3695 *params = texture->getWrapT();
3696 break;
3697 case GL_TEXTURE_WRAP_R_OES:
3698 *params = texture->getWrapR();
3699 break;
3700 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3701 *params = (GLint)texture->getMaxAnisotropy();
3702 break;
3703 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3704 *params = 1;
3705 break;
3706 case GL_TEXTURE_BASE_LEVEL:
3707 if(clientVersion >= 3)
3708 {
3709 *params = texture->getBaseLevel();
3710 break;
3711 }
3712 else return error(GL_INVALID_ENUM);
3713 case GL_TEXTURE_COMPARE_FUNC:
3714 if(clientVersion >= 3)
3715 {
3716 *params = (GLint)texture->getCompareFunc();
3717 break;
3718 }
3719 else return error(GL_INVALID_ENUM);
3720 case GL_TEXTURE_COMPARE_MODE:
3721 if(clientVersion >= 3)
3722 {
3723 *params = (GLint)texture->getCompareMode();
3724 break;
3725 }
3726 else return error(GL_INVALID_ENUM);
3727 case GL_TEXTURE_IMMUTABLE_FORMAT:
3728 if(clientVersion >= 3)
3729 {
3730 *params = (GLint)texture->getImmutableFormat();
3731 break;
3732 }
3733 else return error(GL_INVALID_ENUM);
3734 case GL_TEXTURE_IMMUTABLE_LEVELS:
3735 if(clientVersion >= 3)
3736 {
3737 *params = (GLint)texture->getImmutableLevels();
3738 break;
3739 }
3740 else return error(GL_INVALID_ENUM);
3741 case GL_TEXTURE_MAX_LEVEL:
3742 if(clientVersion >= 3)
3743 {
3744 *params = texture->getMaxLevel();
3745 break;
3746 }
3747 else return error(GL_INVALID_ENUM);
3748 case GL_TEXTURE_MAX_LOD:
3749 if(clientVersion >= 3)
3750 {
3751 *params = (GLint)roundf(texture->getMaxLOD());
3752 break;
3753 }
3754 else return error(GL_INVALID_ENUM);
3755 case GL_TEXTURE_MIN_LOD:
3756 if(clientVersion >= 3)
3757 {
3758 *params = (GLint)roundf(texture->getMinLOD());
3759 break;
3760 }
3761 else return error(GL_INVALID_ENUM);
3762 case GL_TEXTURE_SWIZZLE_R:
3763 if(clientVersion >= 3)
3764 {
3765 *params = (GLint)texture->getSwizzleR();
3766 break;
3767 }
3768 else return error(GL_INVALID_ENUM);
3769 case GL_TEXTURE_SWIZZLE_G:
3770 if(clientVersion >= 3)
3771 {
3772 *params = (GLint)texture->getSwizzleG();
3773 break;
3774 }
3775 else return error(GL_INVALID_ENUM);
3776 case GL_TEXTURE_SWIZZLE_B:
3777 if(clientVersion >= 3)
3778 {
3779 *params = (GLint)texture->getSwizzleB();
3780 break;
3781 }
3782 else return error(GL_INVALID_ENUM);
3783 case GL_TEXTURE_SWIZZLE_A:
3784 if(clientVersion >= 3)
3785 {
3786 *params = (GLint)texture->getSwizzleA();
3787 break;
3788 }
3789 else return error(GL_INVALID_ENUM);
3790 default:
3791 return error(GL_INVALID_ENUM);
3792 }
3793 }
3794}
3795
3796void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3797{
3798 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3799 program, location, bufSize, params);
3800
3801 if(bufSize < 0)
3802 {
3803 return error(GL_INVALID_VALUE);
3804 }
3805
3806 es2::Context *context = es2::getContext();
3807
3808 if(context)
3809 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003810 es2::Program *programObject = context->getProgram(program);
3811
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003812 if(!programObject)
3813 {
3814 if(context->getShader(program))
3815 {
3816 return error(GL_INVALID_OPERATION);
3817 }
3818 else
3819 {
3820 return error(GL_INVALID_VALUE);
3821 }
3822 }
3823
3824 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003825 {
3826 return error(GL_INVALID_OPERATION);
3827 }
3828
3829 if(!programObject->getUniformfv(location, &bufSize, params))
3830 {
3831 return error(GL_INVALID_OPERATION);
3832 }
3833 }
3834}
3835
3836void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3837{
3838 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3839
3840 es2::Context *context = es2::getContext();
3841
3842 if(context)
3843 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003844 es2::Program *programObject = context->getProgram(program);
3845
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003846 if(!programObject)
3847 {
3848 if(context->getShader(program))
3849 {
3850 return error(GL_INVALID_OPERATION);
3851 }
3852 else
3853 {
3854 return error(GL_INVALID_VALUE);
3855 }
3856 }
3857
3858 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003859 {
3860 return error(GL_INVALID_OPERATION);
3861 }
3862
3863 if(!programObject->getUniformfv(location, nullptr, params))
3864 {
3865 return error(GL_INVALID_OPERATION);
3866 }
3867 }
3868}
3869
3870void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3871{
3872 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3873 program, location, bufSize, params);
3874
3875 if(bufSize < 0)
3876 {
3877 return error(GL_INVALID_VALUE);
3878 }
3879
3880 es2::Context *context = es2::getContext();
3881
3882 if(context)
3883 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003884 es2::Program *programObject = context->getProgram(program);
3885
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003886 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003887 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003888 if(context->getShader(program))
3889 {
3890 return error(GL_INVALID_OPERATION);
3891 }
3892 else
3893 {
3894 return error(GL_INVALID_VALUE);
3895 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003896 }
3897
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003898 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003899 {
3900 return error(GL_INVALID_OPERATION);
3901 }
3902
3903 if(!programObject->getUniformiv(location, &bufSize, params))
3904 {
3905 return error(GL_INVALID_OPERATION);
3906 }
3907 }
3908}
3909
3910void GetUniformiv(GLuint program, GLint location, GLint* params)
3911{
3912 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3913
3914 es2::Context *context = es2::getContext();
3915
3916 if(context)
3917 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003918 es2::Program *programObject = context->getProgram(program);
3919
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003920 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003921 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003922 if(context->getShader(program))
3923 {
3924 return error(GL_INVALID_OPERATION);
3925 }
3926 else
3927 {
3928 return error(GL_INVALID_VALUE);
3929 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003930 }
3931
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003932 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003933 {
3934 return error(GL_INVALID_OPERATION);
3935 }
3936
3937 if(!programObject->getUniformiv(location, nullptr, params))
3938 {
3939 return error(GL_INVALID_OPERATION);
3940 }
3941 }
3942}
3943
3944int GetUniformLocation(GLuint program, const GLchar* name)
3945{
3946 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3947
3948 es2::Context *context = es2::getContext();
3949
3950 if(strstr(name, "gl_") == name)
3951 {
3952 return -1;
3953 }
3954
3955 if(context)
3956 {
3957 es2::Program *programObject = context->getProgram(program);
3958
3959 if(!programObject)
3960 {
3961 if(context->getShader(program))
3962 {
3963 return error(GL_INVALID_OPERATION, -1);
3964 }
3965 else
3966 {
3967 return error(GL_INVALID_VALUE, -1);
3968 }
3969 }
3970
3971 if(!programObject->isLinked())
3972 {
3973 return error(GL_INVALID_OPERATION, -1);
3974 }
3975
3976 return programObject->getUniformLocation(name);
3977 }
3978
3979 return -1;
3980}
3981
3982void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3983{
3984 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3985
3986 es2::Context *context = es2::getContext();
3987
3988 if(context)
3989 {
3990 if(index >= es2::MAX_VERTEX_ATTRIBS)
3991 {
3992 return error(GL_INVALID_VALUE);
3993 }
3994
3995 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3996
3997 GLint clientVersion = context->getClientVersion();
3998
3999 switch(pname)
4000 {
4001 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4002 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4003 break;
4004 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4005 *params = (GLfloat)attribState.mSize;
4006 break;
4007 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4008 *params = (GLfloat)attribState.mStride;
4009 break;
4010 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4011 *params = (GLfloat)attribState.mType;
4012 break;
4013 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4014 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4015 break;
4016 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4017 *params = (GLfloat)attribState.mBoundBuffer.name();
4018 break;
4019 case GL_CURRENT_VERTEX_ATTRIB:
4020 {
4021 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4022 for(int i = 0; i < 4; ++i)
4023 {
4024 params[i] = attrib.getCurrentValueF(i);
4025 }
4026 }
4027 break;
4028 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4029 if(clientVersion >= 3)
4030 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004031 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004032 break;
4033 }
4034 else return error(GL_INVALID_ENUM);
4035 default: return error(GL_INVALID_ENUM);
4036 }
4037 }
4038}
4039
4040void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4041{
4042 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4043
4044 es2::Context *context = es2::getContext();
4045
4046 if(context)
4047 {
4048 if(index >= es2::MAX_VERTEX_ATTRIBS)
4049 {
4050 return error(GL_INVALID_VALUE);
4051 }
4052
4053 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4054
4055 GLint clientVersion = context->getClientVersion();
4056
4057 switch(pname)
4058 {
4059 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4060 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4061 break;
4062 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4063 *params = attribState.mSize;
4064 break;
4065 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4066 *params = attribState.mStride;
4067 break;
4068 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4069 *params = attribState.mType;
4070 break;
4071 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4072 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4073 break;
4074 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4075 *params = attribState.mBoundBuffer.name();
4076 break;
4077 case GL_CURRENT_VERTEX_ATTRIB:
4078 {
4079 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4080 for(int i = 0; i < 4; ++i)
4081 {
4082 float currentValue = attrib.getCurrentValueF(i);
4083 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4084 }
4085 }
4086 break;
4087 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4088 if(clientVersion >= 3)
4089 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004090 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004091 break;
4092 }
4093 else return error(GL_INVALID_ENUM);
4094 default: return error(GL_INVALID_ENUM);
4095 }
4096 }
4097}
4098
4099void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4100{
4101 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4102
4103 es2::Context *context = es2::getContext();
4104
4105 if(context)
4106 {
4107 if(index >= es2::MAX_VERTEX_ATTRIBS)
4108 {
4109 return error(GL_INVALID_VALUE);
4110 }
4111
4112 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4113 {
4114 return error(GL_INVALID_ENUM);
4115 }
4116
4117 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4118 }
4119}
4120
4121void Hint(GLenum target, GLenum mode)
4122{
4123 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4124
4125 switch(mode)
4126 {
4127 case GL_FASTEST:
4128 case GL_NICEST:
4129 case GL_DONT_CARE:
4130 break;
4131 default:
4132 return error(GL_INVALID_ENUM);
4133 }
4134
4135 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004136
4137 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004138 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004139 switch(target)
4140 {
4141 case GL_GENERATE_MIPMAP_HINT:
4142 context->setGenerateMipmapHint(mode);
4143 break;
4144 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4145 context->setFragmentShaderDerivativeHint(mode);
4146 break;
4147 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4148 context->setTextureFilteringHint(mode);
4149 break;
4150 default:
4151 return error(GL_INVALID_ENUM);
4152 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004153 }
4154}
4155
4156GLboolean IsBuffer(GLuint buffer)
4157{
4158 TRACE("(GLuint buffer = %d)", buffer);
4159
4160 es2::Context *context = es2::getContext();
4161
4162 if(context && buffer)
4163 {
4164 es2::Buffer *bufferObject = context->getBuffer(buffer);
4165
4166 if(bufferObject)
4167 {
4168 return GL_TRUE;
4169 }
4170 }
4171
4172 return GL_FALSE;
4173}
4174
4175GLboolean IsEnabled(GLenum cap)
4176{
4177 TRACE("(GLenum cap = 0x%X)", cap);
4178
4179 es2::Context *context = es2::getContext();
4180
4181 if(context)
4182 {
4183 GLint clientVersion = context->getClientVersion();
4184
4185 switch(cap)
4186 {
4187 case GL_CULL_FACE: return context->isCullFaceEnabled();
4188 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4189 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4190 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4191 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4192 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4193 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4194 case GL_BLEND: return context->isBlendEnabled();
4195 case GL_DITHER: return context->isDitherEnabled();
4196 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4197 if(clientVersion >= 3)
4198 {
4199 return context->isPrimitiveRestartFixedIndexEnabled();
4200 }
4201 else return error(GL_INVALID_ENUM, false);
4202 case GL_RASTERIZER_DISCARD:
4203 if(clientVersion >= 3)
4204 {
4205 return context->isRasterizerDiscardEnabled();
4206 }
4207 else return error(GL_INVALID_ENUM, false);
4208 default:
4209 return error(GL_INVALID_ENUM, false);
4210 }
4211 }
4212
4213 return false;
4214}
4215
4216GLboolean IsFenceNV(GLuint fence)
4217{
4218 TRACE("(GLuint fence = %d)", fence);
4219
4220 es2::Context *context = es2::getContext();
4221
4222 if(context)
4223 {
4224 es2::Fence *fenceObject = context->getFence(fence);
4225
4226 if(!fenceObject)
4227 {
4228 return GL_FALSE;
4229 }
4230
4231 return fenceObject->isFence();
4232 }
4233
4234 return GL_FALSE;
4235}
4236
4237GLboolean IsFramebuffer(GLuint framebuffer)
4238{
4239 TRACE("(GLuint framebuffer = %d)", framebuffer);
4240
4241 es2::Context *context = es2::getContext();
4242
4243 if(context && framebuffer)
4244 {
4245 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4246
4247 if(framebufferObject)
4248 {
4249 return GL_TRUE;
4250 }
4251 }
4252
4253 return GL_FALSE;
4254}
4255
4256GLboolean IsProgram(GLuint program)
4257{
4258 TRACE("(GLuint program = %d)", program);
4259
4260 es2::Context *context = es2::getContext();
4261
4262 if(context && program)
4263 {
4264 es2::Program *programObject = context->getProgram(program);
4265
4266 if(programObject)
4267 {
4268 return GL_TRUE;
4269 }
4270 }
4271
4272 return GL_FALSE;
4273}
4274
4275GLboolean IsQueryEXT(GLuint name)
4276{
4277 TRACE("(GLuint name = %d)", name);
4278
4279 if(name == 0)
4280 {
4281 return GL_FALSE;
4282 }
4283
4284 es2::Context *context = es2::getContext();
4285
4286 if(context)
4287 {
4288 es2::Query *queryObject = context->getQuery(name);
4289
4290 if(queryObject)
4291 {
4292 return GL_TRUE;
4293 }
4294 }
4295
4296 return GL_FALSE;
4297}
4298
4299GLboolean IsRenderbuffer(GLuint renderbuffer)
4300{
4301 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4302
4303 es2::Context *context = es2::getContext();
4304
4305 if(context && renderbuffer)
4306 {
4307 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4308
4309 if(renderbufferObject)
4310 {
4311 return GL_TRUE;
4312 }
4313 }
4314
4315 return GL_FALSE;
4316}
4317
4318GLboolean IsShader(GLuint shader)
4319{
4320 TRACE("(GLuint shader = %d)", shader);
4321
4322 es2::Context *context = es2::getContext();
4323
4324 if(context && shader)
4325 {
4326 es2::Shader *shaderObject = context->getShader(shader);
4327
4328 if(shaderObject)
4329 {
4330 return GL_TRUE;
4331 }
4332 }
4333
4334 return GL_FALSE;
4335}
4336
4337GLboolean IsTexture(GLuint texture)
4338{
4339 TRACE("(GLuint texture = %d)", texture);
4340
4341 es2::Context *context = es2::getContext();
4342
4343 if(context && texture)
4344 {
4345 es2::Texture *textureObject = context->getTexture(texture);
4346
4347 if(textureObject)
4348 {
4349 return GL_TRUE;
4350 }
4351 }
4352
4353 return GL_FALSE;
4354}
4355
4356void LineWidth(GLfloat width)
4357{
4358 TRACE("(GLfloat width = %f)", width);
4359
4360 if(width <= 0.0f)
4361 {
4362 return error(GL_INVALID_VALUE);
4363 }
4364
4365 es2::Context *context = es2::getContext();
4366
4367 if(context)
4368 {
4369 context->setLineWidth(width);
4370 }
4371}
4372
4373void LinkProgram(GLuint program)
4374{
4375 TRACE("(GLuint program = %d)", program);
4376
4377 es2::Context *context = es2::getContext();
4378
4379 if(context)
4380 {
4381 es2::Program *programObject = context->getProgram(program);
4382
4383 if(!programObject)
4384 {
4385 if(context->getShader(program))
4386 {
4387 return error(GL_INVALID_OPERATION);
4388 }
4389 else
4390 {
4391 return error(GL_INVALID_VALUE);
4392 }
4393 }
4394
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004395 if(programObject == context->getCurrentProgram())
4396 {
4397 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4398 if(transformFeedback && transformFeedback->isActive())
4399 {
4400 return error(GL_INVALID_OPERATION);
4401 }
4402 }
4403
Nicolas Capens0bac2852016-05-07 06:09:58 -04004404 programObject->link();
4405 }
4406}
4407
4408void PixelStorei(GLenum pname, GLint param)
4409{
4410 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4411
4412 es2::Context *context = es2::getContext();
4413
4414 if(context)
4415 {
4416 GLint clientVersion = context->getClientVersion();
4417
4418 switch(pname)
4419 {
4420 case GL_UNPACK_ALIGNMENT:
4421 if(param != 1 && param != 2 && param != 4 && param != 8)
4422 {
4423 return error(GL_INVALID_VALUE);
4424 }
4425 context->setUnpackAlignment(param);
4426 break;
4427 case GL_PACK_ALIGNMENT:
4428 if(param != 1 && param != 2 && param != 4 && param != 8)
4429 {
4430 return error(GL_INVALID_VALUE);
4431 }
4432 context->setPackAlignment(param);
4433 break;
4434 case GL_PACK_ROW_LENGTH:
4435 if(clientVersion >= 3)
4436 {
4437 if(param < 0)
4438 {
4439 return error(GL_INVALID_VALUE);
4440 }
4441 context->setPackRowLength(param);
4442 break;
4443 }
4444 else return error(GL_INVALID_ENUM);
4445 case GL_PACK_SKIP_PIXELS:
4446 if(clientVersion >= 3)
4447 {
4448 if(param < 0)
4449 {
4450 return error(GL_INVALID_VALUE);
4451 }
4452 context->setPackSkipPixels(param);
4453 break;
4454 }
4455 else return error(GL_INVALID_ENUM);
4456 case GL_PACK_SKIP_ROWS:
4457 if(clientVersion >= 3)
4458 {
4459 if(param < 0)
4460 {
4461 return error(GL_INVALID_VALUE);
4462 }
4463 context->setPackSkipRows(param);
4464 break;
4465 }
4466 else return error(GL_INVALID_ENUM);
4467 case GL_UNPACK_ROW_LENGTH:
4468 if(clientVersion >= 3)
4469 {
4470 if(param < 0)
4471 {
4472 return error(GL_INVALID_VALUE);
4473 }
4474 context->setUnpackRowLength(param);
4475 break;
4476 }
4477 else return error(GL_INVALID_ENUM);
4478 case GL_UNPACK_IMAGE_HEIGHT:
4479 if(clientVersion >= 3)
4480 {
4481 if(param < 0)
4482 {
4483 return error(GL_INVALID_VALUE);
4484 }
4485 context->setUnpackImageHeight(param);
4486 break;
4487 }
4488 else return error(GL_INVALID_ENUM);
4489 case GL_UNPACK_SKIP_PIXELS:
4490 if(clientVersion >= 3)
4491 {
4492 if(param < 0)
4493 {
4494 return error(GL_INVALID_VALUE);
4495 }
4496 context->setUnpackSkipPixels(param);
4497 break;
4498 }
4499 else return error(GL_INVALID_ENUM);
4500 case GL_UNPACK_SKIP_ROWS:
4501 if(clientVersion >= 3)
4502 {
4503 if(param < 0)
4504 {
4505 return error(GL_INVALID_VALUE);
4506 }
4507 context->setUnpackSkipRows(param);
4508 break;
4509 }
4510 else return error(GL_INVALID_ENUM);
4511 case GL_UNPACK_SKIP_IMAGES:
4512 if(clientVersion >= 3) {
4513 if(param < 0)
4514 {
4515 return error(GL_INVALID_VALUE);
4516 }
4517 context->setUnpackSkipImages(param);
4518 break;
4519 }
4520 else return error(GL_INVALID_ENUM);
4521 default:
4522 return error(GL_INVALID_ENUM);
4523 }
4524 }
4525}
4526
4527void PolygonOffset(GLfloat factor, GLfloat units)
4528{
4529 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4530
4531 es2::Context *context = es2::getContext();
4532
4533 if(context)
4534 {
4535 context->setPolygonOffsetParams(factor, units);
4536 }
4537}
4538
4539void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4540 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4541{
4542 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4543 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4544 x, y, width, height, format, type, bufSize, data);
4545
4546 if(width < 0 || height < 0 || bufSize < 0)
4547 {
4548 return error(GL_INVALID_VALUE);
4549 }
4550
4551 es2::Context *context = es2::getContext();
4552
4553 if(context)
4554 {
4555 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4556 }
4557}
4558
4559void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4560{
4561 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4562 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4563 x, y, width, height, format, type, pixels);
4564
4565 if(width < 0 || height < 0)
4566 {
4567 return error(GL_INVALID_VALUE);
4568 }
4569
4570 es2::Context *context = es2::getContext();
4571
4572 if(context)
4573 {
4574 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4575 }
4576}
4577
4578void ReleaseShaderCompiler(void)
4579{
4580 TRACE("()");
4581
4582 es2::Shader::releaseCompiler();
4583}
4584
Nicolas Capens400667e2017-03-29 14:40:14 -04004585void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004586{
4587 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4588 target, samples, internalformat, width, height);
4589
4590 switch(target)
4591 {
4592 case GL_RENDERBUFFER:
4593 break;
4594 default:
4595 return error(GL_INVALID_ENUM);
4596 }
4597
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004598 if(width < 0 || height < 0 || samples < 0 ||
4599 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4600 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004601 {
4602 return error(GL_INVALID_VALUE);
4603 }
4604
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004605 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004606 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004607 {
4608 return error(GL_INVALID_OPERATION);
4609 }
4610
Nicolas Capens0bac2852016-05-07 06:09:58 -04004611 es2::Context *context = es2::getContext();
4612
4613 if(context)
4614 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004615 GLuint handle = context->getRenderbufferName();
4616 if(handle == 0)
4617 {
4618 return error(GL_INVALID_OPERATION);
4619 }
4620
4621 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004622
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004623 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004624 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004625 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004626 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004627 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4628 {
4629 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4630 }
4631 else if(IsDepthRenderable(internalformat, clientVersion))
4632 {
4633 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4634 }
4635 else if(IsStencilRenderable(internalformat, clientVersion))
4636 {
4637 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4638 }
4639 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004640 }
4641}
4642
Nicolas Capens400667e2017-03-29 14:40:14 -04004643void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4644{
4645 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4646}
4647
Nicolas Capens0bac2852016-05-07 06:09:58 -04004648void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4649{
Nicolas Capens400667e2017-03-29 14:40:14 -04004650 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004651}
4652
4653void SampleCoverage(GLclampf value, GLboolean invert)
4654{
4655 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4656
4657 es2::Context* context = es2::getContext();
4658
4659 if(context)
4660 {
4661 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4662 }
4663}
4664
4665void SetFenceNV(GLuint fence, GLenum condition)
4666{
4667 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4668
4669 if(condition != GL_ALL_COMPLETED_NV)
4670 {
4671 return error(GL_INVALID_ENUM);
4672 }
4673
4674 es2::Context *context = es2::getContext();
4675
4676 if(context)
4677 {
4678 es2::Fence *fenceObject = context->getFence(fence);
4679
4680 if(!fenceObject)
4681 {
4682 return error(GL_INVALID_OPERATION);
4683 }
4684
4685 fenceObject->setFence(condition);
4686 }
4687}
4688
4689void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4690{
4691 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4692
4693 if(width < 0 || height < 0)
4694 {
4695 return error(GL_INVALID_VALUE);
4696 }
4697
4698 es2::Context* context = es2::getContext();
4699
4700 if(context)
4701 {
4702 context->setScissorParams(x, y, width, height);
4703 }
4704}
4705
4706void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4707{
4708 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4709 "const GLvoid* binary = %p, GLsizei length = %d)",
4710 n, shaders, binaryformat, binary, length);
4711
4712 // No binary shader formats are supported.
4713 return error(GL_INVALID_ENUM);
4714}
4715
4716void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4717{
4718 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4719 shader, count, string, length);
4720
4721 if(count < 0)
4722 {
4723 return error(GL_INVALID_VALUE);
4724 }
4725
4726 es2::Context *context = es2::getContext();
4727
4728 if(context)
4729 {
4730 es2::Shader *shaderObject = context->getShader(shader);
4731
4732 if(!shaderObject)
4733 {
4734 if(context->getProgram(shader))
4735 {
4736 return error(GL_INVALID_OPERATION);
4737 }
4738 else
4739 {
4740 return error(GL_INVALID_VALUE);
4741 }
4742 }
4743
4744 shaderObject->setSource(count, string, length);
4745 }
4746}
4747
4748void StencilFunc(GLenum func, GLint ref, GLuint mask)
4749{
4750 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4751}
4752
4753void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4754{
4755 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4756
4757 switch(face)
4758 {
4759 case GL_FRONT:
4760 case GL_BACK:
4761 case GL_FRONT_AND_BACK:
4762 break;
4763 default:
4764 return error(GL_INVALID_ENUM);
4765 }
4766
4767 switch(func)
4768 {
4769 case GL_NEVER:
4770 case GL_ALWAYS:
4771 case GL_LESS:
4772 case GL_LEQUAL:
4773 case GL_EQUAL:
4774 case GL_GEQUAL:
4775 case GL_GREATER:
4776 case GL_NOTEQUAL:
4777 break;
4778 default:
4779 return error(GL_INVALID_ENUM);
4780 }
4781
4782 es2::Context *context = es2::getContext();
4783
4784 if(context)
4785 {
4786 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4787 {
4788 context->setStencilParams(func, ref, mask);
4789 }
4790
4791 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4792 {
4793 context->setStencilBackParams(func, ref, mask);
4794 }
4795 }
4796}
4797
4798void StencilMask(GLuint mask)
4799{
4800 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4801}
4802
4803void StencilMaskSeparate(GLenum face, GLuint mask)
4804{
4805 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4806
4807 switch(face)
4808 {
4809 case GL_FRONT:
4810 case GL_BACK:
4811 case GL_FRONT_AND_BACK:
4812 break;
4813 default:
4814 return error(GL_INVALID_ENUM);
4815 }
4816
4817 es2::Context *context = es2::getContext();
4818
4819 if(context)
4820 {
4821 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4822 {
4823 context->setStencilWritemask(mask);
4824 }
4825
4826 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4827 {
4828 context->setStencilBackWritemask(mask);
4829 }
4830 }
4831}
4832
4833void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4834{
4835 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4836}
4837
4838void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4839{
4840 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4841 face, fail, zfail, zpass);
4842
4843 switch(face)
4844 {
4845 case GL_FRONT:
4846 case GL_BACK:
4847 case GL_FRONT_AND_BACK:
4848 break;
4849 default:
4850 return error(GL_INVALID_ENUM);
4851 }
4852
4853 switch(fail)
4854 {
4855 case GL_ZERO:
4856 case GL_KEEP:
4857 case GL_REPLACE:
4858 case GL_INCR:
4859 case GL_DECR:
4860 case GL_INVERT:
4861 case GL_INCR_WRAP:
4862 case GL_DECR_WRAP:
4863 break;
4864 default:
4865 return error(GL_INVALID_ENUM);
4866 }
4867
4868 switch(zfail)
4869 {
4870 case GL_ZERO:
4871 case GL_KEEP:
4872 case GL_REPLACE:
4873 case GL_INCR:
4874 case GL_DECR:
4875 case GL_INVERT:
4876 case GL_INCR_WRAP:
4877 case GL_DECR_WRAP:
4878 break;
4879 default:
4880 return error(GL_INVALID_ENUM);
4881 }
4882
4883 switch(zpass)
4884 {
4885 case GL_ZERO:
4886 case GL_KEEP:
4887 case GL_REPLACE:
4888 case GL_INCR:
4889 case GL_DECR:
4890 case GL_INVERT:
4891 case GL_INCR_WRAP:
4892 case GL_DECR_WRAP:
4893 break;
4894 default:
4895 return error(GL_INVALID_ENUM);
4896 }
4897
4898 es2::Context *context = es2::getContext();
4899
4900 if(context)
4901 {
4902 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4903 {
4904 context->setStencilOperations(fail, zfail, zpass);
4905 }
4906
4907 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4908 {
4909 context->setStencilBackOperations(fail, zfail, zpass);
4910 }
4911 }
4912}
4913
4914GLboolean TestFenceNV(GLuint fence)
4915{
4916 TRACE("(GLuint fence = %d)", fence);
4917
4918 es2::Context *context = es2::getContext();
4919
4920 if(context)
4921 {
4922 es2::Fence *fenceObject = context->getFence(fence);
4923
4924 if(!fenceObject)
4925 {
4926 return error(GL_INVALID_OPERATION, GL_TRUE);
4927 }
4928
4929 return fenceObject->testFence();
4930 }
4931
4932 return GL_TRUE;
4933}
4934
4935void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004936 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004937{
4938 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004939 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4940 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004941
4942 if(!validImageSize(level, width, height))
4943 {
4944 return error(GL_INVALID_VALUE);
4945 }
4946
4947 es2::Context *context = es2::getContext();
4948
4949 if(context)
4950 {
4951 GLint clientVersion = context->getClientVersion();
4952 if(clientVersion < 3)
4953 {
4954 if(internalformat != (GLint)format)
4955 {
4956 return error(GL_INVALID_OPERATION);
4957 }
4958 }
4959
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004960 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05004961 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004962 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004963 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004964 }
4965
4966 if(border != 0)
4967 {
4968 return error(GL_INVALID_VALUE);
4969 }
4970
4971 switch(target)
4972 {
4973 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05004974 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004975 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4976 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4977 {
4978 return error(GL_INVALID_VALUE);
4979 }
4980 break;
4981 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4982 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4983 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4984 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4985 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4986 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4987 if(width != height)
4988 {
4989 return error(GL_INVALID_VALUE);
4990 }
4991
4992 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4993 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4994 {
4995 return error(GL_INVALID_VALUE);
4996 }
4997 break;
4998 default:
4999 return error(GL_INVALID_ENUM);
5000 }
5001
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005002 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005003
Nicolas Capens5555af42017-12-14 13:14:03 -05005004 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005005 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005006 {
5007 return error(validationError);
5008 }
5009
Alexis Hetu46768622018-01-16 22:09:28 -05005010 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005011 {
Alexis Hetu46768622018-01-16 22:09:28 -05005012 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005013
5014 if(!texture)
5015 {
5016 return error(GL_INVALID_OPERATION);
5017 }
5018
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005019 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005020 }
5021 else
5022 {
5023 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5024
5025 if(!texture)
5026 {
5027 return error(GL_INVALID_OPERATION);
5028 }
5029
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005030 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005031 }
5032 }
5033}
5034
5035void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5036{
5037 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5038
5039 es2::Context *context = es2::getContext();
5040
5041 if(context)
5042 {
5043 es2::Texture *texture;
5044
5045 GLint clientVersion = context->getClientVersion();
5046
5047 switch(target)
5048 {
5049 case GL_TEXTURE_2D:
5050 texture = context->getTexture2D();
5051 break;
5052 case GL_TEXTURE_2D_ARRAY:
5053 if(clientVersion < 3)
5054 {
5055 return error(GL_INVALID_ENUM);
5056 }
5057 else
5058 {
5059 texture = context->getTexture2DArray();
5060 }
5061 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005062 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005063 texture = context->getTexture3D();
5064 break;
5065 case GL_TEXTURE_CUBE_MAP:
5066 texture = context->getTextureCubeMap();
5067 break;
5068 case GL_TEXTURE_EXTERNAL_OES:
5069 texture = context->getTextureExternal();
5070 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005071 case GL_TEXTURE_RECTANGLE_ARB:
5072 texture = context->getTexture2DRect();
5073 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005074 default:
5075 return error(GL_INVALID_ENUM);
5076 }
5077
5078 switch(pname)
5079 {
5080 case GL_TEXTURE_WRAP_S:
5081 if(!texture->setWrapS((GLenum)param))
5082 {
5083 return error(GL_INVALID_ENUM);
5084 }
5085 break;
5086 case GL_TEXTURE_WRAP_T:
5087 if(!texture->setWrapT((GLenum)param))
5088 {
5089 return error(GL_INVALID_ENUM);
5090 }
5091 break;
5092 case GL_TEXTURE_WRAP_R_OES:
5093 if(!texture->setWrapR((GLenum)param))
5094 {
5095 return error(GL_INVALID_ENUM);
5096 }
5097 break;
5098 case GL_TEXTURE_MIN_FILTER:
5099 if(!texture->setMinFilter((GLenum)param))
5100 {
5101 return error(GL_INVALID_ENUM);
5102 }
5103 break;
5104 case GL_TEXTURE_MAG_FILTER:
5105 if(!texture->setMagFilter((GLenum)param))
5106 {
5107 return error(GL_INVALID_ENUM);
5108 }
5109 break;
5110 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5111 if(!texture->setMaxAnisotropy(param))
5112 {
5113 return error(GL_INVALID_VALUE);
5114 }
5115 break;
5116 case GL_TEXTURE_BASE_LEVEL:
5117 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5118 {
5119 return error(GL_INVALID_VALUE);
5120 }
5121 break;
5122 case GL_TEXTURE_COMPARE_FUNC:
5123 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5124 {
5125 return error(GL_INVALID_VALUE);
5126 }
5127 break;
5128 case GL_TEXTURE_COMPARE_MODE:
5129 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5130 {
5131 return error(GL_INVALID_VALUE);
5132 }
5133 break;
5134 case GL_TEXTURE_MAX_LEVEL:
5135 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5136 {
5137 return error(GL_INVALID_VALUE);
5138 }
5139 break;
5140 case GL_TEXTURE_MAX_LOD:
5141 if(clientVersion < 3 || !texture->setMaxLOD(param))
5142 {
5143 return error(GL_INVALID_VALUE);
5144 }
5145 break;
5146 case GL_TEXTURE_MIN_LOD:
5147 if(clientVersion < 3 || !texture->setMinLOD(param))
5148 {
5149 return error(GL_INVALID_VALUE);
5150 }
5151 break;
5152 case GL_TEXTURE_SWIZZLE_R:
5153 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5154 {
5155 return error(GL_INVALID_VALUE);
5156 }
5157 break;
5158 case GL_TEXTURE_SWIZZLE_G:
5159 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5160 {
5161 return error(GL_INVALID_VALUE);
5162 }
5163 break;
5164 case GL_TEXTURE_SWIZZLE_B:
5165 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5166 {
5167 return error(GL_INVALID_VALUE);
5168 }
5169 break;
5170 case GL_TEXTURE_SWIZZLE_A:
5171 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5172 {
5173 return error(GL_INVALID_VALUE);
5174 }
5175 break;
5176 default:
5177 return error(GL_INVALID_ENUM);
5178 }
5179 }
5180}
5181
5182void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5183{
5184 glTexParameterf(target, pname, *params);
5185}
5186
5187void TexParameteri(GLenum target, GLenum pname, GLint param)
5188{
5189 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5190
5191 es2::Context *context = es2::getContext();
5192
5193 if(context)
5194 {
5195 es2::Texture *texture;
5196
5197 GLint clientVersion = context->getClientVersion();
5198
5199 switch(target)
5200 {
5201 case GL_TEXTURE_2D:
5202 texture = context->getTexture2D();
5203 break;
5204 case GL_TEXTURE_2D_ARRAY:
5205 if(clientVersion < 3)
5206 {
5207 return error(GL_INVALID_ENUM);
5208 }
5209 else
5210 {
5211 texture = context->getTexture2DArray();
5212 }
5213 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005214 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005215 texture = context->getTexture3D();
5216 break;
5217 case GL_TEXTURE_CUBE_MAP:
5218 texture = context->getTextureCubeMap();
5219 break;
5220 case GL_TEXTURE_EXTERNAL_OES:
5221 texture = context->getTextureExternal();
5222 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005223 case GL_TEXTURE_RECTANGLE_ARB:
5224 texture = context->getTexture2DRect();
5225 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005226 default:
5227 return error(GL_INVALID_ENUM);
5228 }
5229
5230 switch(pname)
5231 {
5232 case GL_TEXTURE_WRAP_S:
5233 if(!texture->setWrapS((GLenum)param))
5234 {
5235 return error(GL_INVALID_ENUM);
5236 }
5237 break;
5238 case GL_TEXTURE_WRAP_T:
5239 if(!texture->setWrapT((GLenum)param))
5240 {
5241 return error(GL_INVALID_ENUM);
5242 }
5243 break;
5244 case GL_TEXTURE_WRAP_R_OES:
5245 if(!texture->setWrapR((GLenum)param))
5246 {
5247 return error(GL_INVALID_ENUM);
5248 }
5249 break;
5250 case GL_TEXTURE_MIN_FILTER:
5251 if(!texture->setMinFilter((GLenum)param))
5252 {
5253 return error(GL_INVALID_ENUM);
5254 }
5255 break;
5256 case GL_TEXTURE_MAG_FILTER:
5257 if(!texture->setMagFilter((GLenum)param))
5258 {
5259 return error(GL_INVALID_ENUM);
5260 }
5261 break;
5262 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5263 if(!texture->setMaxAnisotropy((GLfloat)param))
5264 {
5265 return error(GL_INVALID_VALUE);
5266 }
5267 break;
5268 case GL_TEXTURE_BASE_LEVEL:
5269 if(clientVersion < 3 || !texture->setBaseLevel(param))
5270 {
5271 return error(GL_INVALID_VALUE);
5272 }
5273 break;
5274 case GL_TEXTURE_COMPARE_FUNC:
5275 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5276 {
5277 return error(GL_INVALID_VALUE);
5278 }
5279 break;
5280 case GL_TEXTURE_COMPARE_MODE:
5281 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5282 {
5283 return error(GL_INVALID_VALUE);
5284 }
5285 break;
5286 case GL_TEXTURE_MAX_LEVEL:
5287 if(clientVersion < 3 || !texture->setMaxLevel(param))
5288 {
5289 return error(GL_INVALID_VALUE);
5290 }
5291 break;
5292 case GL_TEXTURE_MAX_LOD:
5293 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5294 {
5295 return error(GL_INVALID_VALUE);
5296 }
5297 break;
5298 case GL_TEXTURE_MIN_LOD:
5299 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5300 {
5301 return error(GL_INVALID_VALUE);
5302 }
5303 break;
5304 case GL_TEXTURE_SWIZZLE_R:
5305 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5306 {
5307 return error(GL_INVALID_VALUE);
5308 }
5309 break;
5310 case GL_TEXTURE_SWIZZLE_G:
5311 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5312 {
5313 return error(GL_INVALID_VALUE);
5314 }
5315 break;
5316 case GL_TEXTURE_SWIZZLE_B:
5317 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5318 {
5319 return error(GL_INVALID_VALUE);
5320 }
5321 break;
5322 case GL_TEXTURE_SWIZZLE_A:
5323 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5324 {
5325 return error(GL_INVALID_VALUE);
5326 }
5327 break;
5328 default:
5329 return error(GL_INVALID_ENUM);
5330 }
5331 }
5332}
5333
5334void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5335{
5336 glTexParameteri(target, pname, *params);
5337}
5338
5339void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005340 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005341{
5342 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5343 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005344 "const GLvoid* data = %p)",
5345 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005346
5347 if(!es2::IsTextureTarget(target))
5348 {
5349 return error(GL_INVALID_ENUM);
5350 }
5351
5352 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5353 {
5354 return error(GL_INVALID_VALUE);
5355 }
5356
5357 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5358 {
5359 return error(GL_INVALID_VALUE);
5360 }
5361
5362 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5363 {
5364 return error(GL_INVALID_VALUE);
5365 }
5366
Nicolas Capens0bac2852016-05-07 06:09:58 -04005367 es2::Context *context = es2::getContext();
5368
5369 if(context)
5370 {
Alexis Hetu46768622018-01-16 22:09:28 -05005371 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005372 {
Alexis Hetu46768622018-01-16 22:09:28 -05005373 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005374
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005375 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005376 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005377 {
5378 return error(validationError);
5379 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005380
Nicolas Capens5555af42017-12-14 13:14:03 -05005381 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005382 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005383 {
5384 return error(validationError);
5385 }
5386
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005387 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005388 }
5389 else if(es2::IsCubemapTextureTarget(target))
5390 {
5391 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5392
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005393 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005394 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005395 {
5396 return error(validationError);
5397 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005398
Nicolas Capens5555af42017-12-14 13:14:03 -05005399 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005400 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005401 {
5402 return error(validationError);
5403 }
5404
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005405 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005406 }
5407 else UNREACHABLE(target);
5408 }
5409}
5410
5411void Uniform1f(GLint location, GLfloat x)
5412{
5413 glUniform1fv(location, 1, &x);
5414}
5415
5416void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5417{
5418 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5419
5420 if(count < 0)
5421 {
5422 return error(GL_INVALID_VALUE);
5423 }
5424
Nicolas Capens0bac2852016-05-07 06:09:58 -04005425 es2::Context *context = es2::getContext();
5426
5427 if(context)
5428 {
5429 es2::Program *program = context->getCurrentProgram();
5430
5431 if(!program)
5432 {
5433 return error(GL_INVALID_OPERATION);
5434 }
5435
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005436 if(location == -1)
5437 {
5438 return;
5439 }
5440
Nicolas Capens0bac2852016-05-07 06:09:58 -04005441 if(!program->setUniform1fv(location, count, v))
5442 {
5443 return error(GL_INVALID_OPERATION);
5444 }
5445 }
5446}
5447
5448void Uniform1i(GLint location, GLint x)
5449{
5450 glUniform1iv(location, 1, &x);
5451}
5452
5453void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5454{
5455 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5456
5457 if(count < 0)
5458 {
5459 return error(GL_INVALID_VALUE);
5460 }
5461
Nicolas Capens0bac2852016-05-07 06:09:58 -04005462 es2::Context *context = es2::getContext();
5463
5464 if(context)
5465 {
5466 es2::Program *program = context->getCurrentProgram();
5467
5468 if(!program)
5469 {
5470 return error(GL_INVALID_OPERATION);
5471 }
5472
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005473 if(location == -1)
5474 {
5475 return;
5476 }
5477
Nicolas Capens0bac2852016-05-07 06:09:58 -04005478 if(!program->setUniform1iv(location, count, v))
5479 {
5480 return error(GL_INVALID_OPERATION);
5481 }
5482 }
5483}
5484
5485void Uniform2f(GLint location, GLfloat x, GLfloat y)
5486{
5487 GLfloat xy[2] = {x, y};
5488
5489 glUniform2fv(location, 1, (GLfloat*)&xy);
5490}
5491
5492void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5493{
5494 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5495
5496 if(count < 0)
5497 {
5498 return error(GL_INVALID_VALUE);
5499 }
5500
Nicolas Capens0bac2852016-05-07 06:09:58 -04005501 es2::Context *context = es2::getContext();
5502
5503 if(context)
5504 {
5505 es2::Program *program = context->getCurrentProgram();
5506
5507 if(!program)
5508 {
5509 return error(GL_INVALID_OPERATION);
5510 }
5511
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005512 if(location == -1)
5513 {
5514 return;
5515 }
5516
Nicolas Capens0bac2852016-05-07 06:09:58 -04005517 if(!program->setUniform2fv(location, count, v))
5518 {
5519 return error(GL_INVALID_OPERATION);
5520 }
5521 }
5522}
5523
5524void Uniform2i(GLint location, GLint x, GLint y)
5525{
5526 GLint xy[4] = {x, y};
5527
5528 glUniform2iv(location, 1, (GLint*)&xy);
5529}
5530
5531void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5532{
5533 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5534
5535 if(count < 0)
5536 {
5537 return error(GL_INVALID_VALUE);
5538 }
5539
Nicolas Capens0bac2852016-05-07 06:09:58 -04005540 es2::Context *context = es2::getContext();
5541
5542 if(context)
5543 {
5544 es2::Program *program = context->getCurrentProgram();
5545
5546 if(!program)
5547 {
5548 return error(GL_INVALID_OPERATION);
5549 }
5550
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005551 if(location == -1)
5552 {
5553 return;
5554 }
5555
Nicolas Capens0bac2852016-05-07 06:09:58 -04005556 if(!program->setUniform2iv(location, count, v))
5557 {
5558 return error(GL_INVALID_OPERATION);
5559 }
5560 }
5561}
5562
5563void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5564{
5565 GLfloat xyz[3] = {x, y, z};
5566
5567 glUniform3fv(location, 1, (GLfloat*)&xyz);
5568}
5569
5570void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5571{
5572 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5573
5574 if(count < 0)
5575 {
5576 return error(GL_INVALID_VALUE);
5577 }
5578
Nicolas Capens0bac2852016-05-07 06:09:58 -04005579 es2::Context *context = es2::getContext();
5580
5581 if(context)
5582 {
5583 es2::Program *program = context->getCurrentProgram();
5584
5585 if(!program)
5586 {
5587 return error(GL_INVALID_OPERATION);
5588 }
5589
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005590 if(location == -1)
5591 {
5592 return;
5593 }
5594
Nicolas Capens0bac2852016-05-07 06:09:58 -04005595 if(!program->setUniform3fv(location, count, v))
5596 {
5597 return error(GL_INVALID_OPERATION);
5598 }
5599 }
5600}
5601
5602void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5603{
5604 GLint xyz[3] = {x, y, z};
5605
5606 glUniform3iv(location, 1, (GLint*)&xyz);
5607}
5608
5609void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5610{
5611 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5612
5613 if(count < 0)
5614 {
5615 return error(GL_INVALID_VALUE);
5616 }
5617
Nicolas Capens0bac2852016-05-07 06:09:58 -04005618 es2::Context *context = es2::getContext();
5619
5620 if(context)
5621 {
5622 es2::Program *program = context->getCurrentProgram();
5623
5624 if(!program)
5625 {
5626 return error(GL_INVALID_OPERATION);
5627 }
5628
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005629 if(location == -1)
5630 {
5631 return;
5632 }
5633
Nicolas Capens0bac2852016-05-07 06:09:58 -04005634 if(!program->setUniform3iv(location, count, v))
5635 {
5636 return error(GL_INVALID_OPERATION);
5637 }
5638 }
5639}
5640
5641void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5642{
5643 GLfloat xyzw[4] = {x, y, z, w};
5644
5645 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5646}
5647
5648void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5649{
5650 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5651
5652 if(count < 0)
5653 {
5654 return error(GL_INVALID_VALUE);
5655 }
5656
Nicolas Capens0bac2852016-05-07 06:09:58 -04005657 es2::Context *context = es2::getContext();
5658
5659 if(context)
5660 {
5661 es2::Program *program = context->getCurrentProgram();
5662
5663 if(!program)
5664 {
5665 return error(GL_INVALID_OPERATION);
5666 }
5667
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005668 if(location == -1)
5669 {
5670 return;
5671 }
5672
Nicolas Capens0bac2852016-05-07 06:09:58 -04005673 if(!program->setUniform4fv(location, count, v))
5674 {
5675 return error(GL_INVALID_OPERATION);
5676 }
5677 }
5678}
5679
5680void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5681{
5682 GLint xyzw[4] = {x, y, z, w};
5683
5684 glUniform4iv(location, 1, (GLint*)&xyzw);
5685}
5686
5687void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5688{
5689 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5690
5691 if(count < 0)
5692 {
5693 return error(GL_INVALID_VALUE);
5694 }
5695
Nicolas Capens0bac2852016-05-07 06:09:58 -04005696 es2::Context *context = es2::getContext();
5697
5698 if(context)
5699 {
5700 es2::Program *program = context->getCurrentProgram();
5701
5702 if(!program)
5703 {
5704 return error(GL_INVALID_OPERATION);
5705 }
5706
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005707 if(location == -1)
5708 {
5709 return;
5710 }
5711
Nicolas Capens0bac2852016-05-07 06:09:58 -04005712 if(!program->setUniform4iv(location, count, v))
5713 {
5714 return error(GL_INVALID_OPERATION);
5715 }
5716 }
5717}
5718
5719void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5720{
5721 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5722 location, count, transpose, value);
5723
5724 if(count < 0)
5725 {
5726 return error(GL_INVALID_VALUE);
5727 }
5728
Nicolas Capens0bac2852016-05-07 06:09:58 -04005729 es2::Context *context = es2::getContext();
5730
5731 if(context)
5732 {
5733 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5734 {
5735 return error(GL_INVALID_VALUE);
5736 }
5737
5738 es2::Program *program = context->getCurrentProgram();
5739
5740 if(!program)
5741 {
5742 return error(GL_INVALID_OPERATION);
5743 }
5744
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005745 if(location == -1)
5746 {
5747 return;
5748 }
5749
Nicolas Capens0bac2852016-05-07 06:09:58 -04005750 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5751 {
5752 return error(GL_INVALID_OPERATION);
5753 }
5754 }
5755}
5756
5757void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5758{
5759 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5760 location, count, transpose, value);
5761
5762 if(count < 0)
5763 {
5764 return error(GL_INVALID_VALUE);
5765 }
5766
Nicolas Capens0bac2852016-05-07 06:09:58 -04005767 es2::Context *context = es2::getContext();
5768
5769 if(context)
5770 {
5771 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5772 {
5773 return error(GL_INVALID_VALUE);
5774 }
5775
5776 es2::Program *program = context->getCurrentProgram();
5777
5778 if(!program)
5779 {
5780 return error(GL_INVALID_OPERATION);
5781 }
5782
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005783 if(location == -1)
5784 {
5785 return;
5786 }
5787
Nicolas Capens0bac2852016-05-07 06:09:58 -04005788 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5789 {
5790 return error(GL_INVALID_OPERATION);
5791 }
5792 }
5793}
5794
5795void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5796{
5797 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5798 location, count, transpose, value);
5799
5800 if(count < 0)
5801 {
5802 return error(GL_INVALID_VALUE);
5803 }
5804
Nicolas Capens0bac2852016-05-07 06:09:58 -04005805 es2::Context *context = es2::getContext();
5806
5807 if(context)
5808 {
5809 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5810 {
5811 return error(GL_INVALID_VALUE);
5812 }
5813
5814 es2::Program *program = context->getCurrentProgram();
5815
5816 if(!program)
5817 {
5818 return error(GL_INVALID_OPERATION);
5819 }
5820
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005821 if(location == -1)
5822 {
5823 return;
5824 }
5825
Nicolas Capens0bac2852016-05-07 06:09:58 -04005826 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5827 {
5828 return error(GL_INVALID_OPERATION);
5829 }
5830 }
5831}
5832
5833void UseProgram(GLuint program)
5834{
5835 TRACE("(GLuint program = %d)", program);
5836
5837 es2::Context *context = es2::getContext();
5838
5839 if(context)
5840 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005841 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5842 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5843 {
5844 return error(GL_INVALID_OPERATION);
5845 }
5846
Nicolas Capens0bac2852016-05-07 06:09:58 -04005847 es2::Program *programObject = context->getProgram(program);
5848
5849 if(!programObject && program != 0)
5850 {
5851 if(context->getShader(program))
5852 {
5853 return error(GL_INVALID_OPERATION);
5854 }
5855 else
5856 {
5857 return error(GL_INVALID_VALUE);
5858 }
5859 }
5860
5861 if(program != 0 && !programObject->isLinked())
5862 {
5863 return error(GL_INVALID_OPERATION);
5864 }
5865
5866 context->useProgram(program);
5867 }
5868}
5869
5870void ValidateProgram(GLuint program)
5871{
5872 TRACE("(GLuint program = %d)", program);
5873
5874 es2::Context *context = es2::getContext();
5875
5876 if(context)
5877 {
5878 es2::Program *programObject = context->getProgram(program);
5879
5880 if(!programObject)
5881 {
5882 if(context->getShader(program))
5883 {
5884 return error(GL_INVALID_OPERATION);
5885 }
5886 else
5887 {
5888 return error(GL_INVALID_VALUE);
5889 }
5890 }
5891
Ben Vanik1fd3b282017-07-10 14:08:12 -07005892 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005893 }
5894}
5895
5896void VertexAttrib1f(GLuint index, GLfloat x)
5897{
5898 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5899
5900 if(index >= es2::MAX_VERTEX_ATTRIBS)
5901 {
5902 return error(GL_INVALID_VALUE);
5903 }
5904
5905 es2::Context *context = es2::getContext();
5906
5907 if(context)
5908 {
5909 GLfloat vals[4] = { x, 0, 0, 1 };
5910 context->setVertexAttrib(index, vals);
5911 }
5912}
5913
5914void VertexAttrib1fv(GLuint index, const GLfloat* values)
5915{
5916 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5917
5918 if(index >= es2::MAX_VERTEX_ATTRIBS)
5919 {
5920 return error(GL_INVALID_VALUE);
5921 }
5922
5923 es2::Context *context = es2::getContext();
5924
5925 if(context)
5926 {
5927 GLfloat vals[4] = { values[0], 0, 0, 1 };
5928 context->setVertexAttrib(index, vals);
5929 }
5930}
5931
5932void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5933{
5934 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5935
5936 if(index >= es2::MAX_VERTEX_ATTRIBS)
5937 {
5938 return error(GL_INVALID_VALUE);
5939 }
5940
5941 es2::Context *context = es2::getContext();
5942
5943 if(context)
5944 {
5945 GLfloat vals[4] = { x, y, 0, 1 };
5946 context->setVertexAttrib(index, vals);
5947 }
5948}
5949
5950void VertexAttrib2fv(GLuint index, const GLfloat* values)
5951{
5952 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5953
5954 if(index >= es2::MAX_VERTEX_ATTRIBS)
5955 {
5956 return error(GL_INVALID_VALUE);
5957 }
5958
5959 es2::Context *context = es2::getContext();
5960
5961 if(context)
5962 {
5963 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5964 context->setVertexAttrib(index, vals);
5965 }
5966}
5967
5968void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5969{
5970 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5971
5972 if(index >= es2::MAX_VERTEX_ATTRIBS)
5973 {
5974 return error(GL_INVALID_VALUE);
5975 }
5976
5977 es2::Context *context = es2::getContext();
5978
5979 if(context)
5980 {
5981 GLfloat vals[4] = { x, y, z, 1 };
5982 context->setVertexAttrib(index, vals);
5983 }
5984}
5985
5986void VertexAttrib3fv(GLuint index, const GLfloat* values)
5987{
5988 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5989
5990 if(index >= es2::MAX_VERTEX_ATTRIBS)
5991 {
5992 return error(GL_INVALID_VALUE);
5993 }
5994
5995 es2::Context *context = es2::getContext();
5996
5997 if(context)
5998 {
5999 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6000 context->setVertexAttrib(index, vals);
6001 }
6002}
6003
6004void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6005{
6006 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6007
6008 if(index >= es2::MAX_VERTEX_ATTRIBS)
6009 {
6010 return error(GL_INVALID_VALUE);
6011 }
6012
6013 es2::Context *context = es2::getContext();
6014
6015 if(context)
6016 {
6017 GLfloat vals[4] = { x, y, z, w };
6018 context->setVertexAttrib(index, vals);
6019 }
6020}
6021
6022void VertexAttrib4fv(GLuint index, const GLfloat* values)
6023{
6024 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6025
6026 if(index >= es2::MAX_VERTEX_ATTRIBS)
6027 {
6028 return error(GL_INVALID_VALUE);
6029 }
6030
6031 es2::Context *context = es2::getContext();
6032
6033 if(context)
6034 {
6035 context->setVertexAttrib(index, values);
6036 }
6037}
6038
6039void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6040{
6041 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6042 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6043 index, size, type, normalized, stride, ptr);
6044
6045 if(index >= es2::MAX_VERTEX_ATTRIBS)
6046 {
6047 return error(GL_INVALID_VALUE);
6048 }
6049
6050 if(size < 1 || size > 4)
6051 {
6052 return error(GL_INVALID_VALUE);
6053 }
6054
6055 GLint clientVersion = egl::getClientVersion();
6056
6057 switch(type)
6058 {
6059 case GL_BYTE:
6060 case GL_UNSIGNED_BYTE:
6061 case GL_SHORT:
6062 case GL_UNSIGNED_SHORT:
6063 case GL_FIXED:
6064 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006065 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006066 break;
6067 case GL_INT_2_10_10_10_REV:
6068 case GL_UNSIGNED_INT_2_10_10_10_REV:
6069 if(clientVersion >= 3)
6070 {
6071 if(size != 4)
6072 {
6073 return error(GL_INVALID_OPERATION);
6074 }
6075 break;
6076 }
6077 else return error(GL_INVALID_ENUM);
6078 case GL_INT:
6079 case GL_UNSIGNED_INT:
6080 case GL_HALF_FLOAT:
6081 if(clientVersion >= 3)
6082 {
6083 break;
6084 }
6085 else return error(GL_INVALID_ENUM);
6086 default:
6087 return error(GL_INVALID_ENUM);
6088 }
6089
6090 if(stride < 0)
6091 {
6092 return error(GL_INVALID_VALUE);
6093 }
6094
6095 es2::Context *context = es2::getContext();
6096
6097 if(context)
6098 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006099 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6100 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6101 {
6102 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6103 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6104 return error(GL_INVALID_OPERATION);
6105 }
6106
Alexis Hetu6f284032017-12-11 15:19:36 -05006107 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006108 }
6109}
6110
6111void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6112{
6113 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6114
6115 if(width < 0 || height < 0)
6116 {
6117 return error(GL_INVALID_VALUE);
6118 }
6119
6120 es2::Context *context = es2::getContext();
6121
6122 if(context)
6123 {
6124 context->setViewportParams(x, y, width, height);
6125 }
6126}
6127
Alexis Hetub9dda642016-10-06 11:25:32 -04006128static 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 -04006129{
6130 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6131 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6132 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6133 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6134
6135 switch(filter)
6136 {
6137 case GL_NEAREST:
6138 break;
6139 default:
6140 return error(GL_INVALID_ENUM);
6141 }
6142
6143 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6144 {
6145 return error(GL_INVALID_VALUE);
6146 }
6147
6148 es2::Context *context = es2::getContext();
6149
6150 if(context)
6151 {
6152 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6153 {
6154 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6155 return error(GL_INVALID_OPERATION);
6156 }
6157
Alexis Hetub9dda642016-10-06 11:25:32 -04006158 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006159 }
6160}
6161
Alexis Hetub9dda642016-10-06 11:25:32 -04006162void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6163{
6164 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6165}
6166
Nicolas Capens0bac2852016-05-07 06:09:58 -04006167void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6168 GLbitfield mask, GLenum filter)
6169{
6170 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6171 {
6172 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6173 return error(GL_INVALID_OPERATION);
6174 }
6175
Alexis Hetub9dda642016-10-06 11:25:32 -04006176 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006177}
6178
6179void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006180 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006181{
6182 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6183 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006184 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6185 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006186
6187 switch(target)
6188 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006189 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006190 switch(format)
6191 {
6192 case GL_DEPTH_COMPONENT:
6193 case GL_DEPTH_STENCIL_OES:
6194 return error(GL_INVALID_OPERATION);
6195 default:
6196 break;
6197 }
6198 break;
6199 default:
6200 return error(GL_INVALID_ENUM);
6201 }
6202
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006203 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006204 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006205 return error(GL_INVALID_OPERATION);
6206 }
6207
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006208 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, egl::getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05006209 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006210 {
6211 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006212 }
6213
6214 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6215 {
6216 return error(GL_INVALID_VALUE);
6217 }
6218
6219 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6220 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6221 {
6222 return error(GL_INVALID_VALUE);
6223 }
6224
6225 if(border != 0)
6226 {
6227 return error(GL_INVALID_VALUE);
6228 }
6229
6230 es2::Context *context = es2::getContext();
6231
6232 if(context)
6233 {
6234 es2::Texture3D *texture = context->getTexture3D();
6235
6236 if(!texture)
6237 {
6238 return error(GL_INVALID_OPERATION);
6239 }
6240
Nicolas Capens2fc90512018-01-23 22:24:22 +00006241 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006242 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006243 {
6244 return error(validationError);
6245 }
6246
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006247 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
6248 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006249 }
6250}
6251
Alexis Hetu53f48092016-06-17 14:08:06 -04006252void 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 -04006253{
6254 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6255 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006256 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6257 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006258
6259 switch(target)
6260 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006261 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006262 break;
6263 default:
6264 return error(GL_INVALID_ENUM);
6265 }
6266
Nicolas Capens0bac2852016-05-07 06:09:58 -04006267 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6268 {
6269 return error(GL_INVALID_VALUE);
6270 }
6271
6272 if((width < 0) || (height < 0) || (depth < 0))
6273 {
6274 return error(GL_INVALID_VALUE);
6275 }
6276
6277 es2::Context *context = es2::getContext();
6278
6279 if(context)
6280 {
6281 es2::Texture3D *texture = context->getTexture3D();
6282
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006283 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05006284 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006285 {
6286 return error(validationError);
6287 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006288
Nicolas Capens5555af42017-12-14 13:14:03 -05006289 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006290 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006291 {
6292 return error(validationError);
6293 }
6294
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006295 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006296 }
6297}
6298
6299void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6300{
6301 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6302 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6303 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6304
6305 switch(target)
6306 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006307 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006308 break;
6309 default:
6310 return error(GL_INVALID_ENUM);
6311 }
6312
6313 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6314 {
6315 return error(GL_INVALID_VALUE);
6316 }
6317
6318 es2::Context *context = es2::getContext();
6319
6320 if(context)
6321 {
6322 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6323
6324 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6325 {
6326 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6327 }
6328
6329 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6330
6331 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6332 {
6333 return error(GL_INVALID_OPERATION);
6334 }
6335
6336 es2::Texture3D *texture = context->getTexture3D();
6337
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006338 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05006339 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006340 {
6341 return error(validationError);
6342 }
6343
Nicolas Capens1529c2c2018-02-06 14:44:47 -05006344 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006345 }
6346}
6347
6348void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6349{
6350 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6351 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6352 target, level, internalformat, width, height, depth, border, imageSize, data);
6353
6354 switch(target)
6355 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006356 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006357 break;
6358 default:
6359 return error(GL_INVALID_ENUM);
6360 }
6361
6362 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6363 {
6364 return error(GL_INVALID_VALUE);
6365 }
6366
6367 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6368 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6369 {
6370 return error(GL_INVALID_VALUE);
6371 }
6372
Nicolas Capens03589982018-02-01 17:28:32 -05006373 if(!IsCompressed(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006374 {
Nicolas Capens03589982018-02-01 17:28:32 -05006375 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006376 }
6377
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006378 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006379 {
6380 return error(GL_INVALID_VALUE);
6381 }
6382
6383 es2::Context *context = es2::getContext();
6384
6385 if(context)
6386 {
6387 es2::Texture3D *texture = context->getTexture3D();
6388
6389 if(!texture)
6390 {
6391 return error(GL_INVALID_OPERATION);
6392 }
6393
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006394 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006395
Nicolas Capense65f5642018-02-26 17:47:06 -05006396 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006397 {
6398 return error(validationError);
6399 }
6400
Nicolas Capens0bac2852016-05-07 06:09:58 -04006401 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6402 }
6403}
6404
6405void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6406{
6407 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6408 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6409 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6410 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6411
6412 switch(target)
6413 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006414 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006415 break;
6416 default:
6417 return error(GL_INVALID_ENUM);
6418 }
6419
6420 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6421 {
6422 return error(GL_INVALID_VALUE);
6423 }
6424
6425 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6426 {
6427 return error(GL_INVALID_VALUE);
6428 }
6429
Nicolas Capens03589982018-02-01 17:28:32 -05006430 if(!IsCompressed(format, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006431 {
Nicolas Capens03589982018-02-01 17:28:32 -05006432 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006433 }
6434
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006435 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006436 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006437 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006438 }
6439
6440 es2::Context *context = es2::getContext();
6441
6442 if(context)
6443 {
6444 es2::Texture3D *texture = context->getTexture3D();
6445
6446 if(!texture)
6447 {
6448 return error(GL_INVALID_OPERATION);
6449 }
6450
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006451 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05006452 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006453 {
6454 return error(validationError);
6455 }
6456
6457 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006458 }
6459}
6460
6461void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6462{
6463 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6464 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6465
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006466 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006467 {
6468 return error(GL_INVALID_ENUM);
6469 }
6470
6471 es2::Context *context = es2::getContext();
6472
6473 if(context)
6474 {
6475 if(texture == 0)
6476 {
6477 textarget = GL_NONE;
6478 }
6479 else
6480 {
6481 es2::Texture *tex = context->getTexture(texture);
6482
6483 if(!tex)
6484 {
6485 return error(GL_INVALID_OPERATION);
6486 }
6487
6488 if(tex->isCompressed(textarget, level))
6489 {
6490 return error(GL_INVALID_OPERATION);
6491 }
6492
6493 switch(textarget)
6494 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006495 case GL_TEXTURE_3D:
6496 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006497 {
6498 return error(GL_INVALID_OPERATION);
6499 }
6500 break;
6501 default:
6502 return error(GL_INVALID_ENUM);
6503 }
6504
6505 if(level != 0)
6506 {
6507 return error(GL_INVALID_VALUE);
6508 }
6509 }
6510
6511 es2::Framebuffer *framebuffer = nullptr;
6512 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006513 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006514 {
6515 framebuffer = context->getReadFramebuffer();
6516 framebufferName = context->getReadFramebufferName();
6517 }
6518 else
6519 {
6520 framebuffer = context->getDrawFramebuffer();
6521 framebufferName = context->getDrawFramebufferName();
6522 }
6523
6524 if(framebufferName == 0 || !framebuffer)
6525 {
6526 return error(GL_INVALID_OPERATION);
6527 }
6528
6529 GLint clientVersion = context->getClientVersion();
6530
6531 switch(attachment)
6532 {
6533 case GL_COLOR_ATTACHMENT1:
6534 case GL_COLOR_ATTACHMENT2:
6535 case GL_COLOR_ATTACHMENT3:
6536 case GL_COLOR_ATTACHMENT4:
6537 case GL_COLOR_ATTACHMENT5:
6538 case GL_COLOR_ATTACHMENT6:
6539 case GL_COLOR_ATTACHMENT7:
6540 case GL_COLOR_ATTACHMENT8:
6541 case GL_COLOR_ATTACHMENT9:
6542 case GL_COLOR_ATTACHMENT10:
6543 case GL_COLOR_ATTACHMENT11:
6544 case GL_COLOR_ATTACHMENT12:
6545 case GL_COLOR_ATTACHMENT13:
6546 case GL_COLOR_ATTACHMENT14:
6547 case GL_COLOR_ATTACHMENT15:
6548 case GL_COLOR_ATTACHMENT16:
6549 case GL_COLOR_ATTACHMENT17:
6550 case GL_COLOR_ATTACHMENT18:
6551 case GL_COLOR_ATTACHMENT19:
6552 case GL_COLOR_ATTACHMENT20:
6553 case GL_COLOR_ATTACHMENT21:
6554 case GL_COLOR_ATTACHMENT22:
6555 case GL_COLOR_ATTACHMENT23:
6556 case GL_COLOR_ATTACHMENT24:
6557 case GL_COLOR_ATTACHMENT25:
6558 case GL_COLOR_ATTACHMENT26:
6559 case GL_COLOR_ATTACHMENT27:
6560 case GL_COLOR_ATTACHMENT28:
6561 case GL_COLOR_ATTACHMENT29:
6562 case GL_COLOR_ATTACHMENT30:
6563 case GL_COLOR_ATTACHMENT31:
6564 if(clientVersion < 3)
6565 {
6566 return error(GL_INVALID_ENUM);
6567 }
6568 // fall through
6569 case GL_COLOR_ATTACHMENT0:
6570 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6571 {
6572 return error(GL_INVALID_ENUM);
6573 }
6574 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6575 break;
6576 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6577 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6578 default:
6579 return error(GL_INVALID_ENUM);
6580 }
6581 }
6582}
6583
6584void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6585{
6586 if(egl::getClientVersion() == 1)
6587 {
6588 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6589 }
6590
6591 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6592
6593 switch(target)
6594 {
6595 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006596 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006597 case GL_TEXTURE_EXTERNAL_OES:
6598 break;
6599 default:
6600 return error(GL_INVALID_ENUM);
6601 }
6602
Nicolas Capens0bac2852016-05-07 06:09:58 -04006603 es2::Context *context = es2::getContext();
6604
6605 if(context)
6606 {
Alexis Hetu46768622018-01-16 22:09:28 -05006607 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006608
6609 if(!texture)
6610 {
6611 return error(GL_INVALID_OPERATION);
6612 }
6613
Nicolas Capens58df2f62016-06-07 14:48:56 -04006614 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006615
Nicolas Capens58df2f62016-06-07 14:48:56 -04006616 if(!eglImage)
6617 {
6618 return error(GL_INVALID_OPERATION);
6619 }
6620
6621 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006622 }
6623}
6624
6625void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6626{
6627 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6628
6629 UNIMPLEMENTED();
6630}
6631
6632GLboolean IsRenderbufferOES(GLuint renderbuffer)
6633{
6634 return IsRenderbuffer(renderbuffer);
6635}
6636
6637void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6638{
6639 BindRenderbuffer(target, renderbuffer);
6640}
6641
6642void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6643{
6644 DeleteRenderbuffers(n, renderbuffers);
6645}
6646
6647void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6648{
6649 GenRenderbuffers(n, renderbuffers);
6650}
6651
6652void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6653{
6654 RenderbufferStorage(target, internalformat, width, height);
6655}
6656
6657void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6658{
6659 GetRenderbufferParameteriv(target, pname, params);
6660}
6661
6662GLboolean IsFramebufferOES(GLuint framebuffer)
6663{
6664 return IsFramebuffer(framebuffer);
6665}
6666
6667void BindFramebufferOES(GLenum target, GLuint framebuffer)
6668{
6669 BindFramebuffer(target, framebuffer);
6670}
6671
6672void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6673{
6674 DeleteFramebuffers(n, framebuffers);
6675}
6676
6677void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6678{
6679 GenFramebuffers(n, framebuffers);
6680}
6681
6682GLenum CheckFramebufferStatusOES(GLenum target)
6683{
6684 return CheckFramebufferStatus(target);
6685}
6686
6687void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6688{
6689 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6690}
6691
6692void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6693{
6694 FramebufferTexture2D(target, attachment, textarget, texture, level);
6695}
6696
6697void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6698{
6699 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6700}
6701
6702void GenerateMipmapOES(GLenum target)
6703{
6704 GenerateMipmap(target);
6705}
6706
6707void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6708{
6709 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6710
6711 if(n < 0 || n > MAX_DRAW_BUFFERS)
6712 {
6713 return error(GL_INVALID_VALUE);
6714 }
6715
6716 es2::Context *context = es2::getContext();
6717
6718 if(context)
6719 {
6720 GLuint drawFramebufferName = context->getDrawFramebufferName();
6721
6722 if((drawFramebufferName == 0) && (n != 1))
6723 {
6724 return error(GL_INVALID_OPERATION);
6725 }
6726
6727 for(unsigned int i = 0; i < (unsigned)n; i++)
6728 {
6729 switch(bufs[i])
6730 {
6731 case GL_BACK:
6732 if(drawFramebufferName != 0)
6733 {
6734 return error(GL_INVALID_OPERATION);
6735 }
6736 break;
6737 case GL_NONE:
6738 break;
6739 case GL_COLOR_ATTACHMENT0_EXT:
6740 case GL_COLOR_ATTACHMENT1_EXT:
6741 case GL_COLOR_ATTACHMENT2_EXT:
6742 case GL_COLOR_ATTACHMENT3_EXT:
6743 case GL_COLOR_ATTACHMENT4_EXT:
6744 case GL_COLOR_ATTACHMENT5_EXT:
6745 case GL_COLOR_ATTACHMENT6_EXT:
6746 case GL_COLOR_ATTACHMENT7_EXT:
6747 case GL_COLOR_ATTACHMENT8_EXT:
6748 case GL_COLOR_ATTACHMENT9_EXT:
6749 case GL_COLOR_ATTACHMENT10_EXT:
6750 case GL_COLOR_ATTACHMENT11_EXT:
6751 case GL_COLOR_ATTACHMENT12_EXT:
6752 case GL_COLOR_ATTACHMENT13_EXT:
6753 case GL_COLOR_ATTACHMENT14_EXT:
6754 case GL_COLOR_ATTACHMENT15_EXT:
6755 {
6756 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6757
6758 if(index >= MAX_COLOR_ATTACHMENTS)
6759 {
6760 return error(GL_INVALID_OPERATION);
6761 }
6762
6763 if(index != i)
6764 {
6765 return error(GL_INVALID_OPERATION);
6766 }
6767
6768 if(drawFramebufferName == 0)
6769 {
6770 return error(GL_INVALID_OPERATION);
6771 }
6772 }
6773 break;
6774 default:
6775 return error(GL_INVALID_ENUM);
6776 }
6777 }
6778
6779 context->setFramebufferDrawBuffers(n, bufs);
6780 }
6781}
6782
6783}
6784
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006785extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006786{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006787 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006788 {
6789 const char *name;
6790 __eglMustCastToProperFunctionPointerType address;
6791 };
6792
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006793 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006794 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006795 bool operator()(const Function &a, const Function &b) const
6796 {
6797 return strcmp(a.name, b.name) < 0;
6798 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006799 };
6800
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006801 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6802 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6803 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006804 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006805 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6806
6807 FUNCTION(glActiveTexture),
6808 FUNCTION(glAttachShader),
6809 FUNCTION(glBeginQuery),
6810 FUNCTION(glBeginQueryEXT),
6811 FUNCTION(glBeginTransformFeedback),
6812 FUNCTION(glBindAttribLocation),
6813 FUNCTION(glBindBuffer),
6814 FUNCTION(glBindBufferBase),
6815 FUNCTION(glBindBufferRange),
6816 FUNCTION(glBindFramebuffer),
6817 FUNCTION(glBindFramebufferOES),
6818 FUNCTION(glBindRenderbuffer),
6819 FUNCTION(glBindRenderbufferOES),
6820 FUNCTION(glBindSampler),
6821 FUNCTION(glBindTexture),
6822 FUNCTION(glBindTransformFeedback),
6823 FUNCTION(glBindVertexArray),
6824 FUNCTION(glBlendColor),
6825 FUNCTION(glBlendEquation),
6826 FUNCTION(glBlendEquationSeparate),
6827 FUNCTION(glBlendFunc),
6828 FUNCTION(glBlendFuncSeparate),
6829 FUNCTION(glBlitFramebuffer),
6830 FUNCTION(glBlitFramebufferANGLE),
6831 FUNCTION(glBufferData),
6832 FUNCTION(glBufferSubData),
6833 FUNCTION(glCheckFramebufferStatus),
6834 FUNCTION(glCheckFramebufferStatusOES),
6835 FUNCTION(glClear),
6836 FUNCTION(glClearBufferfi),
6837 FUNCTION(glClearBufferfv),
6838 FUNCTION(glClearBufferiv),
6839 FUNCTION(glClearBufferuiv),
6840 FUNCTION(glClearColor),
6841 FUNCTION(glClearDepthf),
6842 FUNCTION(glClearStencil),
6843 FUNCTION(glClientWaitSync),
6844 FUNCTION(glColorMask),
6845 FUNCTION(glCompileShader),
6846 FUNCTION(glCompressedTexImage2D),
6847 FUNCTION(glCompressedTexImage3D),
6848 FUNCTION(glCompressedTexSubImage2D),
6849 FUNCTION(glCompressedTexSubImage3D),
6850 FUNCTION(glCopyBufferSubData),
6851 FUNCTION(glCopyTexImage2D),
6852 FUNCTION(glCopyTexSubImage2D),
6853 FUNCTION(glCopyTexSubImage3D),
6854 FUNCTION(glCreateProgram),
6855 FUNCTION(glCreateShader),
6856 FUNCTION(glCullFace),
6857 FUNCTION(glDeleteBuffers),
6858 FUNCTION(glDeleteFencesNV),
6859 FUNCTION(glDeleteFramebuffers),
6860 FUNCTION(glDeleteFramebuffersOES),
6861 FUNCTION(glDeleteProgram),
6862 FUNCTION(glDeleteQueries),
6863 FUNCTION(glDeleteQueriesEXT),
6864 FUNCTION(glDeleteRenderbuffers),
6865 FUNCTION(glDeleteRenderbuffersOES),
6866 FUNCTION(glDeleteSamplers),
6867 FUNCTION(glDeleteShader),
6868 FUNCTION(glDeleteSync),
6869 FUNCTION(glDeleteTextures),
6870 FUNCTION(glDeleteTransformFeedbacks),
6871 FUNCTION(glDeleteVertexArrays),
6872 FUNCTION(glDepthFunc),
6873 FUNCTION(glDepthMask),
6874 FUNCTION(glDepthRangef),
6875 FUNCTION(glDetachShader),
6876 FUNCTION(glDisable),
6877 FUNCTION(glDisableVertexAttribArray),
6878 FUNCTION(glDrawArrays),
6879 FUNCTION(glDrawArraysInstanced),
6880 FUNCTION(glDrawBuffers),
6881 FUNCTION(glDrawBuffersEXT),
6882 FUNCTION(glDrawElements),
6883 FUNCTION(glDrawElementsInstanced),
6884 FUNCTION(glDrawRangeElements),
6885 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6886 FUNCTION(glEGLImageTargetTexture2DOES),
6887 FUNCTION(glEnable),
6888 FUNCTION(glEnableVertexAttribArray),
6889 FUNCTION(glEndQuery),
6890 FUNCTION(glEndQueryEXT),
6891 FUNCTION(glEndTransformFeedback),
6892 FUNCTION(glFenceSync),
6893 FUNCTION(glFinish),
6894 FUNCTION(glFinishFenceNV),
6895 FUNCTION(glFlush),
6896 FUNCTION(glFlushMappedBufferRange),
6897 FUNCTION(glFramebufferRenderbuffer),
6898 FUNCTION(glFramebufferRenderbufferOES),
6899 FUNCTION(glFramebufferTexture2D),
6900 FUNCTION(glFramebufferTexture2DOES),
6901 FUNCTION(glFramebufferTextureLayer),
6902 FUNCTION(glFrontFace),
6903 FUNCTION(glGenBuffers),
6904 FUNCTION(glGenFencesNV),
6905 FUNCTION(glGenFramebuffers),
6906 FUNCTION(glGenFramebuffersOES),
6907 FUNCTION(glGenQueries),
6908 FUNCTION(glGenQueriesEXT),
6909 FUNCTION(glGenRenderbuffers),
6910 FUNCTION(glGenRenderbuffersOES),
6911 FUNCTION(glGenSamplers),
6912 FUNCTION(glGenTextures),
6913 FUNCTION(glGenTransformFeedbacks),
6914 FUNCTION(glGenVertexArrays),
6915 FUNCTION(glGenerateMipmap),
6916 FUNCTION(glGenerateMipmapOES),
6917 FUNCTION(glGetActiveAttrib),
6918 FUNCTION(glGetActiveUniform),
6919 FUNCTION(glGetActiveUniformBlockName),
6920 FUNCTION(glGetActiveUniformBlockiv),
6921 FUNCTION(glGetActiveUniformsiv),
6922 FUNCTION(glGetAttachedShaders),
6923 FUNCTION(glGetAttribLocation),
6924 FUNCTION(glGetBooleanv),
6925 FUNCTION(glGetBufferParameteri64v),
6926 FUNCTION(glGetBufferParameteriv),
6927 FUNCTION(glGetBufferPointerv),
6928 FUNCTION(glGetError),
6929 FUNCTION(glGetFenceivNV),
6930 FUNCTION(glGetFloatv),
6931 FUNCTION(glGetFragDataLocation),
6932 FUNCTION(glGetFramebufferAttachmentParameteriv),
6933 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6934 FUNCTION(glGetGraphicsResetStatusEXT),
6935 FUNCTION(glGetInteger64i_v),
6936 FUNCTION(glGetInteger64v),
6937 FUNCTION(glGetIntegeri_v),
6938 FUNCTION(glGetIntegerv),
6939 FUNCTION(glGetInternalformativ),
6940 FUNCTION(glGetProgramBinary),
6941 FUNCTION(glGetProgramInfoLog),
6942 FUNCTION(glGetProgramiv),
6943 FUNCTION(glGetQueryObjectuiv),
6944 FUNCTION(glGetQueryObjectuivEXT),
6945 FUNCTION(glGetQueryiv),
6946 FUNCTION(glGetQueryivEXT),
6947 FUNCTION(glGetRenderbufferParameteriv),
6948 FUNCTION(glGetRenderbufferParameterivOES),
6949 FUNCTION(glGetSamplerParameterfv),
6950 FUNCTION(glGetSamplerParameteriv),
6951 FUNCTION(glGetShaderInfoLog),
6952 FUNCTION(glGetShaderPrecisionFormat),
6953 FUNCTION(glGetShaderSource),
6954 FUNCTION(glGetShaderiv),
6955 FUNCTION(glGetString),
6956 FUNCTION(glGetStringi),
6957 FUNCTION(glGetSynciv),
6958 FUNCTION(glGetTexParameterfv),
6959 FUNCTION(glGetTexParameteriv),
6960 FUNCTION(glGetTransformFeedbackVarying),
6961 FUNCTION(glGetUniformBlockIndex),
6962 FUNCTION(glGetUniformIndices),
6963 FUNCTION(glGetUniformLocation),
6964 FUNCTION(glGetUniformfv),
6965 FUNCTION(glGetUniformiv),
6966 FUNCTION(glGetUniformuiv),
6967 FUNCTION(glGetVertexAttribIiv),
6968 FUNCTION(glGetVertexAttribIuiv),
6969 FUNCTION(glGetVertexAttribPointerv),
6970 FUNCTION(glGetVertexAttribfv),
6971 FUNCTION(glGetVertexAttribiv),
6972 FUNCTION(glGetnUniformfvEXT),
6973 FUNCTION(glGetnUniformivEXT),
6974 FUNCTION(glHint),
6975 FUNCTION(glInvalidateFramebuffer),
6976 FUNCTION(glInvalidateSubFramebuffer),
6977 FUNCTION(glIsBuffer),
6978 FUNCTION(glIsEnabled),
6979 FUNCTION(glIsFenceNV),
6980 FUNCTION(glIsFramebuffer),
6981 FUNCTION(glIsFramebufferOES),
6982 FUNCTION(glIsProgram),
6983 FUNCTION(glIsQuery),
6984 FUNCTION(glIsQueryEXT),
6985 FUNCTION(glIsRenderbuffer),
6986 FUNCTION(glIsRenderbufferOES),
6987 FUNCTION(glIsSampler),
6988 FUNCTION(glIsShader),
6989 FUNCTION(glIsSync),
6990 FUNCTION(glIsTexture),
6991 FUNCTION(glIsTransformFeedback),
6992 FUNCTION(glIsVertexArray),
6993 FUNCTION(glLineWidth),
6994 FUNCTION(glLinkProgram),
6995 FUNCTION(glMapBufferRange),
6996 FUNCTION(glPauseTransformFeedback),
6997 FUNCTION(glPixelStorei),
6998 FUNCTION(glPolygonOffset),
6999 FUNCTION(glProgramBinary),
7000 FUNCTION(glProgramParameteri),
7001 FUNCTION(glReadBuffer),
7002 FUNCTION(glReadPixels),
7003 FUNCTION(glReadnPixelsEXT),
7004 FUNCTION(glReleaseShaderCompiler),
7005 FUNCTION(glRenderbufferStorage),
7006 FUNCTION(glRenderbufferStorageMultisample),
7007 FUNCTION(glRenderbufferStorageMultisampleANGLE),
7008 FUNCTION(glRenderbufferStorageOES),
7009 FUNCTION(glResumeTransformFeedback),
7010 FUNCTION(glSampleCoverage),
7011 FUNCTION(glSamplerParameterf),
7012 FUNCTION(glSamplerParameterfv),
7013 FUNCTION(glSamplerParameteri),
7014 FUNCTION(glSamplerParameteriv),
7015 FUNCTION(glScissor),
7016 FUNCTION(glSetFenceNV),
7017 FUNCTION(glShaderBinary),
7018 FUNCTION(glShaderSource),
7019 FUNCTION(glStencilFunc),
7020 FUNCTION(glStencilFuncSeparate),
7021 FUNCTION(glStencilMask),
7022 FUNCTION(glStencilMaskSeparate),
7023 FUNCTION(glStencilOp),
7024 FUNCTION(glStencilOpSeparate),
7025 FUNCTION(glTestFenceNV),
7026 FUNCTION(glTexImage2D),
7027 FUNCTION(glTexImage3D),
7028 FUNCTION(glTexImage3DOES),
7029 FUNCTION(glTexParameterf),
7030 FUNCTION(glTexParameterfv),
7031 FUNCTION(glTexParameteri),
7032 FUNCTION(glTexParameteriv),
7033 FUNCTION(glTexStorage2D),
7034 FUNCTION(glTexStorage3D),
7035 FUNCTION(glTexSubImage2D),
7036 FUNCTION(glTexSubImage3D),
7037 FUNCTION(glTransformFeedbackVaryings),
7038 FUNCTION(glUniform1f),
7039 FUNCTION(glUniform1fv),
7040 FUNCTION(glUniform1i),
7041 FUNCTION(glUniform1iv),
7042 FUNCTION(glUniform1ui),
7043 FUNCTION(glUniform1uiv),
7044 FUNCTION(glUniform2f),
7045 FUNCTION(glUniform2fv),
7046 FUNCTION(glUniform2i),
7047 FUNCTION(glUniform2iv),
7048 FUNCTION(glUniform2ui),
7049 FUNCTION(glUniform2uiv),
7050 FUNCTION(glUniform3f),
7051 FUNCTION(glUniform3fv),
7052 FUNCTION(glUniform3i),
7053 FUNCTION(glUniform3iv),
7054 FUNCTION(glUniform3ui),
7055 FUNCTION(glUniform3uiv),
7056 FUNCTION(glUniform4f),
7057 FUNCTION(glUniform4fv),
7058 FUNCTION(glUniform4i),
7059 FUNCTION(glUniform4iv),
7060 FUNCTION(glUniform4ui),
7061 FUNCTION(glUniform4uiv),
7062 FUNCTION(glUniformBlockBinding),
7063 FUNCTION(glUniformMatrix2fv),
7064 FUNCTION(glUniformMatrix2x3fv),
7065 FUNCTION(glUniformMatrix2x4fv),
7066 FUNCTION(glUniformMatrix3fv),
7067 FUNCTION(glUniformMatrix3x2fv),
7068 FUNCTION(glUniformMatrix3x4fv),
7069 FUNCTION(glUniformMatrix4fv),
7070 FUNCTION(glUniformMatrix4x2fv),
7071 FUNCTION(glUniformMatrix4x3fv),
7072 FUNCTION(glUnmapBuffer),
7073 FUNCTION(glUseProgram),
7074 FUNCTION(glValidateProgram),
7075 FUNCTION(glVertexAttrib1f),
7076 FUNCTION(glVertexAttrib1fv),
7077 FUNCTION(glVertexAttrib2f),
7078 FUNCTION(glVertexAttrib2fv),
7079 FUNCTION(glVertexAttrib3f),
7080 FUNCTION(glVertexAttrib3fv),
7081 FUNCTION(glVertexAttrib4f),
7082 FUNCTION(glVertexAttrib4fv),
7083 FUNCTION(glVertexAttribDivisor),
7084 FUNCTION(glVertexAttribI4i),
7085 FUNCTION(glVertexAttribI4iv),
7086 FUNCTION(glVertexAttribI4ui),
7087 FUNCTION(glVertexAttribI4uiv),
7088 FUNCTION(glVertexAttribIPointer),
7089 FUNCTION(glVertexAttribPointer),
7090 FUNCTION(glViewport),
7091 FUNCTION(glWaitSync),
7092
7093 #undef FUNCTION
7094 };
7095
7096 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
7097 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
7098
7099 Function needle;
7100 needle.name = procname;
7101
7102 if(procname && strncmp("gl", procname, 2) == 0)
7103 {
7104 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
7105 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04007106 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01007107 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04007108 }
7109 }
7110
7111 return nullptr;
7112}