blob: 9f96d472cb4d23d9e4fad3049b50d93784ddc7d5 [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:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002264 {
2265 TextureCubeMap *cube = context->getTextureCubeMap();
2266 texture = cube;
2267
2268 if(!cube->isCubeComplete())
2269 {
2270 return error(GL_INVALID_OPERATION);
2271 }
2272 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002273 break;
2274 case GL_TEXTURE_2D_ARRAY:
2275 if(clientVersion < 3)
2276 {
2277 return error(GL_INVALID_ENUM);
2278 }
2279 else
2280 {
2281 texture = context->getTexture2DArray();
2282 }
2283 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002284 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002285 texture = context->getTexture3D();
2286 break;
2287 default:
2288 return error(GL_INVALID_ENUM);
2289 }
2290
Nicolas Capense6115342017-12-18 15:58:46 -05002291 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel()), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002292 {
2293 return error(GL_INVALID_OPERATION);
2294 }
2295
Nicolas Capens0bac2852016-05-07 06:09:58 -04002296 texture->generateMipmaps();
2297 }
2298}
2299
2300void GenFencesNV(GLsizei n, GLuint* fences)
2301{
2302 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2303
2304 if(n < 0)
2305 {
2306 return error(GL_INVALID_VALUE);
2307 }
2308
2309 es2::Context *context = es2::getContext();
2310
2311 if(context)
2312 {
2313 for(int i = 0; i < n; i++)
2314 {
2315 fences[i] = context->createFence();
2316 }
2317 }
2318}
2319
2320void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2321{
2322 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2323
2324 if(n < 0)
2325 {
2326 return error(GL_INVALID_VALUE);
2327 }
2328
2329 es2::Context *context = es2::getContext();
2330
2331 if(context)
2332 {
2333 for(int i = 0; i < n; i++)
2334 {
2335 framebuffers[i] = context->createFramebuffer();
2336 }
2337 }
2338}
2339
2340void GenQueriesEXT(GLsizei n, GLuint* ids)
2341{
2342 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2343
2344 if(n < 0)
2345 {
2346 return error(GL_INVALID_VALUE);
2347 }
2348
2349 es2::Context *context = es2::getContext();
2350
2351 if(context)
2352 {
2353 for(int i = 0; i < n; i++)
2354 {
2355 ids[i] = context->createQuery();
2356 }
2357 }
2358}
2359
2360void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2361{
2362 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2363
2364 if(n < 0)
2365 {
2366 return error(GL_INVALID_VALUE);
2367 }
2368
2369 es2::Context *context = es2::getContext();
2370
2371 if(context)
2372 {
2373 for(int i = 0; i < n; i++)
2374 {
2375 renderbuffers[i] = context->createRenderbuffer();
2376 }
2377 }
2378}
2379
2380void GenTextures(GLsizei n, GLuint* textures)
2381{
2382 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2383
2384 if(n < 0)
2385 {
2386 return error(GL_INVALID_VALUE);
2387 }
2388
2389 es2::Context *context = es2::getContext();
2390
2391 if(context)
2392 {
2393 for(int i = 0; i < n; i++)
2394 {
2395 textures[i] = context->createTexture();
2396 }
2397 }
2398}
2399
2400void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2401{
2402 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2403 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2404 program, index, bufsize, length, size, type, name);
2405
2406 if(bufsize < 0)
2407 {
2408 return error(GL_INVALID_VALUE);
2409 }
2410
2411 es2::Context *context = es2::getContext();
2412
2413 if(context)
2414 {
2415 es2::Program *programObject = context->getProgram(program);
2416
2417 if(!programObject)
2418 {
2419 if(context->getShader(program))
2420 {
2421 return error(GL_INVALID_OPERATION);
2422 }
2423 else
2424 {
2425 return error(GL_INVALID_VALUE);
2426 }
2427 }
2428
2429 if(index >= programObject->getActiveAttributeCount())
2430 {
2431 return error(GL_INVALID_VALUE);
2432 }
2433
2434 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2435 }
2436}
2437
2438void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2439{
2440 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2441 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2442 program, index, bufsize, length, size, type, name);
2443
2444 if(bufsize < 0)
2445 {
2446 return error(GL_INVALID_VALUE);
2447 }
2448
2449 es2::Context *context = es2::getContext();
2450
2451 if(context)
2452 {
2453 es2::Program *programObject = context->getProgram(program);
2454
2455 if(!programObject)
2456 {
2457 if(context->getShader(program))
2458 {
2459 return error(GL_INVALID_OPERATION);
2460 }
2461 else
2462 {
2463 return error(GL_INVALID_VALUE);
2464 }
2465 }
2466
2467 if(index >= programObject->getActiveUniformCount())
2468 {
2469 return error(GL_INVALID_VALUE);
2470 }
2471
2472 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2473 }
2474}
2475
2476void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2477{
2478 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2479 program, maxcount, count, shaders);
2480
2481 if(maxcount < 0)
2482 {
2483 return error(GL_INVALID_VALUE);
2484 }
2485
2486 es2::Context *context = es2::getContext();
2487
2488 if(context)
2489 {
2490 es2::Program *programObject = context->getProgram(program);
2491
2492 if(!programObject)
2493 {
2494 if(context->getShader(program))
2495 {
2496 return error(GL_INVALID_OPERATION);
2497 }
2498 else
2499 {
2500 return error(GL_INVALID_VALUE);
2501 }
2502 }
2503
2504 return programObject->getAttachedShaders(maxcount, count, shaders);
2505 }
2506}
2507
2508int GetAttribLocation(GLuint program, const GLchar* name)
2509{
2510 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2511
2512 es2::Context *context = es2::getContext();
2513
2514 if(context)
2515 {
2516
2517 es2::Program *programObject = context->getProgram(program);
2518
2519 if(!programObject)
2520 {
2521 if(context->getShader(program))
2522 {
2523 return error(GL_INVALID_OPERATION, -1);
2524 }
2525 else
2526 {
2527 return error(GL_INVALID_VALUE, -1);
2528 }
2529 }
2530
2531 if(!programObject->isLinked())
2532 {
2533 return error(GL_INVALID_OPERATION, -1);
2534 }
2535
2536 return programObject->getAttributeLocation(name);
2537 }
2538
2539 return -1;
2540}
2541
2542void GetBooleanv(GLenum pname, GLboolean* params)
2543{
2544 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2545
2546 es2::Context *context = es2::getContext();
2547
2548 if(context)
2549 {
2550 if(!(context->getBooleanv(pname, params)))
2551 {
2552 GLenum nativeType;
2553 unsigned int numParams = 0;
2554 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2555 return error(GL_INVALID_ENUM);
2556
2557 if(numParams == 0)
2558 return; // it is known that the pname is valid, but there are no parameters to return
2559
2560 if(nativeType == GL_FLOAT)
2561 {
2562 GLfloat *floatParams = nullptr;
2563 floatParams = new GLfloat[numParams];
2564
2565 context->getFloatv(pname, floatParams);
2566
2567 for(unsigned int i = 0; i < numParams; ++i)
2568 {
2569 if(floatParams[i] == 0.0f)
2570 params[i] = GL_FALSE;
2571 else
2572 params[i] = GL_TRUE;
2573 }
2574
2575 delete [] floatParams;
2576 }
2577 else if(nativeType == GL_INT)
2578 {
2579 GLint *intParams = nullptr;
2580 intParams = new GLint[numParams];
2581
2582 context->getIntegerv(pname, intParams);
2583
2584 for(unsigned int i = 0; i < numParams; ++i)
2585 {
2586 if(intParams[i] == 0)
2587 params[i] = GL_FALSE;
2588 else
2589 params[i] = GL_TRUE;
2590 }
2591
2592 delete [] intParams;
2593 }
2594 }
2595 }
2596}
2597
2598void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2599{
2600 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2601
2602 es2::Context *context = es2::getContext();
2603
2604 if(context)
2605 {
2606 es2::Buffer *buffer;
2607 if(!context->getBuffer(target, &buffer))
2608 {
2609 return error(GL_INVALID_ENUM);
2610 }
2611
2612 if(!buffer)
2613 {
2614 // A null buffer means that "0" is bound to the requested buffer target
2615 return error(GL_INVALID_OPERATION);
2616 }
2617
2618 GLint clientVersion = context->getClientVersion();
2619
2620 switch(pname)
2621 {
2622 case GL_BUFFER_USAGE:
2623 *params = buffer->usage();
2624 break;
2625 case GL_BUFFER_SIZE:
2626 *params = (GLint)buffer->size();
2627 break;
2628 case GL_BUFFER_ACCESS_FLAGS:
2629 if(clientVersion >= 3)
2630 {
2631 *params = buffer->access();
2632 break;
2633 }
2634 else return error(GL_INVALID_ENUM);
2635 case GL_BUFFER_MAPPED:
2636 if(clientVersion >= 3)
2637 {
2638 *params = buffer->isMapped();
2639 break;
2640 }
2641 else return error(GL_INVALID_ENUM);
2642 case GL_BUFFER_MAP_LENGTH:
2643 if(clientVersion >= 3)
2644 {
2645 *params = (GLint)buffer->length();
2646 break;
2647 }
2648 else return error(GL_INVALID_ENUM);
2649 case GL_BUFFER_MAP_OFFSET:
2650 if(clientVersion >= 3)
2651 {
2652 *params = (GLint)buffer->offset();
2653 break;
2654 }
2655 else return error(GL_INVALID_ENUM);
2656 default:
2657 return error(GL_INVALID_ENUM);
2658 }
2659 }
2660}
2661
2662GLenum GetError(void)
2663{
2664 TRACE("()");
2665
2666 es2::Context *context = es2::getContext();
2667
2668 if(context)
2669 {
2670 return context->getError();
2671 }
2672
2673 return GL_NO_ERROR;
2674}
2675
2676void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2677{
2678 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2679
2680 es2::Context *context = es2::getContext();
2681
2682 if(context)
2683 {
2684 es2::Fence *fenceObject = context->getFence(fence);
2685
2686 if(!fenceObject)
2687 {
2688 return error(GL_INVALID_OPERATION);
2689 }
2690
2691 fenceObject->getFenceiv(pname, params);
2692 }
2693}
2694
2695void GetFloatv(GLenum pname, GLfloat* params)
2696{
2697 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2698
2699 es2::Context *context = es2::getContext();
2700
2701 if(context)
2702 {
2703 if(!(context->getFloatv(pname, params)))
2704 {
2705 GLenum nativeType;
2706 unsigned int numParams = 0;
2707 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2708 return error(GL_INVALID_ENUM);
2709
2710 if(numParams == 0)
2711 return; // it is known that the pname is valid, but that there are no parameters to return.
2712
2713 if(nativeType == GL_BOOL)
2714 {
2715 GLboolean *boolParams = nullptr;
2716 boolParams = new GLboolean[numParams];
2717
2718 context->getBooleanv(pname, boolParams);
2719
2720 for(unsigned int i = 0; i < numParams; ++i)
2721 {
2722 if(boolParams[i] == GL_FALSE)
2723 params[i] = 0.0f;
2724 else
2725 params[i] = 1.0f;
2726 }
2727
2728 delete [] boolParams;
2729 }
2730 else if(nativeType == GL_INT)
2731 {
2732 GLint *intParams = nullptr;
2733 intParams = new GLint[numParams];
2734
2735 context->getIntegerv(pname, intParams);
2736
2737 for(unsigned int i = 0; i < numParams; ++i)
2738 {
2739 params[i] = (GLfloat)intParams[i];
2740 }
2741
2742 delete [] intParams;
2743 }
2744 }
2745 }
2746}
2747
2748void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2749{
2750 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2751 target, attachment, pname, params);
2752
2753 es2::Context *context = es2::getContext();
2754
2755 if(context)
2756 {
2757 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2758 {
2759 return error(GL_INVALID_ENUM);
2760 }
2761
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002762 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002763
Nicolas Capens0bac2852016-05-07 06:09:58 -04002764 if(target == GL_READ_FRAMEBUFFER)
2765 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002766 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002767 }
2768 else
2769 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002770 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002771 }
2772
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002773 GLint clientVersion = context->getClientVersion();
2774
2775 if(framebufferName == 0) // Default framebuffer.
2776 {
2777 if(clientVersion < 3)
2778 {
2779 return error(GL_INVALID_OPERATION);
2780 }
2781 }
2782
Nicolas Capens0bac2852016-05-07 06:09:58 -04002783 switch(attachment)
2784 {
2785 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002786 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002787 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002788 if(clientVersion < 3)
2789 {
2790 return error(GL_INVALID_ENUM);
2791 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002792
2793 if(framebufferName != 0)
2794 {
2795 return error(GL_INVALID_OPERATION);
2796 }
2797 break;
2798 case GL_DEPTH_ATTACHMENT:
2799 case GL_STENCIL_ATTACHMENT:
2800 if(framebufferName == 0)
2801 {
2802 return error(GL_INVALID_OPERATION);
2803 }
2804 break;
2805 case GL_DEPTH_STENCIL_ATTACHMENT:
2806 if(clientVersion < 3)
2807 {
2808 return error(GL_INVALID_ENUM);
2809 }
2810
2811 if(framebufferName == 0)
2812 {
2813 return error(GL_INVALID_OPERATION);
2814 }
2815 break;
2816 default:
2817 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2818 {
2819 if(framebufferName == 0)
2820 {
2821 return error(GL_INVALID_OPERATION);
2822 }
2823 }
2824 else return error(GL_INVALID_ENUM);
2825 }
2826
2827 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2828
2829 GLenum attachmentType;
2830 GLuint attachmentHandle;
2831 GLint attachmentLayer;
2832 Renderbuffer *renderbuffer = nullptr;
2833 switch(attachment)
2834 {
2835 case GL_BACK:
2836 attachmentType = framebuffer->getColorbufferType(0);
2837 attachmentHandle = framebuffer->getColorbufferName(0);
2838 attachmentLayer = framebuffer->getColorbufferLayer(0);
2839 renderbuffer = framebuffer->getColorbuffer(0);
2840 break;
2841 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002842 case GL_DEPTH_ATTACHMENT:
2843 attachmentType = framebuffer->getDepthbufferType();
2844 attachmentHandle = framebuffer->getDepthbufferName();
2845 attachmentLayer = framebuffer->getDepthbufferLayer();
2846 renderbuffer = framebuffer->getDepthbuffer();
2847 break;
2848 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002849 case GL_STENCIL_ATTACHMENT:
2850 attachmentType = framebuffer->getStencilbufferType();
2851 attachmentHandle = framebuffer->getStencilbufferName();
2852 attachmentLayer = framebuffer->getStencilbufferLayer();
2853 renderbuffer = framebuffer->getStencilbuffer();
2854 break;
2855 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002856 attachmentType = framebuffer->getDepthbufferType();
2857 attachmentHandle = framebuffer->getDepthbufferName();
2858 attachmentLayer = framebuffer->getDepthbufferLayer();
2859 renderbuffer = framebuffer->getDepthbuffer();
2860
2861 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002862 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002863 // Different attachments to DEPTH and STENCIL, query fails
2864 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002865 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002866 break;
2867 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002868 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2869 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2870 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2871 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2872 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2873 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002874 }
2875
2876 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002877 if(framebufferName == 0)
2878 {
2879 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2880 }
2881 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002882 {
2883 attachmentObjectType = attachmentType;
2884 }
2885 else if(es2::IsTextureTarget(attachmentType))
2886 {
2887 attachmentObjectType = GL_TEXTURE;
2888 }
2889 else UNREACHABLE(attachmentType);
2890
2891 if(attachmentObjectType != GL_NONE)
2892 {
2893 switch(pname)
2894 {
2895 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2896 *params = attachmentObjectType;
2897 break;
2898 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002899 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002900 {
2901 *params = attachmentHandle;
2902 }
2903 else
2904 {
2905 return error(GL_INVALID_ENUM);
2906 }
2907 break;
2908 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2909 if(attachmentObjectType == GL_TEXTURE)
2910 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002911 *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 -04002912 }
2913 else
2914 {
2915 return error(GL_INVALID_ENUM);
2916 }
2917 break;
2918 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2919 if(attachmentObjectType == GL_TEXTURE)
2920 {
2921 if(es2::IsCubemapTextureTarget(attachmentType))
2922 {
2923 *params = attachmentType;
2924 }
2925 else
2926 {
2927 *params = 0;
2928 }
2929 }
2930 else
2931 {
2932 return error(GL_INVALID_ENUM);
2933 }
2934 break;
2935 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2936 if(clientVersion >= 3)
2937 {
2938 *params = attachmentLayer;
2939 }
2940 else return error(GL_INVALID_ENUM);
2941 break;
2942 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2943 if(clientVersion >= 3)
2944 {
2945 *params = renderbuffer->getRedSize();
2946 }
2947 else return error(GL_INVALID_ENUM);
2948 break;
2949 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2950 if(clientVersion >= 3)
2951 {
2952 *params = renderbuffer->getGreenSize();
2953 }
2954 else return error(GL_INVALID_ENUM);
2955 break;
2956 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2957 if(clientVersion >= 3)
2958 {
2959 *params = renderbuffer->getBlueSize();
2960 }
2961 else return error(GL_INVALID_ENUM);
2962 break;
2963 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2964 if(clientVersion >= 3)
2965 {
2966 *params = renderbuffer->getAlphaSize();
2967 }
2968 else return error(GL_INVALID_ENUM);
2969 break;
2970 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2971 if(clientVersion >= 3)
2972 {
2973 *params = renderbuffer->getDepthSize();
2974 }
2975 else return error(GL_INVALID_ENUM);
2976 break;
2977 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2978 if(clientVersion >= 3)
2979 {
2980 *params = renderbuffer->getStencilSize();
2981 }
2982 else return error(GL_INVALID_ENUM);
2983 break;
2984 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002985 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2986 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002987 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002988 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002989 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002990
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002991 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002992 break;
2993 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2994 if(clientVersion >= 3)
2995 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002996 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002997 }
2998 else return error(GL_INVALID_ENUM);
2999 break;
3000 default:
3001 return error(GL_INVALID_ENUM);
3002 }
3003 }
3004 else
3005 {
3006 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3007 // is NONE, then querying any other pname will generate INVALID_ENUM.
3008
3009 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3010 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3011 // INVALID_OPERATION for all other pnames
3012
3013 switch(pname)
3014 {
3015 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3016 *params = GL_NONE;
3017 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003018 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3019 if(clientVersion < 3)
3020 {
3021 return error(GL_INVALID_ENUM);
3022 }
3023 *params = 0;
3024 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003025 default:
3026 if(clientVersion < 3)
3027 {
3028 return error(GL_INVALID_ENUM);
3029 }
3030 else
3031 {
3032 return error(GL_INVALID_OPERATION);
3033 }
3034 }
3035 }
3036 }
3037}
3038
3039GLenum GetGraphicsResetStatusEXT(void)
3040{
3041 TRACE("()");
3042
3043 return GL_NO_ERROR;
3044}
3045
3046void GetIntegerv(GLenum pname, GLint* params)
3047{
3048 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
3049
3050 es2::Context *context = es2::getContext();
3051
3052 if(!context)
3053 {
3054 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
3055 #ifdef __ANDROID__
3056 ALOGI("expected_badness glGetIntegerv() called without current context.");
3057 #else
3058 ERR("glGetIntegerv() called without current context.");
3059 #endif
3060
3061 // This is not spec compliant! When there is no current GL context, functions should
3062 // have no side effects. Google Maps queries these values before creating a context,
3063 // so we need this as a bug-compatible workaround.
3064 switch(pname)
3065 {
3066 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3067 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3068 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3069 case GL_STENCIL_BITS: *params = 8; return;
3070 case GL_ALIASED_LINE_WIDTH_RANGE:
3071 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3072 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3073 return;
3074 }
3075 }
3076
3077 if(context)
3078 {
3079 if(!(context->getIntegerv(pname, params)))
3080 {
3081 GLenum nativeType;
3082 unsigned int numParams = 0;
3083 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3084 return error(GL_INVALID_ENUM);
3085
3086 if(numParams == 0)
3087 return; // it is known that pname is valid, but there are no parameters to return
3088
3089 if(nativeType == GL_BOOL)
3090 {
3091 GLboolean *boolParams = nullptr;
3092 boolParams = new GLboolean[numParams];
3093
3094 context->getBooleanv(pname, boolParams);
3095
3096 for(unsigned int i = 0; i < numParams; ++i)
3097 {
3098 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3099 }
3100
3101 delete [] boolParams;
3102 }
3103 else if(nativeType == GL_FLOAT)
3104 {
3105 GLfloat *floatParams = nullptr;
3106 floatParams = new GLfloat[numParams];
3107
3108 context->getFloatv(pname, floatParams);
3109
3110 for(unsigned int i = 0; i < numParams; ++i)
3111 {
3112 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3113 {
Alexis Hetu60e20282017-12-13 07:42:22 -05003114 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003115 }
3116 else
3117 {
3118 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3119 }
3120 }
3121
3122 delete [] floatParams;
3123 }
3124 }
3125 }
3126}
3127
3128void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3129{
3130 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3131
3132 es2::Context *context = es2::getContext();
3133
3134 if(context)
3135 {
3136 es2::Program *programObject = context->getProgram(program);
3137
3138 if(!programObject)
3139 {
3140 if(context->getShader(program))
3141 {
3142 return error(GL_INVALID_OPERATION);
3143 }
3144 else
3145 {
3146 return error(GL_INVALID_VALUE);
3147 }
3148 }
3149
3150 GLint clientVersion = egl::getClientVersion();
3151
3152 switch(pname)
3153 {
3154 case GL_DELETE_STATUS:
3155 *params = programObject->isFlaggedForDeletion();
3156 return;
3157 case GL_LINK_STATUS:
3158 *params = programObject->isLinked();
3159 return;
3160 case GL_VALIDATE_STATUS:
3161 *params = programObject->isValidated();
3162 return;
3163 case GL_INFO_LOG_LENGTH:
3164 *params = (GLint)programObject->getInfoLogLength();
3165 return;
3166 case GL_ATTACHED_SHADERS:
3167 *params = programObject->getAttachedShadersCount();
3168 return;
3169 case GL_ACTIVE_ATTRIBUTES:
3170 *params = (GLint)programObject->getActiveAttributeCount();
3171 return;
3172 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3173 *params = programObject->getActiveAttributeMaxLength();
3174 return;
3175 case GL_ACTIVE_UNIFORMS:
3176 *params = (GLint)programObject->getActiveUniformCount();
3177 return;
3178 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3179 *params = programObject->getActiveUniformMaxLength();
3180 return;
3181 case GL_ACTIVE_UNIFORM_BLOCKS:
3182 if(clientVersion >= 3)
3183 {
3184 *params = (GLint)programObject->getActiveUniformBlockCount();
3185 return;
3186 }
3187 else return error(GL_INVALID_ENUM);
3188 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3189 if(clientVersion >= 3)
3190 {
3191 *params = programObject->getActiveUniformBlockMaxLength();
3192 return;
3193 }
3194 else return error(GL_INVALID_ENUM);
3195 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3196 if(clientVersion >= 3)
3197 {
3198 *params = programObject->getTransformFeedbackBufferMode();
3199 return;
3200 }
3201 else return error(GL_INVALID_ENUM);
3202 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3203 if(clientVersion >= 3)
3204 {
3205 *params = programObject->getTransformFeedbackVaryingCount();
3206 return;
3207 }
3208 else return error(GL_INVALID_ENUM);
3209 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3210 if(clientVersion >= 3)
3211 {
3212 *params = programObject->getTransformFeedbackVaryingMaxLength();
3213 return;
3214 }
3215 else return error(GL_INVALID_ENUM);
3216 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3217 if(clientVersion >= 3)
3218 {
3219 *params = programObject->getBinaryRetrievableHint();
3220 return;
3221 }
3222 else return error(GL_INVALID_ENUM);
3223 case GL_PROGRAM_BINARY_LENGTH:
3224 if(clientVersion >= 3)
3225 {
3226 *params = programObject->getBinaryLength();
3227 return;
3228 }
3229 else return error(GL_INVALID_ENUM);
3230 default:
3231 return error(GL_INVALID_ENUM);
3232 }
3233 }
3234}
3235
3236void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3237{
3238 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3239 program, bufsize, length, infolog);
3240
3241 if(bufsize < 0)
3242 {
3243 return error(GL_INVALID_VALUE);
3244 }
3245
3246 es2::Context *context = es2::getContext();
3247
3248 if(context)
3249 {
3250 es2::Program *programObject = context->getProgram(program);
3251
3252 if(!programObject)
3253 {
3254 if(context->getShader(program))
3255 {
3256 return error(GL_INVALID_OPERATION);
3257 }
3258 else
3259 {
3260 return error(GL_INVALID_VALUE);
3261 }
3262 }
3263
3264 programObject->getInfoLog(bufsize, length, infolog);
3265 }
3266}
3267
3268void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3269{
3270 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3271
3272 switch(pname)
3273 {
3274 case GL_CURRENT_QUERY_EXT:
3275 break;
3276 default:
3277 return error(GL_INVALID_ENUM);
3278 }
3279
3280 es2::Context *context = es2::getContext();
3281
3282 if(context)
3283 {
3284 params[0] = context->getActiveQuery(target);
3285 }
3286}
3287
3288void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3289{
3290 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3291
3292 switch(pname)
3293 {
3294 case GL_QUERY_RESULT_EXT:
3295 case GL_QUERY_RESULT_AVAILABLE_EXT:
3296 break;
3297 default:
3298 return error(GL_INVALID_ENUM);
3299 }
3300
3301 es2::Context *context = es2::getContext();
3302
3303 if(context)
3304 {
3305 es2::Query *queryObject = context->getQuery(name);
3306
3307 if(!queryObject)
3308 {
3309 return error(GL_INVALID_OPERATION);
3310 }
3311
3312 if(context->getActiveQuery(queryObject->getType()) == name)
3313 {
3314 return error(GL_INVALID_OPERATION);
3315 }
3316
3317 switch(pname)
3318 {
3319 case GL_QUERY_RESULT_EXT:
3320 params[0] = queryObject->getResult();
3321 break;
3322 case GL_QUERY_RESULT_AVAILABLE_EXT:
3323 params[0] = queryObject->isResultAvailable();
3324 break;
3325 default:
3326 ASSERT(false);
3327 }
3328 }
3329}
3330
3331void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3332{
3333 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3334
3335 es2::Context *context = es2::getContext();
3336
3337 if(context)
3338 {
3339 if(target != GL_RENDERBUFFER)
3340 {
3341 return error(GL_INVALID_ENUM);
3342 }
3343
3344 if(context->getRenderbufferName() == 0)
3345 {
3346 return error(GL_INVALID_OPERATION);
3347 }
3348
3349 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3350
3351 switch(pname)
3352 {
3353 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3354 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003355 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3356 {
3357 GLint internalformat = renderbuffer->getFormat();
3358 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3359 }
3360 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003361 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3362 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3363 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3364 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3365 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3366 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003367 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003368 default:
3369 return error(GL_INVALID_ENUM);
3370 }
3371 }
3372}
3373
3374void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3375{
3376 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3377
3378 es2::Context *context = es2::getContext();
3379
3380 if(context)
3381 {
3382 es2::Shader *shaderObject = context->getShader(shader);
3383
3384 if(!shaderObject)
3385 {
3386 if(context->getProgram(shader))
3387 {
3388 return error(GL_INVALID_OPERATION);
3389 }
3390 else
3391 {
3392 return error(GL_INVALID_VALUE);
3393 }
3394 }
3395
3396 switch(pname)
3397 {
3398 case GL_SHADER_TYPE:
3399 *params = shaderObject->getType();
3400 return;
3401 case GL_DELETE_STATUS:
3402 *params = shaderObject->isFlaggedForDeletion();
3403 return;
3404 case GL_COMPILE_STATUS:
3405 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3406 return;
3407 case GL_INFO_LOG_LENGTH:
3408 *params = (GLint)shaderObject->getInfoLogLength();
3409 return;
3410 case GL_SHADER_SOURCE_LENGTH:
3411 *params = (GLint)shaderObject->getSourceLength();
3412 return;
3413 default:
3414 return error(GL_INVALID_ENUM);
3415 }
3416 }
3417}
3418
3419void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3420{
3421 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3422 shader, bufsize, length, infolog);
3423
3424 if(bufsize < 0)
3425 {
3426 return error(GL_INVALID_VALUE);
3427 }
3428
3429 es2::Context *context = es2::getContext();
3430
3431 if(context)
3432 {
3433 es2::Shader *shaderObject = context->getShader(shader);
3434
3435 if(!shaderObject)
3436 {
3437 if(context->getProgram(shader))
3438 {
3439 return error(GL_INVALID_OPERATION);
3440 }
3441 else
3442 {
3443 return error(GL_INVALID_VALUE);
3444 }
3445 }
3446
3447 shaderObject->getInfoLog(bufsize, length, infolog);
3448 }
3449}
3450
3451void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3452{
3453 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3454 shadertype, precisiontype, range, precision);
3455
3456 switch(shadertype)
3457 {
3458 case GL_VERTEX_SHADER:
3459 case GL_FRAGMENT_SHADER:
3460 break;
3461 default:
3462 return error(GL_INVALID_ENUM);
3463 }
3464
3465 switch(precisiontype)
3466 {
3467 case GL_LOW_FLOAT:
3468 case GL_MEDIUM_FLOAT:
3469 case GL_HIGH_FLOAT:
3470 // IEEE 754 single-precision
3471 range[0] = 127;
3472 range[1] = 127;
3473 *precision = 23;
3474 break;
3475 case GL_LOW_INT:
3476 case GL_MEDIUM_INT:
3477 case GL_HIGH_INT:
3478 // Full integer precision is supported
3479 range[0] = 31;
3480 range[1] = 30;
3481 *precision = 0;
3482 break;
3483 default:
3484 return error(GL_INVALID_ENUM);
3485 }
3486}
3487
3488void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3489{
3490 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3491 shader, bufsize, length, source);
3492
3493 if(bufsize < 0)
3494 {
3495 return error(GL_INVALID_VALUE);
3496 }
3497
3498 es2::Context *context = es2::getContext();
3499
3500 if(context)
3501 {
3502 es2::Shader *shaderObject = context->getShader(shader);
3503
3504 if(!shaderObject)
3505 {
3506 if(context->getProgram(shader))
3507 {
3508 return error(GL_INVALID_OPERATION);
3509 }
3510 else
3511 {
3512 return error(GL_INVALID_VALUE);
3513 }
3514 }
3515
3516 shaderObject->getSource(bufsize, length, source);
3517 }
3518}
3519
3520const GLubyte* GetString(GLenum name)
3521{
3522 TRACE("(GLenum name = 0x%X)", name);
3523
3524 switch(name)
3525 {
3526 case GL_VENDOR:
3527 return (GLubyte*)"Google Inc.";
3528 case GL_RENDERER:
3529 return (GLubyte*)"Google SwiftShader";
3530 case GL_VERSION:
3531 {
3532 es2::Context *context = es2::getContext();
3533 return (context && (context->getClientVersion() >= 3)) ?
3534 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3535 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3536 }
3537 case GL_SHADING_LANGUAGE_VERSION:
3538 {
3539 es2::Context *context = es2::getContext();
3540 return (context && (context->getClientVersion() >= 3)) ?
3541 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3542 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3543 }
3544 case GL_EXTENSIONS:
3545 {
3546 es2::Context *context = es2::getContext();
3547 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3548 }
3549 default:
3550 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3551 }
3552}
3553
3554void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3555{
3556 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3557
3558 es2::Context *context = es2::getContext();
3559
3560 if(context)
3561 {
3562 es2::Texture *texture;
3563
3564 GLint clientVersion = context->getClientVersion();
3565
3566 switch(target)
3567 {
3568 case GL_TEXTURE_2D:
3569 texture = context->getTexture2D();
3570 break;
3571 case GL_TEXTURE_CUBE_MAP:
3572 texture = context->getTextureCubeMap();
3573 break;
3574 case GL_TEXTURE_EXTERNAL_OES:
3575 texture = context->getTextureExternal();
3576 break;
3577 case GL_TEXTURE_2D_ARRAY:
3578 if(clientVersion < 3)
3579 {
3580 return error(GL_INVALID_ENUM);
3581 }
3582 else
3583 {
3584 texture = context->getTexture2DArray();
3585 }
3586 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003587 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003588 texture = context->getTexture3D();
3589 break;
3590 default:
3591 return error(GL_INVALID_ENUM);
3592 }
3593
3594 switch(pname)
3595 {
3596 case GL_TEXTURE_MAG_FILTER:
3597 *params = (GLfloat)texture->getMagFilter();
3598 break;
3599 case GL_TEXTURE_MIN_FILTER:
3600 *params = (GLfloat)texture->getMinFilter();
3601 break;
3602 case GL_TEXTURE_WRAP_S:
3603 *params = (GLfloat)texture->getWrapS();
3604 break;
3605 case GL_TEXTURE_WRAP_T:
3606 *params = (GLfloat)texture->getWrapT();
3607 break;
3608 case GL_TEXTURE_WRAP_R_OES:
3609 *params = (GLfloat)texture->getWrapR();
3610 break;
3611 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3612 *params = texture->getMaxAnisotropy();
3613 break;
3614 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3615 *params = (GLfloat)1;
3616 break;
3617 case GL_TEXTURE_BASE_LEVEL:
3618 if(clientVersion >= 3)
3619 {
3620 *params = (GLfloat)texture->getBaseLevel();
3621 break;
3622 }
3623 else return error(GL_INVALID_ENUM);
3624 case GL_TEXTURE_COMPARE_FUNC:
3625 if(clientVersion >= 3)
3626 {
3627 *params = (GLfloat)texture->getCompareFunc();
3628 break;
3629 }
3630 else return error(GL_INVALID_ENUM);
3631 case GL_TEXTURE_COMPARE_MODE:
3632 if(clientVersion >= 3)
3633 {
3634 *params = (GLfloat)texture->getCompareMode();
3635 break;
3636 }
3637 else return error(GL_INVALID_ENUM);
3638 case GL_TEXTURE_IMMUTABLE_FORMAT:
3639 if(clientVersion >= 3)
3640 {
3641 *params = (GLfloat)texture->getImmutableFormat();
3642 break;
3643 }
3644 else return error(GL_INVALID_ENUM);
3645 case GL_TEXTURE_IMMUTABLE_LEVELS:
3646 if(clientVersion >= 3)
3647 {
3648 *params = (GLfloat)texture->getImmutableLevels();
3649 break;
3650 }
3651 else return error(GL_INVALID_ENUM);
3652 case GL_TEXTURE_MAX_LEVEL:
3653 if(clientVersion >= 3)
3654 {
3655 *params = (GLfloat)texture->getMaxLevel();
3656 break;
3657 }
3658 else return error(GL_INVALID_ENUM);
3659 case GL_TEXTURE_MAX_LOD:
3660 if(clientVersion >= 3)
3661 {
3662 *params = texture->getMaxLOD();
3663 break;
3664 }
3665 else return error(GL_INVALID_ENUM);
3666 case GL_TEXTURE_MIN_LOD:
3667 if(clientVersion >= 3)
3668 {
3669 *params = texture->getMinLOD();
3670 break;
3671 }
3672 else return error(GL_INVALID_ENUM);
3673 case GL_TEXTURE_SWIZZLE_R:
3674 if(clientVersion >= 3)
3675 {
3676 *params = (GLfloat)texture->getSwizzleR();
3677 break;
3678 }
3679 else return error(GL_INVALID_ENUM);
3680 case GL_TEXTURE_SWIZZLE_G:
3681 if(clientVersion >= 3)
3682 {
3683 *params = (GLfloat)texture->getSwizzleG();
3684 break;
3685 }
3686 else return error(GL_INVALID_ENUM);
3687 case GL_TEXTURE_SWIZZLE_B:
3688 if(clientVersion >= 3)
3689 {
3690 *params = (GLfloat)texture->getSwizzleB();
3691 break;
3692 }
3693 else return error(GL_INVALID_ENUM);
3694 case GL_TEXTURE_SWIZZLE_A:
3695 if(clientVersion >= 3)
3696 {
3697 *params = (GLfloat)texture->getSwizzleA();
3698 break;
3699 }
3700 else return error(GL_INVALID_ENUM);
3701 default:
3702 return error(GL_INVALID_ENUM);
3703 }
3704 }
3705}
3706
3707void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3708{
3709 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3710
3711 es2::Context *context = es2::getContext();
3712
3713 if(context)
3714 {
3715 es2::Texture *texture;
3716
3717 GLint clientVersion = context->getClientVersion();
3718
3719 switch(target)
3720 {
3721 case GL_TEXTURE_2D:
3722 texture = context->getTexture2D();
3723 break;
3724 case GL_TEXTURE_CUBE_MAP:
3725 texture = context->getTextureCubeMap();
3726 break;
3727 case GL_TEXTURE_EXTERNAL_OES:
3728 texture = context->getTextureExternal();
3729 break;
3730 case GL_TEXTURE_2D_ARRAY:
3731 if(clientVersion < 3)
3732 {
3733 return error(GL_INVALID_ENUM);
3734 }
3735 else
3736 {
3737 texture = context->getTexture2DArray();
3738 }
3739 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003740 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003741 texture = context->getTexture3D();
3742 break;
3743 default:
3744 return error(GL_INVALID_ENUM);
3745 }
3746
3747 switch(pname)
3748 {
3749 case GL_TEXTURE_MAG_FILTER:
3750 *params = texture->getMagFilter();
3751 break;
3752 case GL_TEXTURE_MIN_FILTER:
3753 *params = texture->getMinFilter();
3754 break;
3755 case GL_TEXTURE_WRAP_S:
3756 *params = texture->getWrapS();
3757 break;
3758 case GL_TEXTURE_WRAP_T:
3759 *params = texture->getWrapT();
3760 break;
3761 case GL_TEXTURE_WRAP_R_OES:
3762 *params = texture->getWrapR();
3763 break;
3764 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3765 *params = (GLint)texture->getMaxAnisotropy();
3766 break;
3767 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3768 *params = 1;
3769 break;
3770 case GL_TEXTURE_BASE_LEVEL:
3771 if(clientVersion >= 3)
3772 {
3773 *params = texture->getBaseLevel();
3774 break;
3775 }
3776 else return error(GL_INVALID_ENUM);
3777 case GL_TEXTURE_COMPARE_FUNC:
3778 if(clientVersion >= 3)
3779 {
3780 *params = (GLint)texture->getCompareFunc();
3781 break;
3782 }
3783 else return error(GL_INVALID_ENUM);
3784 case GL_TEXTURE_COMPARE_MODE:
3785 if(clientVersion >= 3)
3786 {
3787 *params = (GLint)texture->getCompareMode();
3788 break;
3789 }
3790 else return error(GL_INVALID_ENUM);
3791 case GL_TEXTURE_IMMUTABLE_FORMAT:
3792 if(clientVersion >= 3)
3793 {
3794 *params = (GLint)texture->getImmutableFormat();
3795 break;
3796 }
3797 else return error(GL_INVALID_ENUM);
3798 case GL_TEXTURE_IMMUTABLE_LEVELS:
3799 if(clientVersion >= 3)
3800 {
3801 *params = (GLint)texture->getImmutableLevels();
3802 break;
3803 }
3804 else return error(GL_INVALID_ENUM);
3805 case GL_TEXTURE_MAX_LEVEL:
3806 if(clientVersion >= 3)
3807 {
3808 *params = texture->getMaxLevel();
3809 break;
3810 }
3811 else return error(GL_INVALID_ENUM);
3812 case GL_TEXTURE_MAX_LOD:
3813 if(clientVersion >= 3)
3814 {
3815 *params = (GLint)roundf(texture->getMaxLOD());
3816 break;
3817 }
3818 else return error(GL_INVALID_ENUM);
3819 case GL_TEXTURE_MIN_LOD:
3820 if(clientVersion >= 3)
3821 {
3822 *params = (GLint)roundf(texture->getMinLOD());
3823 break;
3824 }
3825 else return error(GL_INVALID_ENUM);
3826 case GL_TEXTURE_SWIZZLE_R:
3827 if(clientVersion >= 3)
3828 {
3829 *params = (GLint)texture->getSwizzleR();
3830 break;
3831 }
3832 else return error(GL_INVALID_ENUM);
3833 case GL_TEXTURE_SWIZZLE_G:
3834 if(clientVersion >= 3)
3835 {
3836 *params = (GLint)texture->getSwizzleG();
3837 break;
3838 }
3839 else return error(GL_INVALID_ENUM);
3840 case GL_TEXTURE_SWIZZLE_B:
3841 if(clientVersion >= 3)
3842 {
3843 *params = (GLint)texture->getSwizzleB();
3844 break;
3845 }
3846 else return error(GL_INVALID_ENUM);
3847 case GL_TEXTURE_SWIZZLE_A:
3848 if(clientVersion >= 3)
3849 {
3850 *params = (GLint)texture->getSwizzleA();
3851 break;
3852 }
3853 else return error(GL_INVALID_ENUM);
3854 default:
3855 return error(GL_INVALID_ENUM);
3856 }
3857 }
3858}
3859
3860void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3861{
3862 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3863 program, location, bufSize, params);
3864
3865 if(bufSize < 0)
3866 {
3867 return error(GL_INVALID_VALUE);
3868 }
3869
3870 es2::Context *context = es2::getContext();
3871
3872 if(context)
3873 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003874 es2::Program *programObject = context->getProgram(program);
3875
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003876 if(!programObject)
3877 {
3878 if(context->getShader(program))
3879 {
3880 return error(GL_INVALID_OPERATION);
3881 }
3882 else
3883 {
3884 return error(GL_INVALID_VALUE);
3885 }
3886 }
3887
3888 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003889 {
3890 return error(GL_INVALID_OPERATION);
3891 }
3892
3893 if(!programObject->getUniformfv(location, &bufSize, params))
3894 {
3895 return error(GL_INVALID_OPERATION);
3896 }
3897 }
3898}
3899
3900void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3901{
3902 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3903
3904 es2::Context *context = es2::getContext();
3905
3906 if(context)
3907 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003908 es2::Program *programObject = context->getProgram(program);
3909
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003910 if(!programObject)
3911 {
3912 if(context->getShader(program))
3913 {
3914 return error(GL_INVALID_OPERATION);
3915 }
3916 else
3917 {
3918 return error(GL_INVALID_VALUE);
3919 }
3920 }
3921
3922 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003923 {
3924 return error(GL_INVALID_OPERATION);
3925 }
3926
3927 if(!programObject->getUniformfv(location, nullptr, params))
3928 {
3929 return error(GL_INVALID_OPERATION);
3930 }
3931 }
3932}
3933
3934void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3935{
3936 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3937 program, location, bufSize, params);
3938
3939 if(bufSize < 0)
3940 {
3941 return error(GL_INVALID_VALUE);
3942 }
3943
3944 es2::Context *context = es2::getContext();
3945
3946 if(context)
3947 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003948 es2::Program *programObject = context->getProgram(program);
3949
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003950 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003951 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003952 if(context->getShader(program))
3953 {
3954 return error(GL_INVALID_OPERATION);
3955 }
3956 else
3957 {
3958 return error(GL_INVALID_VALUE);
3959 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003960 }
3961
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003962 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003963 {
3964 return error(GL_INVALID_OPERATION);
3965 }
3966
3967 if(!programObject->getUniformiv(location, &bufSize, params))
3968 {
3969 return error(GL_INVALID_OPERATION);
3970 }
3971 }
3972}
3973
3974void GetUniformiv(GLuint program, GLint location, GLint* params)
3975{
3976 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3977
3978 es2::Context *context = es2::getContext();
3979
3980 if(context)
3981 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003982 es2::Program *programObject = context->getProgram(program);
3983
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003984 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003985 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003986 if(context->getShader(program))
3987 {
3988 return error(GL_INVALID_OPERATION);
3989 }
3990 else
3991 {
3992 return error(GL_INVALID_VALUE);
3993 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003994 }
3995
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003996 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003997 {
3998 return error(GL_INVALID_OPERATION);
3999 }
4000
4001 if(!programObject->getUniformiv(location, nullptr, params))
4002 {
4003 return error(GL_INVALID_OPERATION);
4004 }
4005 }
4006}
4007
4008int GetUniformLocation(GLuint program, const GLchar* name)
4009{
4010 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
4011
4012 es2::Context *context = es2::getContext();
4013
4014 if(strstr(name, "gl_") == name)
4015 {
4016 return -1;
4017 }
4018
4019 if(context)
4020 {
4021 es2::Program *programObject = context->getProgram(program);
4022
4023 if(!programObject)
4024 {
4025 if(context->getShader(program))
4026 {
4027 return error(GL_INVALID_OPERATION, -1);
4028 }
4029 else
4030 {
4031 return error(GL_INVALID_VALUE, -1);
4032 }
4033 }
4034
4035 if(!programObject->isLinked())
4036 {
4037 return error(GL_INVALID_OPERATION, -1);
4038 }
4039
4040 return programObject->getUniformLocation(name);
4041 }
4042
4043 return -1;
4044}
4045
4046void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
4047{
4048 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
4049
4050 es2::Context *context = es2::getContext();
4051
4052 if(context)
4053 {
4054 if(index >= es2::MAX_VERTEX_ATTRIBS)
4055 {
4056 return error(GL_INVALID_VALUE);
4057 }
4058
4059 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4060
4061 GLint clientVersion = context->getClientVersion();
4062
4063 switch(pname)
4064 {
4065 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4066 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4067 break;
4068 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4069 *params = (GLfloat)attribState.mSize;
4070 break;
4071 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4072 *params = (GLfloat)attribState.mStride;
4073 break;
4074 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4075 *params = (GLfloat)attribState.mType;
4076 break;
4077 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4078 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4079 break;
4080 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4081 *params = (GLfloat)attribState.mBoundBuffer.name();
4082 break;
4083 case GL_CURRENT_VERTEX_ATTRIB:
4084 {
4085 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4086 for(int i = 0; i < 4; ++i)
4087 {
4088 params[i] = attrib.getCurrentValueF(i);
4089 }
4090 }
4091 break;
4092 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4093 if(clientVersion >= 3)
4094 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004095 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004096 break;
4097 }
4098 else return error(GL_INVALID_ENUM);
4099 default: return error(GL_INVALID_ENUM);
4100 }
4101 }
4102}
4103
4104void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4105{
4106 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4107
4108 es2::Context *context = es2::getContext();
4109
4110 if(context)
4111 {
4112 if(index >= es2::MAX_VERTEX_ATTRIBS)
4113 {
4114 return error(GL_INVALID_VALUE);
4115 }
4116
4117 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4118
4119 GLint clientVersion = context->getClientVersion();
4120
4121 switch(pname)
4122 {
4123 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4124 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4125 break;
4126 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4127 *params = attribState.mSize;
4128 break;
4129 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4130 *params = attribState.mStride;
4131 break;
4132 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4133 *params = attribState.mType;
4134 break;
4135 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4136 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4137 break;
4138 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4139 *params = attribState.mBoundBuffer.name();
4140 break;
4141 case GL_CURRENT_VERTEX_ATTRIB:
4142 {
4143 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4144 for(int i = 0; i < 4; ++i)
4145 {
4146 float currentValue = attrib.getCurrentValueF(i);
4147 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4148 }
4149 }
4150 break;
4151 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4152 if(clientVersion >= 3)
4153 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004154 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004155 break;
4156 }
4157 else return error(GL_INVALID_ENUM);
4158 default: return error(GL_INVALID_ENUM);
4159 }
4160 }
4161}
4162
4163void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4164{
4165 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4166
4167 es2::Context *context = es2::getContext();
4168
4169 if(context)
4170 {
4171 if(index >= es2::MAX_VERTEX_ATTRIBS)
4172 {
4173 return error(GL_INVALID_VALUE);
4174 }
4175
4176 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4177 {
4178 return error(GL_INVALID_ENUM);
4179 }
4180
4181 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4182 }
4183}
4184
4185void Hint(GLenum target, GLenum mode)
4186{
4187 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4188
4189 switch(mode)
4190 {
4191 case GL_FASTEST:
4192 case GL_NICEST:
4193 case GL_DONT_CARE:
4194 break;
4195 default:
4196 return error(GL_INVALID_ENUM);
4197 }
4198
4199 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004200
4201 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004202 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004203 switch(target)
4204 {
4205 case GL_GENERATE_MIPMAP_HINT:
4206 context->setGenerateMipmapHint(mode);
4207 break;
4208 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4209 context->setFragmentShaderDerivativeHint(mode);
4210 break;
4211 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4212 context->setTextureFilteringHint(mode);
4213 break;
4214 default:
4215 return error(GL_INVALID_ENUM);
4216 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004217 }
4218}
4219
4220GLboolean IsBuffer(GLuint buffer)
4221{
4222 TRACE("(GLuint buffer = %d)", buffer);
4223
4224 es2::Context *context = es2::getContext();
4225
4226 if(context && buffer)
4227 {
4228 es2::Buffer *bufferObject = context->getBuffer(buffer);
4229
4230 if(bufferObject)
4231 {
4232 return GL_TRUE;
4233 }
4234 }
4235
4236 return GL_FALSE;
4237}
4238
4239GLboolean IsEnabled(GLenum cap)
4240{
4241 TRACE("(GLenum cap = 0x%X)", cap);
4242
4243 es2::Context *context = es2::getContext();
4244
4245 if(context)
4246 {
4247 GLint clientVersion = context->getClientVersion();
4248
4249 switch(cap)
4250 {
4251 case GL_CULL_FACE: return context->isCullFaceEnabled();
4252 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4253 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4254 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4255 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4256 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4257 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4258 case GL_BLEND: return context->isBlendEnabled();
4259 case GL_DITHER: return context->isDitherEnabled();
4260 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4261 if(clientVersion >= 3)
4262 {
4263 return context->isPrimitiveRestartFixedIndexEnabled();
4264 }
4265 else return error(GL_INVALID_ENUM, false);
4266 case GL_RASTERIZER_DISCARD:
4267 if(clientVersion >= 3)
4268 {
4269 return context->isRasterizerDiscardEnabled();
4270 }
4271 else return error(GL_INVALID_ENUM, false);
4272 default:
4273 return error(GL_INVALID_ENUM, false);
4274 }
4275 }
4276
4277 return false;
4278}
4279
4280GLboolean IsFenceNV(GLuint fence)
4281{
4282 TRACE("(GLuint fence = %d)", fence);
4283
4284 es2::Context *context = es2::getContext();
4285
4286 if(context)
4287 {
4288 es2::Fence *fenceObject = context->getFence(fence);
4289
4290 if(!fenceObject)
4291 {
4292 return GL_FALSE;
4293 }
4294
4295 return fenceObject->isFence();
4296 }
4297
4298 return GL_FALSE;
4299}
4300
4301GLboolean IsFramebuffer(GLuint framebuffer)
4302{
4303 TRACE("(GLuint framebuffer = %d)", framebuffer);
4304
4305 es2::Context *context = es2::getContext();
4306
4307 if(context && framebuffer)
4308 {
4309 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4310
4311 if(framebufferObject)
4312 {
4313 return GL_TRUE;
4314 }
4315 }
4316
4317 return GL_FALSE;
4318}
4319
4320GLboolean IsProgram(GLuint program)
4321{
4322 TRACE("(GLuint program = %d)", program);
4323
4324 es2::Context *context = es2::getContext();
4325
4326 if(context && program)
4327 {
4328 es2::Program *programObject = context->getProgram(program);
4329
4330 if(programObject)
4331 {
4332 return GL_TRUE;
4333 }
4334 }
4335
4336 return GL_FALSE;
4337}
4338
4339GLboolean IsQueryEXT(GLuint name)
4340{
4341 TRACE("(GLuint name = %d)", name);
4342
4343 if(name == 0)
4344 {
4345 return GL_FALSE;
4346 }
4347
4348 es2::Context *context = es2::getContext();
4349
4350 if(context)
4351 {
4352 es2::Query *queryObject = context->getQuery(name);
4353
4354 if(queryObject)
4355 {
4356 return GL_TRUE;
4357 }
4358 }
4359
4360 return GL_FALSE;
4361}
4362
4363GLboolean IsRenderbuffer(GLuint renderbuffer)
4364{
4365 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4366
4367 es2::Context *context = es2::getContext();
4368
4369 if(context && renderbuffer)
4370 {
4371 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4372
4373 if(renderbufferObject)
4374 {
4375 return GL_TRUE;
4376 }
4377 }
4378
4379 return GL_FALSE;
4380}
4381
4382GLboolean IsShader(GLuint shader)
4383{
4384 TRACE("(GLuint shader = %d)", shader);
4385
4386 es2::Context *context = es2::getContext();
4387
4388 if(context && shader)
4389 {
4390 es2::Shader *shaderObject = context->getShader(shader);
4391
4392 if(shaderObject)
4393 {
4394 return GL_TRUE;
4395 }
4396 }
4397
4398 return GL_FALSE;
4399}
4400
4401GLboolean IsTexture(GLuint texture)
4402{
4403 TRACE("(GLuint texture = %d)", texture);
4404
4405 es2::Context *context = es2::getContext();
4406
4407 if(context && texture)
4408 {
4409 es2::Texture *textureObject = context->getTexture(texture);
4410
4411 if(textureObject)
4412 {
4413 return GL_TRUE;
4414 }
4415 }
4416
4417 return GL_FALSE;
4418}
4419
4420void LineWidth(GLfloat width)
4421{
4422 TRACE("(GLfloat width = %f)", width);
4423
4424 if(width <= 0.0f)
4425 {
4426 return error(GL_INVALID_VALUE);
4427 }
4428
4429 es2::Context *context = es2::getContext();
4430
4431 if(context)
4432 {
4433 context->setLineWidth(width);
4434 }
4435}
4436
4437void LinkProgram(GLuint program)
4438{
4439 TRACE("(GLuint program = %d)", program);
4440
4441 es2::Context *context = es2::getContext();
4442
4443 if(context)
4444 {
4445 es2::Program *programObject = context->getProgram(program);
4446
4447 if(!programObject)
4448 {
4449 if(context->getShader(program))
4450 {
4451 return error(GL_INVALID_OPERATION);
4452 }
4453 else
4454 {
4455 return error(GL_INVALID_VALUE);
4456 }
4457 }
4458
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004459 if(programObject == context->getCurrentProgram())
4460 {
4461 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4462 if(transformFeedback && transformFeedback->isActive())
4463 {
4464 return error(GL_INVALID_OPERATION);
4465 }
4466 }
4467
Nicolas Capens0bac2852016-05-07 06:09:58 -04004468 programObject->link();
4469 }
4470}
4471
4472void PixelStorei(GLenum pname, GLint param)
4473{
4474 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4475
4476 es2::Context *context = es2::getContext();
4477
4478 if(context)
4479 {
4480 GLint clientVersion = context->getClientVersion();
4481
4482 switch(pname)
4483 {
4484 case GL_UNPACK_ALIGNMENT:
4485 if(param != 1 && param != 2 && param != 4 && param != 8)
4486 {
4487 return error(GL_INVALID_VALUE);
4488 }
4489 context->setUnpackAlignment(param);
4490 break;
4491 case GL_PACK_ALIGNMENT:
4492 if(param != 1 && param != 2 && param != 4 && param != 8)
4493 {
4494 return error(GL_INVALID_VALUE);
4495 }
4496 context->setPackAlignment(param);
4497 break;
4498 case GL_PACK_ROW_LENGTH:
4499 if(clientVersion >= 3)
4500 {
4501 if(param < 0)
4502 {
4503 return error(GL_INVALID_VALUE);
4504 }
4505 context->setPackRowLength(param);
4506 break;
4507 }
4508 else return error(GL_INVALID_ENUM);
4509 case GL_PACK_SKIP_PIXELS:
4510 if(clientVersion >= 3)
4511 {
4512 if(param < 0)
4513 {
4514 return error(GL_INVALID_VALUE);
4515 }
4516 context->setPackSkipPixels(param);
4517 break;
4518 }
4519 else return error(GL_INVALID_ENUM);
4520 case GL_PACK_SKIP_ROWS:
4521 if(clientVersion >= 3)
4522 {
4523 if(param < 0)
4524 {
4525 return error(GL_INVALID_VALUE);
4526 }
4527 context->setPackSkipRows(param);
4528 break;
4529 }
4530 else return error(GL_INVALID_ENUM);
4531 case GL_UNPACK_ROW_LENGTH:
4532 if(clientVersion >= 3)
4533 {
4534 if(param < 0)
4535 {
4536 return error(GL_INVALID_VALUE);
4537 }
4538 context->setUnpackRowLength(param);
4539 break;
4540 }
4541 else return error(GL_INVALID_ENUM);
4542 case GL_UNPACK_IMAGE_HEIGHT:
4543 if(clientVersion >= 3)
4544 {
4545 if(param < 0)
4546 {
4547 return error(GL_INVALID_VALUE);
4548 }
4549 context->setUnpackImageHeight(param);
4550 break;
4551 }
4552 else return error(GL_INVALID_ENUM);
4553 case GL_UNPACK_SKIP_PIXELS:
4554 if(clientVersion >= 3)
4555 {
4556 if(param < 0)
4557 {
4558 return error(GL_INVALID_VALUE);
4559 }
4560 context->setUnpackSkipPixels(param);
4561 break;
4562 }
4563 else return error(GL_INVALID_ENUM);
4564 case GL_UNPACK_SKIP_ROWS:
4565 if(clientVersion >= 3)
4566 {
4567 if(param < 0)
4568 {
4569 return error(GL_INVALID_VALUE);
4570 }
4571 context->setUnpackSkipRows(param);
4572 break;
4573 }
4574 else return error(GL_INVALID_ENUM);
4575 case GL_UNPACK_SKIP_IMAGES:
4576 if(clientVersion >= 3) {
4577 if(param < 0)
4578 {
4579 return error(GL_INVALID_VALUE);
4580 }
4581 context->setUnpackSkipImages(param);
4582 break;
4583 }
4584 else return error(GL_INVALID_ENUM);
4585 default:
4586 return error(GL_INVALID_ENUM);
4587 }
4588 }
4589}
4590
4591void PolygonOffset(GLfloat factor, GLfloat units)
4592{
4593 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4594
4595 es2::Context *context = es2::getContext();
4596
4597 if(context)
4598 {
4599 context->setPolygonOffsetParams(factor, units);
4600 }
4601}
4602
4603void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4604 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4605{
4606 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4607 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4608 x, y, width, height, format, type, bufSize, data);
4609
4610 if(width < 0 || height < 0 || bufSize < 0)
4611 {
4612 return error(GL_INVALID_VALUE);
4613 }
4614
4615 es2::Context *context = es2::getContext();
4616
4617 if(context)
4618 {
4619 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4620 }
4621}
4622
4623void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4624{
4625 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4626 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4627 x, y, width, height, format, type, pixels);
4628
4629 if(width < 0 || height < 0)
4630 {
4631 return error(GL_INVALID_VALUE);
4632 }
4633
4634 es2::Context *context = es2::getContext();
4635
4636 if(context)
4637 {
4638 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4639 }
4640}
4641
4642void ReleaseShaderCompiler(void)
4643{
4644 TRACE("()");
4645
4646 es2::Shader::releaseCompiler();
4647}
4648
Nicolas Capens400667e2017-03-29 14:40:14 -04004649void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004650{
4651 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4652 target, samples, internalformat, width, height);
4653
4654 switch(target)
4655 {
4656 case GL_RENDERBUFFER:
4657 break;
4658 default:
4659 return error(GL_INVALID_ENUM);
4660 }
4661
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004662 if(width < 0 || height < 0 || samples < 0 ||
4663 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4664 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004665 {
4666 return error(GL_INVALID_VALUE);
4667 }
4668
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004669 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004670 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004671 {
4672 return error(GL_INVALID_OPERATION);
4673 }
4674
Nicolas Capens0bac2852016-05-07 06:09:58 -04004675 es2::Context *context = es2::getContext();
4676
4677 if(context)
4678 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004679 GLuint handle = context->getRenderbufferName();
4680 if(handle == 0)
4681 {
4682 return error(GL_INVALID_OPERATION);
4683 }
4684
4685 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004686
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004687 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004688 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004689 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004690 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004691 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4692 {
4693 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4694 }
4695 else if(IsDepthRenderable(internalformat, clientVersion))
4696 {
4697 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4698 }
4699 else if(IsStencilRenderable(internalformat, clientVersion))
4700 {
4701 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4702 }
4703 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004704 }
4705}
4706
Nicolas Capens400667e2017-03-29 14:40:14 -04004707void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4708{
4709 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4710}
4711
Nicolas Capens0bac2852016-05-07 06:09:58 -04004712void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4713{
Nicolas Capens400667e2017-03-29 14:40:14 -04004714 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004715}
4716
4717void SampleCoverage(GLclampf value, GLboolean invert)
4718{
4719 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4720
4721 es2::Context* context = es2::getContext();
4722
4723 if(context)
4724 {
4725 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4726 }
4727}
4728
4729void SetFenceNV(GLuint fence, GLenum condition)
4730{
4731 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4732
4733 if(condition != GL_ALL_COMPLETED_NV)
4734 {
4735 return error(GL_INVALID_ENUM);
4736 }
4737
4738 es2::Context *context = es2::getContext();
4739
4740 if(context)
4741 {
4742 es2::Fence *fenceObject = context->getFence(fence);
4743
4744 if(!fenceObject)
4745 {
4746 return error(GL_INVALID_OPERATION);
4747 }
4748
4749 fenceObject->setFence(condition);
4750 }
4751}
4752
4753void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4754{
4755 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4756
4757 if(width < 0 || height < 0)
4758 {
4759 return error(GL_INVALID_VALUE);
4760 }
4761
4762 es2::Context* context = es2::getContext();
4763
4764 if(context)
4765 {
4766 context->setScissorParams(x, y, width, height);
4767 }
4768}
4769
4770void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4771{
4772 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4773 "const GLvoid* binary = %p, GLsizei length = %d)",
4774 n, shaders, binaryformat, binary, length);
4775
4776 // No binary shader formats are supported.
4777 return error(GL_INVALID_ENUM);
4778}
4779
4780void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4781{
4782 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4783 shader, count, string, length);
4784
4785 if(count < 0)
4786 {
4787 return error(GL_INVALID_VALUE);
4788 }
4789
4790 es2::Context *context = es2::getContext();
4791
4792 if(context)
4793 {
4794 es2::Shader *shaderObject = context->getShader(shader);
4795
4796 if(!shaderObject)
4797 {
4798 if(context->getProgram(shader))
4799 {
4800 return error(GL_INVALID_OPERATION);
4801 }
4802 else
4803 {
4804 return error(GL_INVALID_VALUE);
4805 }
4806 }
4807
4808 shaderObject->setSource(count, string, length);
4809 }
4810}
4811
4812void StencilFunc(GLenum func, GLint ref, GLuint mask)
4813{
4814 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4815}
4816
4817void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4818{
4819 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4820
4821 switch(face)
4822 {
4823 case GL_FRONT:
4824 case GL_BACK:
4825 case GL_FRONT_AND_BACK:
4826 break;
4827 default:
4828 return error(GL_INVALID_ENUM);
4829 }
4830
4831 switch(func)
4832 {
4833 case GL_NEVER:
4834 case GL_ALWAYS:
4835 case GL_LESS:
4836 case GL_LEQUAL:
4837 case GL_EQUAL:
4838 case GL_GEQUAL:
4839 case GL_GREATER:
4840 case GL_NOTEQUAL:
4841 break;
4842 default:
4843 return error(GL_INVALID_ENUM);
4844 }
4845
4846 es2::Context *context = es2::getContext();
4847
4848 if(context)
4849 {
4850 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4851 {
4852 context->setStencilParams(func, ref, mask);
4853 }
4854
4855 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4856 {
4857 context->setStencilBackParams(func, ref, mask);
4858 }
4859 }
4860}
4861
4862void StencilMask(GLuint mask)
4863{
4864 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4865}
4866
4867void StencilMaskSeparate(GLenum face, GLuint mask)
4868{
4869 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4870
4871 switch(face)
4872 {
4873 case GL_FRONT:
4874 case GL_BACK:
4875 case GL_FRONT_AND_BACK:
4876 break;
4877 default:
4878 return error(GL_INVALID_ENUM);
4879 }
4880
4881 es2::Context *context = es2::getContext();
4882
4883 if(context)
4884 {
4885 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4886 {
4887 context->setStencilWritemask(mask);
4888 }
4889
4890 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4891 {
4892 context->setStencilBackWritemask(mask);
4893 }
4894 }
4895}
4896
4897void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4898{
4899 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4900}
4901
4902void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4903{
4904 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4905 face, fail, zfail, zpass);
4906
4907 switch(face)
4908 {
4909 case GL_FRONT:
4910 case GL_BACK:
4911 case GL_FRONT_AND_BACK:
4912 break;
4913 default:
4914 return error(GL_INVALID_ENUM);
4915 }
4916
4917 switch(fail)
4918 {
4919 case GL_ZERO:
4920 case GL_KEEP:
4921 case GL_REPLACE:
4922 case GL_INCR:
4923 case GL_DECR:
4924 case GL_INVERT:
4925 case GL_INCR_WRAP:
4926 case GL_DECR_WRAP:
4927 break;
4928 default:
4929 return error(GL_INVALID_ENUM);
4930 }
4931
4932 switch(zfail)
4933 {
4934 case GL_ZERO:
4935 case GL_KEEP:
4936 case GL_REPLACE:
4937 case GL_INCR:
4938 case GL_DECR:
4939 case GL_INVERT:
4940 case GL_INCR_WRAP:
4941 case GL_DECR_WRAP:
4942 break;
4943 default:
4944 return error(GL_INVALID_ENUM);
4945 }
4946
4947 switch(zpass)
4948 {
4949 case GL_ZERO:
4950 case GL_KEEP:
4951 case GL_REPLACE:
4952 case GL_INCR:
4953 case GL_DECR:
4954 case GL_INVERT:
4955 case GL_INCR_WRAP:
4956 case GL_DECR_WRAP:
4957 break;
4958 default:
4959 return error(GL_INVALID_ENUM);
4960 }
4961
4962 es2::Context *context = es2::getContext();
4963
4964 if(context)
4965 {
4966 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4967 {
4968 context->setStencilOperations(fail, zfail, zpass);
4969 }
4970
4971 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4972 {
4973 context->setStencilBackOperations(fail, zfail, zpass);
4974 }
4975 }
4976}
4977
4978GLboolean TestFenceNV(GLuint fence)
4979{
4980 TRACE("(GLuint fence = %d)", fence);
4981
4982 es2::Context *context = es2::getContext();
4983
4984 if(context)
4985 {
4986 es2::Fence *fenceObject = context->getFence(fence);
4987
4988 if(!fenceObject)
4989 {
4990 return error(GL_INVALID_OPERATION, GL_TRUE);
4991 }
4992
4993 return fenceObject->testFence();
4994 }
4995
4996 return GL_TRUE;
4997}
4998
4999void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005000 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005001{
5002 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005003 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
5004 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005005
5006 if(!validImageSize(level, width, height))
5007 {
5008 return error(GL_INVALID_VALUE);
5009 }
5010
5011 es2::Context *context = es2::getContext();
5012
5013 if(context)
5014 {
5015 GLint clientVersion = context->getClientVersion();
5016 if(clientVersion < 3)
5017 {
5018 if(internalformat != (GLint)format)
5019 {
5020 return error(GL_INVALID_OPERATION);
5021 }
5022 }
5023
5024 GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
5025 if(validationError != GL_NONE)
5026 {
5027 return error(validationError);
5028 }
5029
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005030 validationError = ValidateTextureFormatType(format, type, internalformat, context->getClientVersion());
5031 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005032 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005033 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005034 }
5035
5036 if(border != 0)
5037 {
5038 return error(GL_INVALID_VALUE);
5039 }
5040
5041 switch(target)
5042 {
5043 case GL_TEXTURE_2D:
5044 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5045 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5046 {
5047 return error(GL_INVALID_VALUE);
5048 }
5049 break;
5050 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5051 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5052 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5053 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5054 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5055 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5056 if(width != height)
5057 {
5058 return error(GL_INVALID_VALUE);
5059 }
5060
5061 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5062 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5063 {
5064 return error(GL_INVALID_VALUE);
5065 }
5066 break;
5067 default:
5068 return error(GL_INVALID_ENUM);
5069 }
5070
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005071 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005072
Nicolas Capens5555af42017-12-14 13:14:03 -05005073 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005074 if(validationError != GL_NONE)
5075 {
5076 return error(validationError);
5077 }
5078
Nicolas Capens0bac2852016-05-07 06:09:58 -04005079 if(target == GL_TEXTURE_2D)
5080 {
5081 es2::Texture2D *texture = context->getTexture2D();
5082
5083 if(!texture)
5084 {
5085 return error(GL_INVALID_OPERATION);
5086 }
5087
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005088 texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005089 }
5090 else
5091 {
5092 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5093
5094 if(!texture)
5095 {
5096 return error(GL_INVALID_OPERATION);
5097 }
5098
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005099 texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005100 }
5101 }
5102}
5103
5104void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5105{
5106 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5107
5108 es2::Context *context = es2::getContext();
5109
5110 if(context)
5111 {
5112 es2::Texture *texture;
5113
5114 GLint clientVersion = context->getClientVersion();
5115
5116 switch(target)
5117 {
5118 case GL_TEXTURE_2D:
5119 texture = context->getTexture2D();
5120 break;
5121 case GL_TEXTURE_2D_ARRAY:
5122 if(clientVersion < 3)
5123 {
5124 return error(GL_INVALID_ENUM);
5125 }
5126 else
5127 {
5128 texture = context->getTexture2DArray();
5129 }
5130 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005131 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005132 texture = context->getTexture3D();
5133 break;
5134 case GL_TEXTURE_CUBE_MAP:
5135 texture = context->getTextureCubeMap();
5136 break;
5137 case GL_TEXTURE_EXTERNAL_OES:
5138 texture = context->getTextureExternal();
5139 break;
5140 default:
5141 return error(GL_INVALID_ENUM);
5142 }
5143
5144 switch(pname)
5145 {
5146 case GL_TEXTURE_WRAP_S:
5147 if(!texture->setWrapS((GLenum)param))
5148 {
5149 return error(GL_INVALID_ENUM);
5150 }
5151 break;
5152 case GL_TEXTURE_WRAP_T:
5153 if(!texture->setWrapT((GLenum)param))
5154 {
5155 return error(GL_INVALID_ENUM);
5156 }
5157 break;
5158 case GL_TEXTURE_WRAP_R_OES:
5159 if(!texture->setWrapR((GLenum)param))
5160 {
5161 return error(GL_INVALID_ENUM);
5162 }
5163 break;
5164 case GL_TEXTURE_MIN_FILTER:
5165 if(!texture->setMinFilter((GLenum)param))
5166 {
5167 return error(GL_INVALID_ENUM);
5168 }
5169 break;
5170 case GL_TEXTURE_MAG_FILTER:
5171 if(!texture->setMagFilter((GLenum)param))
5172 {
5173 return error(GL_INVALID_ENUM);
5174 }
5175 break;
5176 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5177 if(!texture->setMaxAnisotropy(param))
5178 {
5179 return error(GL_INVALID_VALUE);
5180 }
5181 break;
5182 case GL_TEXTURE_BASE_LEVEL:
5183 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5184 {
5185 return error(GL_INVALID_VALUE);
5186 }
5187 break;
5188 case GL_TEXTURE_COMPARE_FUNC:
5189 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5190 {
5191 return error(GL_INVALID_VALUE);
5192 }
5193 break;
5194 case GL_TEXTURE_COMPARE_MODE:
5195 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5196 {
5197 return error(GL_INVALID_VALUE);
5198 }
5199 break;
5200 case GL_TEXTURE_MAX_LEVEL:
5201 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5202 {
5203 return error(GL_INVALID_VALUE);
5204 }
5205 break;
5206 case GL_TEXTURE_MAX_LOD:
5207 if(clientVersion < 3 || !texture->setMaxLOD(param))
5208 {
5209 return error(GL_INVALID_VALUE);
5210 }
5211 break;
5212 case GL_TEXTURE_MIN_LOD:
5213 if(clientVersion < 3 || !texture->setMinLOD(param))
5214 {
5215 return error(GL_INVALID_VALUE);
5216 }
5217 break;
5218 case GL_TEXTURE_SWIZZLE_R:
5219 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5220 {
5221 return error(GL_INVALID_VALUE);
5222 }
5223 break;
5224 case GL_TEXTURE_SWIZZLE_G:
5225 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5226 {
5227 return error(GL_INVALID_VALUE);
5228 }
5229 break;
5230 case GL_TEXTURE_SWIZZLE_B:
5231 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5232 {
5233 return error(GL_INVALID_VALUE);
5234 }
5235 break;
5236 case GL_TEXTURE_SWIZZLE_A:
5237 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5238 {
5239 return error(GL_INVALID_VALUE);
5240 }
5241 break;
5242 default:
5243 return error(GL_INVALID_ENUM);
5244 }
5245 }
5246}
5247
5248void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5249{
5250 glTexParameterf(target, pname, *params);
5251}
5252
5253void TexParameteri(GLenum target, GLenum pname, GLint param)
5254{
5255 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5256
5257 es2::Context *context = es2::getContext();
5258
5259 if(context)
5260 {
5261 es2::Texture *texture;
5262
5263 GLint clientVersion = context->getClientVersion();
5264
5265 switch(target)
5266 {
5267 case GL_TEXTURE_2D:
5268 texture = context->getTexture2D();
5269 break;
5270 case GL_TEXTURE_2D_ARRAY:
5271 if(clientVersion < 3)
5272 {
5273 return error(GL_INVALID_ENUM);
5274 }
5275 else
5276 {
5277 texture = context->getTexture2DArray();
5278 }
5279 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005280 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005281 texture = context->getTexture3D();
5282 break;
5283 case GL_TEXTURE_CUBE_MAP:
5284 texture = context->getTextureCubeMap();
5285 break;
5286 case GL_TEXTURE_EXTERNAL_OES:
5287 texture = context->getTextureExternal();
5288 break;
5289 default:
5290 return error(GL_INVALID_ENUM);
5291 }
5292
5293 switch(pname)
5294 {
5295 case GL_TEXTURE_WRAP_S:
5296 if(!texture->setWrapS((GLenum)param))
5297 {
5298 return error(GL_INVALID_ENUM);
5299 }
5300 break;
5301 case GL_TEXTURE_WRAP_T:
5302 if(!texture->setWrapT((GLenum)param))
5303 {
5304 return error(GL_INVALID_ENUM);
5305 }
5306 break;
5307 case GL_TEXTURE_WRAP_R_OES:
5308 if(!texture->setWrapR((GLenum)param))
5309 {
5310 return error(GL_INVALID_ENUM);
5311 }
5312 break;
5313 case GL_TEXTURE_MIN_FILTER:
5314 if(!texture->setMinFilter((GLenum)param))
5315 {
5316 return error(GL_INVALID_ENUM);
5317 }
5318 break;
5319 case GL_TEXTURE_MAG_FILTER:
5320 if(!texture->setMagFilter((GLenum)param))
5321 {
5322 return error(GL_INVALID_ENUM);
5323 }
5324 break;
5325 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5326 if(!texture->setMaxAnisotropy((GLfloat)param))
5327 {
5328 return error(GL_INVALID_VALUE);
5329 }
5330 break;
5331 case GL_TEXTURE_BASE_LEVEL:
5332 if(clientVersion < 3 || !texture->setBaseLevel(param))
5333 {
5334 return error(GL_INVALID_VALUE);
5335 }
5336 break;
5337 case GL_TEXTURE_COMPARE_FUNC:
5338 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5339 {
5340 return error(GL_INVALID_VALUE);
5341 }
5342 break;
5343 case GL_TEXTURE_COMPARE_MODE:
5344 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5345 {
5346 return error(GL_INVALID_VALUE);
5347 }
5348 break;
5349 case GL_TEXTURE_MAX_LEVEL:
5350 if(clientVersion < 3 || !texture->setMaxLevel(param))
5351 {
5352 return error(GL_INVALID_VALUE);
5353 }
5354 break;
5355 case GL_TEXTURE_MAX_LOD:
5356 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5357 {
5358 return error(GL_INVALID_VALUE);
5359 }
5360 break;
5361 case GL_TEXTURE_MIN_LOD:
5362 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5363 {
5364 return error(GL_INVALID_VALUE);
5365 }
5366 break;
5367 case GL_TEXTURE_SWIZZLE_R:
5368 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5369 {
5370 return error(GL_INVALID_VALUE);
5371 }
5372 break;
5373 case GL_TEXTURE_SWIZZLE_G:
5374 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5375 {
5376 return error(GL_INVALID_VALUE);
5377 }
5378 break;
5379 case GL_TEXTURE_SWIZZLE_B:
5380 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5381 {
5382 return error(GL_INVALID_VALUE);
5383 }
5384 break;
5385 case GL_TEXTURE_SWIZZLE_A:
5386 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5387 {
5388 return error(GL_INVALID_VALUE);
5389 }
5390 break;
5391 default:
5392 return error(GL_INVALID_ENUM);
5393 }
5394 }
5395}
5396
5397void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5398{
5399 glTexParameteri(target, pname, *params);
5400}
5401
5402void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005403 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005404{
5405 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5406 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005407 "const GLvoid* data = %p)",
5408 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005409
5410 if(!es2::IsTextureTarget(target))
5411 {
5412 return error(GL_INVALID_ENUM);
5413 }
5414
5415 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5416 {
5417 return error(GL_INVALID_VALUE);
5418 }
5419
5420 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5421 {
5422 return error(GL_INVALID_VALUE);
5423 }
5424
5425 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5426 {
5427 return error(GL_INVALID_VALUE);
5428 }
5429
Nicolas Capens0bac2852016-05-07 06:09:58 -04005430 es2::Context *context = es2::getContext();
5431
5432 if(context)
5433 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005434 if(target == GL_TEXTURE_2D)
5435 {
5436 es2::Texture2D *texture = context->getTexture2D();
5437
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005438 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5439 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005440 {
5441 return error(validationError);
5442 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005443
Nicolas Capens5555af42017-12-14 13:14:03 -05005444 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005445 if(validationError != GL_NONE)
5446 {
5447 return error(validationError);
5448 }
5449
Nicolas Capens5555af42017-12-14 13:14:03 -05005450 texture->subImage(context, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005451 }
5452 else if(es2::IsCubemapTextureTarget(target))
5453 {
5454 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5455
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005456 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5457 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005458 {
5459 return error(validationError);
5460 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005461
Nicolas Capens5555af42017-12-14 13:14:03 -05005462 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005463 if(validationError != GL_NONE)
5464 {
5465 return error(validationError);
5466 }
5467
Nicolas Capens5555af42017-12-14 13:14:03 -05005468 texture->subImage(context, target, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005469 }
5470 else UNREACHABLE(target);
5471 }
5472}
5473
5474void Uniform1f(GLint location, GLfloat x)
5475{
5476 glUniform1fv(location, 1, &x);
5477}
5478
5479void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5480{
5481 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5482
5483 if(count < 0)
5484 {
5485 return error(GL_INVALID_VALUE);
5486 }
5487
Nicolas Capens0bac2852016-05-07 06:09:58 -04005488 es2::Context *context = es2::getContext();
5489
5490 if(context)
5491 {
5492 es2::Program *program = context->getCurrentProgram();
5493
5494 if(!program)
5495 {
5496 return error(GL_INVALID_OPERATION);
5497 }
5498
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005499 if(location == -1)
5500 {
5501 return;
5502 }
5503
Nicolas Capens0bac2852016-05-07 06:09:58 -04005504 if(!program->setUniform1fv(location, count, v))
5505 {
5506 return error(GL_INVALID_OPERATION);
5507 }
5508 }
5509}
5510
5511void Uniform1i(GLint location, GLint x)
5512{
5513 glUniform1iv(location, 1, &x);
5514}
5515
5516void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5517{
5518 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5519
5520 if(count < 0)
5521 {
5522 return error(GL_INVALID_VALUE);
5523 }
5524
Nicolas Capens0bac2852016-05-07 06:09:58 -04005525 es2::Context *context = es2::getContext();
5526
5527 if(context)
5528 {
5529 es2::Program *program = context->getCurrentProgram();
5530
5531 if(!program)
5532 {
5533 return error(GL_INVALID_OPERATION);
5534 }
5535
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005536 if(location == -1)
5537 {
5538 return;
5539 }
5540
Nicolas Capens0bac2852016-05-07 06:09:58 -04005541 if(!program->setUniform1iv(location, count, v))
5542 {
5543 return error(GL_INVALID_OPERATION);
5544 }
5545 }
5546}
5547
5548void Uniform2f(GLint location, GLfloat x, GLfloat y)
5549{
5550 GLfloat xy[2] = {x, y};
5551
5552 glUniform2fv(location, 1, (GLfloat*)&xy);
5553}
5554
5555void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5556{
5557 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5558
5559 if(count < 0)
5560 {
5561 return error(GL_INVALID_VALUE);
5562 }
5563
Nicolas Capens0bac2852016-05-07 06:09:58 -04005564 es2::Context *context = es2::getContext();
5565
5566 if(context)
5567 {
5568 es2::Program *program = context->getCurrentProgram();
5569
5570 if(!program)
5571 {
5572 return error(GL_INVALID_OPERATION);
5573 }
5574
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005575 if(location == -1)
5576 {
5577 return;
5578 }
5579
Nicolas Capens0bac2852016-05-07 06:09:58 -04005580 if(!program->setUniform2fv(location, count, v))
5581 {
5582 return error(GL_INVALID_OPERATION);
5583 }
5584 }
5585}
5586
5587void Uniform2i(GLint location, GLint x, GLint y)
5588{
5589 GLint xy[4] = {x, y};
5590
5591 glUniform2iv(location, 1, (GLint*)&xy);
5592}
5593
5594void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5595{
5596 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5597
5598 if(count < 0)
5599 {
5600 return error(GL_INVALID_VALUE);
5601 }
5602
Nicolas Capens0bac2852016-05-07 06:09:58 -04005603 es2::Context *context = es2::getContext();
5604
5605 if(context)
5606 {
5607 es2::Program *program = context->getCurrentProgram();
5608
5609 if(!program)
5610 {
5611 return error(GL_INVALID_OPERATION);
5612 }
5613
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005614 if(location == -1)
5615 {
5616 return;
5617 }
5618
Nicolas Capens0bac2852016-05-07 06:09:58 -04005619 if(!program->setUniform2iv(location, count, v))
5620 {
5621 return error(GL_INVALID_OPERATION);
5622 }
5623 }
5624}
5625
5626void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5627{
5628 GLfloat xyz[3] = {x, y, z};
5629
5630 glUniform3fv(location, 1, (GLfloat*)&xyz);
5631}
5632
5633void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5634{
5635 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5636
5637 if(count < 0)
5638 {
5639 return error(GL_INVALID_VALUE);
5640 }
5641
Nicolas Capens0bac2852016-05-07 06:09:58 -04005642 es2::Context *context = es2::getContext();
5643
5644 if(context)
5645 {
5646 es2::Program *program = context->getCurrentProgram();
5647
5648 if(!program)
5649 {
5650 return error(GL_INVALID_OPERATION);
5651 }
5652
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005653 if(location == -1)
5654 {
5655 return;
5656 }
5657
Nicolas Capens0bac2852016-05-07 06:09:58 -04005658 if(!program->setUniform3fv(location, count, v))
5659 {
5660 return error(GL_INVALID_OPERATION);
5661 }
5662 }
5663}
5664
5665void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5666{
5667 GLint xyz[3] = {x, y, z};
5668
5669 glUniform3iv(location, 1, (GLint*)&xyz);
5670}
5671
5672void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5673{
5674 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5675
5676 if(count < 0)
5677 {
5678 return error(GL_INVALID_VALUE);
5679 }
5680
Nicolas Capens0bac2852016-05-07 06:09:58 -04005681 es2::Context *context = es2::getContext();
5682
5683 if(context)
5684 {
5685 es2::Program *program = context->getCurrentProgram();
5686
5687 if(!program)
5688 {
5689 return error(GL_INVALID_OPERATION);
5690 }
5691
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005692 if(location == -1)
5693 {
5694 return;
5695 }
5696
Nicolas Capens0bac2852016-05-07 06:09:58 -04005697 if(!program->setUniform3iv(location, count, v))
5698 {
5699 return error(GL_INVALID_OPERATION);
5700 }
5701 }
5702}
5703
5704void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5705{
5706 GLfloat xyzw[4] = {x, y, z, w};
5707
5708 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5709}
5710
5711void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5712{
5713 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5714
5715 if(count < 0)
5716 {
5717 return error(GL_INVALID_VALUE);
5718 }
5719
Nicolas Capens0bac2852016-05-07 06:09:58 -04005720 es2::Context *context = es2::getContext();
5721
5722 if(context)
5723 {
5724 es2::Program *program = context->getCurrentProgram();
5725
5726 if(!program)
5727 {
5728 return error(GL_INVALID_OPERATION);
5729 }
5730
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005731 if(location == -1)
5732 {
5733 return;
5734 }
5735
Nicolas Capens0bac2852016-05-07 06:09:58 -04005736 if(!program->setUniform4fv(location, count, v))
5737 {
5738 return error(GL_INVALID_OPERATION);
5739 }
5740 }
5741}
5742
5743void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5744{
5745 GLint xyzw[4] = {x, y, z, w};
5746
5747 glUniform4iv(location, 1, (GLint*)&xyzw);
5748}
5749
5750void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5751{
5752 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5753
5754 if(count < 0)
5755 {
5756 return error(GL_INVALID_VALUE);
5757 }
5758
Nicolas Capens0bac2852016-05-07 06:09:58 -04005759 es2::Context *context = es2::getContext();
5760
5761 if(context)
5762 {
5763 es2::Program *program = context->getCurrentProgram();
5764
5765 if(!program)
5766 {
5767 return error(GL_INVALID_OPERATION);
5768 }
5769
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005770 if(location == -1)
5771 {
5772 return;
5773 }
5774
Nicolas Capens0bac2852016-05-07 06:09:58 -04005775 if(!program->setUniform4iv(location, count, v))
5776 {
5777 return error(GL_INVALID_OPERATION);
5778 }
5779 }
5780}
5781
5782void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5783{
5784 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5785 location, count, transpose, value);
5786
5787 if(count < 0)
5788 {
5789 return error(GL_INVALID_VALUE);
5790 }
5791
Nicolas Capens0bac2852016-05-07 06:09:58 -04005792 es2::Context *context = es2::getContext();
5793
5794 if(context)
5795 {
5796 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5797 {
5798 return error(GL_INVALID_VALUE);
5799 }
5800
5801 es2::Program *program = context->getCurrentProgram();
5802
5803 if(!program)
5804 {
5805 return error(GL_INVALID_OPERATION);
5806 }
5807
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005808 if(location == -1)
5809 {
5810 return;
5811 }
5812
Nicolas Capens0bac2852016-05-07 06:09:58 -04005813 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5814 {
5815 return error(GL_INVALID_OPERATION);
5816 }
5817 }
5818}
5819
5820void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5821{
5822 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5823 location, count, transpose, value);
5824
5825 if(count < 0)
5826 {
5827 return error(GL_INVALID_VALUE);
5828 }
5829
Nicolas Capens0bac2852016-05-07 06:09:58 -04005830 es2::Context *context = es2::getContext();
5831
5832 if(context)
5833 {
5834 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5835 {
5836 return error(GL_INVALID_VALUE);
5837 }
5838
5839 es2::Program *program = context->getCurrentProgram();
5840
5841 if(!program)
5842 {
5843 return error(GL_INVALID_OPERATION);
5844 }
5845
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005846 if(location == -1)
5847 {
5848 return;
5849 }
5850
Nicolas Capens0bac2852016-05-07 06:09:58 -04005851 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5852 {
5853 return error(GL_INVALID_OPERATION);
5854 }
5855 }
5856}
5857
5858void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5859{
5860 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5861 location, count, transpose, value);
5862
5863 if(count < 0)
5864 {
5865 return error(GL_INVALID_VALUE);
5866 }
5867
Nicolas Capens0bac2852016-05-07 06:09:58 -04005868 es2::Context *context = es2::getContext();
5869
5870 if(context)
5871 {
5872 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5873 {
5874 return error(GL_INVALID_VALUE);
5875 }
5876
5877 es2::Program *program = context->getCurrentProgram();
5878
5879 if(!program)
5880 {
5881 return error(GL_INVALID_OPERATION);
5882 }
5883
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005884 if(location == -1)
5885 {
5886 return;
5887 }
5888
Nicolas Capens0bac2852016-05-07 06:09:58 -04005889 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5890 {
5891 return error(GL_INVALID_OPERATION);
5892 }
5893 }
5894}
5895
5896void UseProgram(GLuint program)
5897{
5898 TRACE("(GLuint program = %d)", program);
5899
5900 es2::Context *context = es2::getContext();
5901
5902 if(context)
5903 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005904 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5905 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5906 {
5907 return error(GL_INVALID_OPERATION);
5908 }
5909
Nicolas Capens0bac2852016-05-07 06:09:58 -04005910 es2::Program *programObject = context->getProgram(program);
5911
5912 if(!programObject && program != 0)
5913 {
5914 if(context->getShader(program))
5915 {
5916 return error(GL_INVALID_OPERATION);
5917 }
5918 else
5919 {
5920 return error(GL_INVALID_VALUE);
5921 }
5922 }
5923
5924 if(program != 0 && !programObject->isLinked())
5925 {
5926 return error(GL_INVALID_OPERATION);
5927 }
5928
5929 context->useProgram(program);
5930 }
5931}
5932
5933void ValidateProgram(GLuint program)
5934{
5935 TRACE("(GLuint program = %d)", program);
5936
5937 es2::Context *context = es2::getContext();
5938
5939 if(context)
5940 {
5941 es2::Program *programObject = context->getProgram(program);
5942
5943 if(!programObject)
5944 {
5945 if(context->getShader(program))
5946 {
5947 return error(GL_INVALID_OPERATION);
5948 }
5949 else
5950 {
5951 return error(GL_INVALID_VALUE);
5952 }
5953 }
5954
Ben Vanik1fd3b282017-07-10 14:08:12 -07005955 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005956 }
5957}
5958
5959void VertexAttrib1f(GLuint index, GLfloat x)
5960{
5961 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5962
5963 if(index >= es2::MAX_VERTEX_ATTRIBS)
5964 {
5965 return error(GL_INVALID_VALUE);
5966 }
5967
5968 es2::Context *context = es2::getContext();
5969
5970 if(context)
5971 {
5972 GLfloat vals[4] = { x, 0, 0, 1 };
5973 context->setVertexAttrib(index, vals);
5974 }
5975}
5976
5977void VertexAttrib1fv(GLuint index, const GLfloat* values)
5978{
5979 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5980
5981 if(index >= es2::MAX_VERTEX_ATTRIBS)
5982 {
5983 return error(GL_INVALID_VALUE);
5984 }
5985
5986 es2::Context *context = es2::getContext();
5987
5988 if(context)
5989 {
5990 GLfloat vals[4] = { values[0], 0, 0, 1 };
5991 context->setVertexAttrib(index, vals);
5992 }
5993}
5994
5995void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5996{
5997 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5998
5999 if(index >= es2::MAX_VERTEX_ATTRIBS)
6000 {
6001 return error(GL_INVALID_VALUE);
6002 }
6003
6004 es2::Context *context = es2::getContext();
6005
6006 if(context)
6007 {
6008 GLfloat vals[4] = { x, y, 0, 1 };
6009 context->setVertexAttrib(index, vals);
6010 }
6011}
6012
6013void VertexAttrib2fv(GLuint index, const GLfloat* values)
6014{
6015 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6016
6017 if(index >= es2::MAX_VERTEX_ATTRIBS)
6018 {
6019 return error(GL_INVALID_VALUE);
6020 }
6021
6022 es2::Context *context = es2::getContext();
6023
6024 if(context)
6025 {
6026 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6027 context->setVertexAttrib(index, vals);
6028 }
6029}
6030
6031void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6032{
6033 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
6034
6035 if(index >= es2::MAX_VERTEX_ATTRIBS)
6036 {
6037 return error(GL_INVALID_VALUE);
6038 }
6039
6040 es2::Context *context = es2::getContext();
6041
6042 if(context)
6043 {
6044 GLfloat vals[4] = { x, y, z, 1 };
6045 context->setVertexAttrib(index, vals);
6046 }
6047}
6048
6049void VertexAttrib3fv(GLuint index, const GLfloat* values)
6050{
6051 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6052
6053 if(index >= es2::MAX_VERTEX_ATTRIBS)
6054 {
6055 return error(GL_INVALID_VALUE);
6056 }
6057
6058 es2::Context *context = es2::getContext();
6059
6060 if(context)
6061 {
6062 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6063 context->setVertexAttrib(index, vals);
6064 }
6065}
6066
6067void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6068{
6069 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6070
6071 if(index >= es2::MAX_VERTEX_ATTRIBS)
6072 {
6073 return error(GL_INVALID_VALUE);
6074 }
6075
6076 es2::Context *context = es2::getContext();
6077
6078 if(context)
6079 {
6080 GLfloat vals[4] = { x, y, z, w };
6081 context->setVertexAttrib(index, vals);
6082 }
6083}
6084
6085void VertexAttrib4fv(GLuint index, const GLfloat* values)
6086{
6087 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6088
6089 if(index >= es2::MAX_VERTEX_ATTRIBS)
6090 {
6091 return error(GL_INVALID_VALUE);
6092 }
6093
6094 es2::Context *context = es2::getContext();
6095
6096 if(context)
6097 {
6098 context->setVertexAttrib(index, values);
6099 }
6100}
6101
6102void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6103{
6104 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6105 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6106 index, size, type, normalized, stride, ptr);
6107
6108 if(index >= es2::MAX_VERTEX_ATTRIBS)
6109 {
6110 return error(GL_INVALID_VALUE);
6111 }
6112
6113 if(size < 1 || size > 4)
6114 {
6115 return error(GL_INVALID_VALUE);
6116 }
6117
6118 GLint clientVersion = egl::getClientVersion();
6119
6120 switch(type)
6121 {
6122 case GL_BYTE:
6123 case GL_UNSIGNED_BYTE:
6124 case GL_SHORT:
6125 case GL_UNSIGNED_SHORT:
6126 case GL_FIXED:
6127 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006128 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006129 break;
6130 case GL_INT_2_10_10_10_REV:
6131 case GL_UNSIGNED_INT_2_10_10_10_REV:
6132 if(clientVersion >= 3)
6133 {
6134 if(size != 4)
6135 {
6136 return error(GL_INVALID_OPERATION);
6137 }
6138 break;
6139 }
6140 else return error(GL_INVALID_ENUM);
6141 case GL_INT:
6142 case GL_UNSIGNED_INT:
6143 case GL_HALF_FLOAT:
6144 if(clientVersion >= 3)
6145 {
6146 break;
6147 }
6148 else return error(GL_INVALID_ENUM);
6149 default:
6150 return error(GL_INVALID_ENUM);
6151 }
6152
6153 if(stride < 0)
6154 {
6155 return error(GL_INVALID_VALUE);
6156 }
6157
6158 es2::Context *context = es2::getContext();
6159
6160 if(context)
6161 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006162 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6163 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6164 {
6165 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6166 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6167 return error(GL_INVALID_OPERATION);
6168 }
6169
Alexis Hetu6f284032017-12-11 15:19:36 -05006170 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006171 }
6172}
6173
6174void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6175{
6176 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6177
6178 if(width < 0 || height < 0)
6179 {
6180 return error(GL_INVALID_VALUE);
6181 }
6182
6183 es2::Context *context = es2::getContext();
6184
6185 if(context)
6186 {
6187 context->setViewportParams(x, y, width, height);
6188 }
6189}
6190
Alexis Hetub9dda642016-10-06 11:25:32 -04006191static 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 -04006192{
6193 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6194 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6195 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6196 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6197
6198 switch(filter)
6199 {
6200 case GL_NEAREST:
6201 break;
6202 default:
6203 return error(GL_INVALID_ENUM);
6204 }
6205
6206 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6207 {
6208 return error(GL_INVALID_VALUE);
6209 }
6210
6211 es2::Context *context = es2::getContext();
6212
6213 if(context)
6214 {
6215 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6216 {
6217 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6218 return error(GL_INVALID_OPERATION);
6219 }
6220
Alexis Hetub9dda642016-10-06 11:25:32 -04006221 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006222 }
6223}
6224
Alexis Hetub9dda642016-10-06 11:25:32 -04006225void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6226{
6227 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6228}
6229
Nicolas Capens0bac2852016-05-07 06:09:58 -04006230void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6231 GLbitfield mask, GLenum filter)
6232{
6233 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6234 {
6235 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6236 return error(GL_INVALID_OPERATION);
6237 }
6238
Alexis Hetub9dda642016-10-06 11:25:32 -04006239 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006240}
6241
6242void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006243 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006244{
6245 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6246 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006247 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6248 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006249
6250 switch(target)
6251 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006252 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006253 switch(format)
6254 {
6255 case GL_DEPTH_COMPONENT:
6256 case GL_DEPTH_STENCIL_OES:
6257 return error(GL_INVALID_OPERATION);
6258 default:
6259 break;
6260 }
6261 break;
6262 default:
6263 return error(GL_INVALID_ENUM);
6264 }
6265
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006266 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006267 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006268 return error(GL_INVALID_OPERATION);
6269 }
6270
6271 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion());
6272 if(validationError != GL_NONE)
6273 {
6274 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006275 }
6276
6277 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6278 {
6279 return error(GL_INVALID_VALUE);
6280 }
6281
6282 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6283 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6284 {
6285 return error(GL_INVALID_VALUE);
6286 }
6287
6288 if(border != 0)
6289 {
6290 return error(GL_INVALID_VALUE);
6291 }
6292
6293 es2::Context *context = es2::getContext();
6294
6295 if(context)
6296 {
6297 es2::Texture3D *texture = context->getTexture3D();
6298
6299 if(!texture)
6300 {
6301 return error(GL_INVALID_OPERATION);
6302 }
6303
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006304 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006305 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006306 if(validationError != GL_NONE)
6307 {
6308 return error(validationError);
6309 }
6310
6311 texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006312 }
6313}
6314
Alexis Hetu53f48092016-06-17 14:08:06 -04006315void 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 -04006316{
6317 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6318 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006319 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6320 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006321
6322 switch(target)
6323 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006324 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006325 break;
6326 default:
6327 return error(GL_INVALID_ENUM);
6328 }
6329
6330 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6331 {
6332 return;
6333 }
6334
6335 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6336 {
6337 return error(GL_INVALID_VALUE);
6338 }
6339
6340 if((width < 0) || (height < 0) || (depth < 0))
6341 {
6342 return error(GL_INVALID_VALUE);
6343 }
6344
6345 es2::Context *context = es2::getContext();
6346
6347 if(context)
6348 {
6349 es2::Texture3D *texture = context->getTexture3D();
6350
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006351 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
6352 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006353 {
6354 return error(validationError);
6355 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006356
Nicolas Capens5555af42017-12-14 13:14:03 -05006357 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006358 if(validationError != GL_NONE)
6359 {
6360 return error(validationError);
6361 }
6362
Nicolas Capens5555af42017-12-14 13:14:03 -05006363 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006364 }
6365}
6366
6367void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6368{
6369 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6370 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6371 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6372
6373 switch(target)
6374 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006375 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006376 break;
6377 default:
6378 return error(GL_INVALID_ENUM);
6379 }
6380
6381 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6382 {
6383 return error(GL_INVALID_VALUE);
6384 }
6385
6386 es2::Context *context = es2::getContext();
6387
6388 if(context)
6389 {
6390 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6391
6392 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6393 {
6394 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6395 }
6396
6397 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6398
6399 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6400 {
6401 return error(GL_INVALID_OPERATION);
6402 }
6403
6404 es2::Texture3D *texture = context->getTexture3D();
6405
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006406 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 -04006407 if(validationError != GL_NONE)
6408 {
6409 return error(validationError);
6410 }
6411
6412 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6413 }
6414}
6415
6416void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6417{
6418 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6419 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6420 target, level, internalformat, width, height, depth, border, imageSize, data);
6421
6422 switch(target)
6423 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006424 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006425 break;
6426 default:
6427 return error(GL_INVALID_ENUM);
6428 }
6429
6430 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6431 {
6432 return error(GL_INVALID_VALUE);
6433 }
6434
6435 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6436 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6437 {
6438 return error(GL_INVALID_VALUE);
6439 }
6440
6441 switch(internalformat)
6442 {
6443 case GL_DEPTH_COMPONENT:
6444 case GL_DEPTH_COMPONENT16:
6445 case GL_DEPTH_COMPONENT32_OES:
6446 case GL_DEPTH_STENCIL_OES:
6447 case GL_DEPTH24_STENCIL8_OES:
6448 return error(GL_INVALID_OPERATION);
6449 default:
6450 {
6451 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
6452 if(validationError != GL_NONE)
6453 {
6454 return error(validationError);
6455 }
6456 }
6457 }
6458
6459 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6460 {
6461 return error(GL_INVALID_VALUE);
6462 }
6463
6464 es2::Context *context = es2::getContext();
6465
6466 if(context)
6467 {
6468 es2::Texture3D *texture = context->getTexture3D();
6469
6470 if(!texture)
6471 {
6472 return error(GL_INVALID_OPERATION);
6473 }
6474
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006475 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006476
6477 if(validationError != GL_NONE)
6478 {
6479 return error(validationError);
6480 }
6481
Nicolas Capens0bac2852016-05-07 06:09:58 -04006482 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6483 }
6484}
6485
6486void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6487{
6488 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6489 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6490 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6491 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6492
6493 switch(target)
6494 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006495 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006496 break;
6497 default:
6498 return error(GL_INVALID_ENUM);
6499 }
6500
6501 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6502 {
6503 return error(GL_INVALID_VALUE);
6504 }
6505
6506 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6507 {
6508 return error(GL_INVALID_VALUE);
6509 }
6510
6511 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
6512 if(validationError != GL_NONE)
6513 {
6514 return error(validationError);
6515 }
6516
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006517 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006518 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006519 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006520 }
6521
6522 es2::Context *context = es2::getContext();
6523
6524 if(context)
6525 {
6526 es2::Texture3D *texture = context->getTexture3D();
6527
6528 if(!texture)
6529 {
6530 return error(GL_INVALID_OPERATION);
6531 }
6532
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006533 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006534 if(validationError != GL_NONE)
6535 {
6536 return error(validationError);
6537 }
6538
6539 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006540 }
6541}
6542
6543void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6544{
6545 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6546 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6547
6548 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
6549 {
6550 return error(GL_INVALID_ENUM);
6551 }
6552
6553 es2::Context *context = es2::getContext();
6554
6555 if(context)
6556 {
6557 if(texture == 0)
6558 {
6559 textarget = GL_NONE;
6560 }
6561 else
6562 {
6563 es2::Texture *tex = context->getTexture(texture);
6564
6565 if(!tex)
6566 {
6567 return error(GL_INVALID_OPERATION);
6568 }
6569
6570 if(tex->isCompressed(textarget, level))
6571 {
6572 return error(GL_INVALID_OPERATION);
6573 }
6574
6575 switch(textarget)
6576 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006577 case GL_TEXTURE_3D:
6578 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006579 {
6580 return error(GL_INVALID_OPERATION);
6581 }
6582 break;
6583 default:
6584 return error(GL_INVALID_ENUM);
6585 }
6586
6587 if(level != 0)
6588 {
6589 return error(GL_INVALID_VALUE);
6590 }
6591 }
6592
6593 es2::Framebuffer *framebuffer = nullptr;
6594 GLuint framebufferName = 0;
6595 if(target == GL_READ_FRAMEBUFFER_ANGLE)
6596 {
6597 framebuffer = context->getReadFramebuffer();
6598 framebufferName = context->getReadFramebufferName();
6599 }
6600 else
6601 {
6602 framebuffer = context->getDrawFramebuffer();
6603 framebufferName = context->getDrawFramebufferName();
6604 }
6605
6606 if(framebufferName == 0 || !framebuffer)
6607 {
6608 return error(GL_INVALID_OPERATION);
6609 }
6610
6611 GLint clientVersion = context->getClientVersion();
6612
6613 switch(attachment)
6614 {
6615 case GL_COLOR_ATTACHMENT1:
6616 case GL_COLOR_ATTACHMENT2:
6617 case GL_COLOR_ATTACHMENT3:
6618 case GL_COLOR_ATTACHMENT4:
6619 case GL_COLOR_ATTACHMENT5:
6620 case GL_COLOR_ATTACHMENT6:
6621 case GL_COLOR_ATTACHMENT7:
6622 case GL_COLOR_ATTACHMENT8:
6623 case GL_COLOR_ATTACHMENT9:
6624 case GL_COLOR_ATTACHMENT10:
6625 case GL_COLOR_ATTACHMENT11:
6626 case GL_COLOR_ATTACHMENT12:
6627 case GL_COLOR_ATTACHMENT13:
6628 case GL_COLOR_ATTACHMENT14:
6629 case GL_COLOR_ATTACHMENT15:
6630 case GL_COLOR_ATTACHMENT16:
6631 case GL_COLOR_ATTACHMENT17:
6632 case GL_COLOR_ATTACHMENT18:
6633 case GL_COLOR_ATTACHMENT19:
6634 case GL_COLOR_ATTACHMENT20:
6635 case GL_COLOR_ATTACHMENT21:
6636 case GL_COLOR_ATTACHMENT22:
6637 case GL_COLOR_ATTACHMENT23:
6638 case GL_COLOR_ATTACHMENT24:
6639 case GL_COLOR_ATTACHMENT25:
6640 case GL_COLOR_ATTACHMENT26:
6641 case GL_COLOR_ATTACHMENT27:
6642 case GL_COLOR_ATTACHMENT28:
6643 case GL_COLOR_ATTACHMENT29:
6644 case GL_COLOR_ATTACHMENT30:
6645 case GL_COLOR_ATTACHMENT31:
6646 if(clientVersion < 3)
6647 {
6648 return error(GL_INVALID_ENUM);
6649 }
6650 // fall through
6651 case GL_COLOR_ATTACHMENT0:
6652 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6653 {
6654 return error(GL_INVALID_ENUM);
6655 }
6656 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6657 break;
6658 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6659 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6660 default:
6661 return error(GL_INVALID_ENUM);
6662 }
6663 }
6664}
6665
6666void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6667{
6668 if(egl::getClientVersion() == 1)
6669 {
6670 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6671 }
6672
6673 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6674
6675 switch(target)
6676 {
6677 case GL_TEXTURE_2D:
6678 case GL_TEXTURE_EXTERNAL_OES:
6679 break;
6680 default:
6681 return error(GL_INVALID_ENUM);
6682 }
6683
Nicolas Capens0bac2852016-05-07 06:09:58 -04006684 es2::Context *context = es2::getContext();
6685
6686 if(context)
6687 {
Nicolas Capens58df2f62016-06-07 14:48:56 -04006688 es2::Texture2D *texture = nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006689
6690 switch(target)
6691 {
6692 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
6693 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
6694 default: UNREACHABLE(target);
6695 }
6696
6697 if(!texture)
6698 {
6699 return error(GL_INVALID_OPERATION);
6700 }
6701
Nicolas Capens58df2f62016-06-07 14:48:56 -04006702 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006703
Nicolas Capens58df2f62016-06-07 14:48:56 -04006704 if(!eglImage)
6705 {
6706 return error(GL_INVALID_OPERATION);
6707 }
6708
6709 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006710 }
6711}
6712
6713void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6714{
6715 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6716
6717 UNIMPLEMENTED();
6718}
6719
6720GLboolean IsRenderbufferOES(GLuint renderbuffer)
6721{
6722 return IsRenderbuffer(renderbuffer);
6723}
6724
6725void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6726{
6727 BindRenderbuffer(target, renderbuffer);
6728}
6729
6730void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6731{
6732 DeleteRenderbuffers(n, renderbuffers);
6733}
6734
6735void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6736{
6737 GenRenderbuffers(n, renderbuffers);
6738}
6739
6740void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6741{
6742 RenderbufferStorage(target, internalformat, width, height);
6743}
6744
6745void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6746{
6747 GetRenderbufferParameteriv(target, pname, params);
6748}
6749
6750GLboolean IsFramebufferOES(GLuint framebuffer)
6751{
6752 return IsFramebuffer(framebuffer);
6753}
6754
6755void BindFramebufferOES(GLenum target, GLuint framebuffer)
6756{
6757 BindFramebuffer(target, framebuffer);
6758}
6759
6760void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6761{
6762 DeleteFramebuffers(n, framebuffers);
6763}
6764
6765void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6766{
6767 GenFramebuffers(n, framebuffers);
6768}
6769
6770GLenum CheckFramebufferStatusOES(GLenum target)
6771{
6772 return CheckFramebufferStatus(target);
6773}
6774
6775void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6776{
6777 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6778}
6779
6780void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6781{
6782 FramebufferTexture2D(target, attachment, textarget, texture, level);
6783}
6784
6785void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6786{
6787 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6788}
6789
6790void GenerateMipmapOES(GLenum target)
6791{
6792 GenerateMipmap(target);
6793}
6794
6795void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6796{
6797 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6798
6799 if(n < 0 || n > MAX_DRAW_BUFFERS)
6800 {
6801 return error(GL_INVALID_VALUE);
6802 }
6803
6804 es2::Context *context = es2::getContext();
6805
6806 if(context)
6807 {
6808 GLuint drawFramebufferName = context->getDrawFramebufferName();
6809
6810 if((drawFramebufferName == 0) && (n != 1))
6811 {
6812 return error(GL_INVALID_OPERATION);
6813 }
6814
6815 for(unsigned int i = 0; i < (unsigned)n; i++)
6816 {
6817 switch(bufs[i])
6818 {
6819 case GL_BACK:
6820 if(drawFramebufferName != 0)
6821 {
6822 return error(GL_INVALID_OPERATION);
6823 }
6824 break;
6825 case GL_NONE:
6826 break;
6827 case GL_COLOR_ATTACHMENT0_EXT:
6828 case GL_COLOR_ATTACHMENT1_EXT:
6829 case GL_COLOR_ATTACHMENT2_EXT:
6830 case GL_COLOR_ATTACHMENT3_EXT:
6831 case GL_COLOR_ATTACHMENT4_EXT:
6832 case GL_COLOR_ATTACHMENT5_EXT:
6833 case GL_COLOR_ATTACHMENT6_EXT:
6834 case GL_COLOR_ATTACHMENT7_EXT:
6835 case GL_COLOR_ATTACHMENT8_EXT:
6836 case GL_COLOR_ATTACHMENT9_EXT:
6837 case GL_COLOR_ATTACHMENT10_EXT:
6838 case GL_COLOR_ATTACHMENT11_EXT:
6839 case GL_COLOR_ATTACHMENT12_EXT:
6840 case GL_COLOR_ATTACHMENT13_EXT:
6841 case GL_COLOR_ATTACHMENT14_EXT:
6842 case GL_COLOR_ATTACHMENT15_EXT:
6843 {
6844 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6845
6846 if(index >= MAX_COLOR_ATTACHMENTS)
6847 {
6848 return error(GL_INVALID_OPERATION);
6849 }
6850
6851 if(index != i)
6852 {
6853 return error(GL_INVALID_OPERATION);
6854 }
6855
6856 if(drawFramebufferName == 0)
6857 {
6858 return error(GL_INVALID_OPERATION);
6859 }
6860 }
6861 break;
6862 default:
6863 return error(GL_INVALID_ENUM);
6864 }
6865 }
6866
6867 context->setFramebufferDrawBuffers(n, bufs);
6868 }
6869}
6870
6871}
6872
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006873extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006874{
6875 struct Extension
6876 {
6877 const char *name;
6878 __eglMustCastToProperFunctionPointerType address;
6879 };
6880
6881 static const Extension glExtensions[] =
6882 {
6883 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6884
6885 EXTENSION(glTexImage3DOES),
6886 EXTENSION(glBlitFramebufferANGLE),
6887 EXTENSION(glBlitFramebufferNV),
6888 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6889 EXTENSION(glDeleteFencesNV),
6890 EXTENSION(glGenFencesNV),
6891 EXTENSION(glIsFenceNV),
6892 EXTENSION(glTestFenceNV),
6893 EXTENSION(glGetFenceivNV),
6894 EXTENSION(glFinishFenceNV),
6895 EXTENSION(glSetFenceNV),
6896 EXTENSION(glGetGraphicsResetStatusEXT),
6897 EXTENSION(glReadnPixelsEXT),
6898 EXTENSION(glGetnUniformfvEXT),
6899 EXTENSION(glGetnUniformivEXT),
6900 EXTENSION(glGenQueriesEXT),
6901 EXTENSION(glDeleteQueriesEXT),
6902 EXTENSION(glIsQueryEXT),
6903 EXTENSION(glBeginQueryEXT),
6904 EXTENSION(glEndQueryEXT),
6905 EXTENSION(glGetQueryivEXT),
6906 EXTENSION(glGetQueryObjectuivEXT),
6907 EXTENSION(glEGLImageTargetTexture2DOES),
6908 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
6909 EXTENSION(glDrawElementsInstancedEXT),
6910 EXTENSION(glDrawArraysInstancedEXT),
6911 EXTENSION(glVertexAttribDivisorEXT),
6912 EXTENSION(glDrawArraysInstancedANGLE),
6913 EXTENSION(glDrawElementsInstancedANGLE),
6914 EXTENSION(glVertexAttribDivisorANGLE),
6915 EXTENSION(glIsRenderbufferOES),
6916 EXTENSION(glBindRenderbufferOES),
6917 EXTENSION(glDeleteRenderbuffersOES),
6918 EXTENSION(glGenRenderbuffersOES),
6919 EXTENSION(glRenderbufferStorageOES),
6920 EXTENSION(glGetRenderbufferParameterivOES),
6921 EXTENSION(glIsFramebufferOES),
6922 EXTENSION(glBindFramebufferOES),
6923 EXTENSION(glDeleteFramebuffersOES),
6924 EXTENSION(glGenFramebuffersOES),
6925 EXTENSION(glCheckFramebufferStatusOES),
6926 EXTENSION(glFramebufferRenderbufferOES),
6927 EXTENSION(glFramebufferTexture2DOES),
6928 EXTENSION(glGetFramebufferAttachmentParameterivOES),
6929 EXTENSION(glGenerateMipmapOES),
6930 EXTENSION(glDrawBuffersEXT),
6931
6932 #undef EXTENSION
6933 };
6934
6935 for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
6936 {
6937 if(strcmp(procname, glExtensions[ext].name) == 0)
6938 {
6939 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
6940 }
6941 }
6942
6943 return nullptr;
6944}