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