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