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