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