blob: 5198adabb9907420f2c01a129db68bd0c5abc95e [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
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002759 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002760
Nicolas Capens0bac2852016-05-07 06:09:58 -04002761 if(target == GL_READ_FRAMEBUFFER)
2762 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002763 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002764 }
2765 else
2766 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002767 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002768 }
2769
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002770 GLint clientVersion = context->getClientVersion();
2771
2772 if(framebufferName == 0) // Default framebuffer.
2773 {
2774 if(clientVersion < 3)
2775 {
2776 return error(GL_INVALID_OPERATION);
2777 }
2778 }
2779
Nicolas Capens0bac2852016-05-07 06:09:58 -04002780 switch(attachment)
2781 {
2782 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002783 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002784 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002785 if(clientVersion < 3)
2786 {
2787 return error(GL_INVALID_ENUM);
2788 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002789
2790 if(framebufferName != 0)
2791 {
2792 return error(GL_INVALID_OPERATION);
2793 }
2794 break;
2795 case GL_DEPTH_ATTACHMENT:
2796 case GL_STENCIL_ATTACHMENT:
2797 if(framebufferName == 0)
2798 {
2799 return error(GL_INVALID_OPERATION);
2800 }
2801 break;
2802 case GL_DEPTH_STENCIL_ATTACHMENT:
2803 if(clientVersion < 3)
2804 {
2805 return error(GL_INVALID_ENUM);
2806 }
2807
2808 if(framebufferName == 0)
2809 {
2810 return error(GL_INVALID_OPERATION);
2811 }
2812 break;
2813 default:
2814 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2815 {
2816 if(framebufferName == 0)
2817 {
2818 return error(GL_INVALID_OPERATION);
2819 }
2820 }
2821 else return error(GL_INVALID_ENUM);
2822 }
2823
2824 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2825
2826 GLenum attachmentType;
2827 GLuint attachmentHandle;
2828 GLint attachmentLayer;
2829 Renderbuffer *renderbuffer = nullptr;
2830 switch(attachment)
2831 {
2832 case GL_BACK:
2833 attachmentType = framebuffer->getColorbufferType(0);
2834 attachmentHandle = framebuffer->getColorbufferName(0);
2835 attachmentLayer = framebuffer->getColorbufferLayer(0);
2836 renderbuffer = framebuffer->getColorbuffer(0);
2837 break;
2838 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002839 case GL_DEPTH_ATTACHMENT:
2840 attachmentType = framebuffer->getDepthbufferType();
2841 attachmentHandle = framebuffer->getDepthbufferName();
2842 attachmentLayer = framebuffer->getDepthbufferLayer();
2843 renderbuffer = framebuffer->getDepthbuffer();
2844 break;
2845 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002846 case GL_STENCIL_ATTACHMENT:
2847 attachmentType = framebuffer->getStencilbufferType();
2848 attachmentHandle = framebuffer->getStencilbufferName();
2849 attachmentLayer = framebuffer->getStencilbufferLayer();
2850 renderbuffer = framebuffer->getStencilbuffer();
2851 break;
2852 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002853 attachmentType = framebuffer->getDepthbufferType();
2854 attachmentHandle = framebuffer->getDepthbufferName();
2855 attachmentLayer = framebuffer->getDepthbufferLayer();
2856 renderbuffer = framebuffer->getDepthbuffer();
2857
2858 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002859 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002860 // Different attachments to DEPTH and STENCIL, query fails
2861 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002862 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002863 break;
2864 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002865 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2866 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2867 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2868 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2869 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2870 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002871 }
2872
2873 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002874 if(framebufferName == 0)
2875 {
2876 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2877 }
2878 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002879 {
2880 attachmentObjectType = attachmentType;
2881 }
2882 else if(es2::IsTextureTarget(attachmentType))
2883 {
2884 attachmentObjectType = GL_TEXTURE;
2885 }
2886 else UNREACHABLE(attachmentType);
2887
2888 if(attachmentObjectType != GL_NONE)
2889 {
2890 switch(pname)
2891 {
2892 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2893 *params = attachmentObjectType;
2894 break;
2895 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002896 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002897 {
2898 *params = attachmentHandle;
2899 }
2900 else
2901 {
2902 return error(GL_INVALID_ENUM);
2903 }
2904 break;
2905 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2906 if(attachmentObjectType == GL_TEXTURE)
2907 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002908 *params = clientVersion < 3 ? 0 : renderbuffer->getLevel(); // glFramebufferTexture2D does not allow level to be set to anything else in GL ES 2.0
Nicolas Capens0bac2852016-05-07 06:09:58 -04002909 }
2910 else
2911 {
2912 return error(GL_INVALID_ENUM);
2913 }
2914 break;
2915 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2916 if(attachmentObjectType == GL_TEXTURE)
2917 {
2918 if(es2::IsCubemapTextureTarget(attachmentType))
2919 {
2920 *params = attachmentType;
2921 }
2922 else
2923 {
2924 *params = 0;
2925 }
2926 }
2927 else
2928 {
2929 return error(GL_INVALID_ENUM);
2930 }
2931 break;
2932 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2933 if(clientVersion >= 3)
2934 {
2935 *params = attachmentLayer;
2936 }
2937 else return error(GL_INVALID_ENUM);
2938 break;
2939 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2940 if(clientVersion >= 3)
2941 {
2942 *params = renderbuffer->getRedSize();
2943 }
2944 else return error(GL_INVALID_ENUM);
2945 break;
2946 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2947 if(clientVersion >= 3)
2948 {
2949 *params = renderbuffer->getGreenSize();
2950 }
2951 else return error(GL_INVALID_ENUM);
2952 break;
2953 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2954 if(clientVersion >= 3)
2955 {
2956 *params = renderbuffer->getBlueSize();
2957 }
2958 else return error(GL_INVALID_ENUM);
2959 break;
2960 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2961 if(clientVersion >= 3)
2962 {
2963 *params = renderbuffer->getAlphaSize();
2964 }
2965 else return error(GL_INVALID_ENUM);
2966 break;
2967 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2968 if(clientVersion >= 3)
2969 {
2970 *params = renderbuffer->getDepthSize();
2971 }
2972 else return error(GL_INVALID_ENUM);
2973 break;
2974 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2975 if(clientVersion >= 3)
2976 {
2977 *params = renderbuffer->getStencilSize();
2978 }
2979 else return error(GL_INVALID_ENUM);
2980 break;
2981 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002982 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2983 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002984 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002985 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002986 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002987
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002988 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002989 break;
2990 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2991 if(clientVersion >= 3)
2992 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002993 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002994 }
2995 else return error(GL_INVALID_ENUM);
2996 break;
2997 default:
2998 return error(GL_INVALID_ENUM);
2999 }
3000 }
3001 else
3002 {
3003 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3004 // is NONE, then querying any other pname will generate INVALID_ENUM.
3005
3006 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3007 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3008 // INVALID_OPERATION for all other pnames
3009
3010 switch(pname)
3011 {
3012 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3013 *params = GL_NONE;
3014 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003015 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3016 if(clientVersion < 3)
3017 {
3018 return error(GL_INVALID_ENUM);
3019 }
3020 *params = 0;
3021 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003022 default:
3023 if(clientVersion < 3)
3024 {
3025 return error(GL_INVALID_ENUM);
3026 }
3027 else
3028 {
3029 return error(GL_INVALID_OPERATION);
3030 }
3031 }
3032 }
3033 }
3034}
3035
3036GLenum GetGraphicsResetStatusEXT(void)
3037{
3038 TRACE("()");
3039
3040 return GL_NO_ERROR;
3041}
3042
3043void GetIntegerv(GLenum pname, GLint* params)
3044{
3045 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
3046
3047 es2::Context *context = es2::getContext();
3048
3049 if(!context)
3050 {
3051 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
3052 #ifdef __ANDROID__
3053 ALOGI("expected_badness glGetIntegerv() called without current context.");
3054 #else
3055 ERR("glGetIntegerv() called without current context.");
3056 #endif
3057
3058 // This is not spec compliant! When there is no current GL context, functions should
3059 // have no side effects. Google Maps queries these values before creating a context,
3060 // so we need this as a bug-compatible workaround.
3061 switch(pname)
3062 {
3063 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3064 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3065 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3066 case GL_STENCIL_BITS: *params = 8; return;
3067 case GL_ALIASED_LINE_WIDTH_RANGE:
3068 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3069 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3070 return;
3071 }
3072 }
3073
3074 if(context)
3075 {
3076 if(!(context->getIntegerv(pname, params)))
3077 {
3078 GLenum nativeType;
3079 unsigned int numParams = 0;
3080 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3081 return error(GL_INVALID_ENUM);
3082
3083 if(numParams == 0)
3084 return; // it is known that pname is valid, but there are no parameters to return
3085
3086 if(nativeType == GL_BOOL)
3087 {
3088 GLboolean *boolParams = nullptr;
3089 boolParams = new GLboolean[numParams];
3090
3091 context->getBooleanv(pname, boolParams);
3092
3093 for(unsigned int i = 0; i < numParams; ++i)
3094 {
3095 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3096 }
3097
3098 delete [] boolParams;
3099 }
3100 else if(nativeType == GL_FLOAT)
3101 {
3102 GLfloat *floatParams = nullptr;
3103 floatParams = new GLfloat[numParams];
3104
3105 context->getFloatv(pname, floatParams);
3106
3107 for(unsigned int i = 0; i < numParams; ++i)
3108 {
3109 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3110 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003111 params[i] = convert_float_int(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003112 }
3113 else
3114 {
3115 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3116 }
3117 }
3118
3119 delete [] floatParams;
3120 }
3121 }
3122 }
3123}
3124
3125void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3126{
3127 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3128
3129 es2::Context *context = es2::getContext();
3130
3131 if(context)
3132 {
3133 es2::Program *programObject = context->getProgram(program);
3134
3135 if(!programObject)
3136 {
3137 if(context->getShader(program))
3138 {
3139 return error(GL_INVALID_OPERATION);
3140 }
3141 else
3142 {
3143 return error(GL_INVALID_VALUE);
3144 }
3145 }
3146
3147 GLint clientVersion = egl::getClientVersion();
3148
3149 switch(pname)
3150 {
3151 case GL_DELETE_STATUS:
3152 *params = programObject->isFlaggedForDeletion();
3153 return;
3154 case GL_LINK_STATUS:
3155 *params = programObject->isLinked();
3156 return;
3157 case GL_VALIDATE_STATUS:
3158 *params = programObject->isValidated();
3159 return;
3160 case GL_INFO_LOG_LENGTH:
3161 *params = (GLint)programObject->getInfoLogLength();
3162 return;
3163 case GL_ATTACHED_SHADERS:
3164 *params = programObject->getAttachedShadersCount();
3165 return;
3166 case GL_ACTIVE_ATTRIBUTES:
3167 *params = (GLint)programObject->getActiveAttributeCount();
3168 return;
3169 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3170 *params = programObject->getActiveAttributeMaxLength();
3171 return;
3172 case GL_ACTIVE_UNIFORMS:
3173 *params = (GLint)programObject->getActiveUniformCount();
3174 return;
3175 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3176 *params = programObject->getActiveUniformMaxLength();
3177 return;
3178 case GL_ACTIVE_UNIFORM_BLOCKS:
3179 if(clientVersion >= 3)
3180 {
3181 *params = (GLint)programObject->getActiveUniformBlockCount();
3182 return;
3183 }
3184 else return error(GL_INVALID_ENUM);
3185 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3186 if(clientVersion >= 3)
3187 {
3188 *params = programObject->getActiveUniformBlockMaxLength();
3189 return;
3190 }
3191 else return error(GL_INVALID_ENUM);
3192 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3193 if(clientVersion >= 3)
3194 {
3195 *params = programObject->getTransformFeedbackBufferMode();
3196 return;
3197 }
3198 else return error(GL_INVALID_ENUM);
3199 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3200 if(clientVersion >= 3)
3201 {
3202 *params = programObject->getTransformFeedbackVaryingCount();
3203 return;
3204 }
3205 else return error(GL_INVALID_ENUM);
3206 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3207 if(clientVersion >= 3)
3208 {
3209 *params = programObject->getTransformFeedbackVaryingMaxLength();
3210 return;
3211 }
3212 else return error(GL_INVALID_ENUM);
3213 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3214 if(clientVersion >= 3)
3215 {
3216 *params = programObject->getBinaryRetrievableHint();
3217 return;
3218 }
3219 else return error(GL_INVALID_ENUM);
3220 case GL_PROGRAM_BINARY_LENGTH:
3221 if(clientVersion >= 3)
3222 {
3223 *params = programObject->getBinaryLength();
3224 return;
3225 }
3226 else return error(GL_INVALID_ENUM);
3227 default:
3228 return error(GL_INVALID_ENUM);
3229 }
3230 }
3231}
3232
3233void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3234{
3235 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3236 program, bufsize, length, infolog);
3237
3238 if(bufsize < 0)
3239 {
3240 return error(GL_INVALID_VALUE);
3241 }
3242
3243 es2::Context *context = es2::getContext();
3244
3245 if(context)
3246 {
3247 es2::Program *programObject = context->getProgram(program);
3248
3249 if(!programObject)
3250 {
3251 if(context->getShader(program))
3252 {
3253 return error(GL_INVALID_OPERATION);
3254 }
3255 else
3256 {
3257 return error(GL_INVALID_VALUE);
3258 }
3259 }
3260
3261 programObject->getInfoLog(bufsize, length, infolog);
3262 }
3263}
3264
3265void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3266{
3267 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3268
3269 switch(pname)
3270 {
3271 case GL_CURRENT_QUERY_EXT:
3272 break;
3273 default:
3274 return error(GL_INVALID_ENUM);
3275 }
3276
3277 es2::Context *context = es2::getContext();
3278
3279 if(context)
3280 {
3281 params[0] = context->getActiveQuery(target);
3282 }
3283}
3284
3285void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3286{
3287 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3288
3289 switch(pname)
3290 {
3291 case GL_QUERY_RESULT_EXT:
3292 case GL_QUERY_RESULT_AVAILABLE_EXT:
3293 break;
3294 default:
3295 return error(GL_INVALID_ENUM);
3296 }
3297
3298 es2::Context *context = es2::getContext();
3299
3300 if(context)
3301 {
3302 es2::Query *queryObject = context->getQuery(name);
3303
3304 if(!queryObject)
3305 {
3306 return error(GL_INVALID_OPERATION);
3307 }
3308
3309 if(context->getActiveQuery(queryObject->getType()) == name)
3310 {
3311 return error(GL_INVALID_OPERATION);
3312 }
3313
3314 switch(pname)
3315 {
3316 case GL_QUERY_RESULT_EXT:
3317 params[0] = queryObject->getResult();
3318 break;
3319 case GL_QUERY_RESULT_AVAILABLE_EXT:
3320 params[0] = queryObject->isResultAvailable();
3321 break;
3322 default:
3323 ASSERT(false);
3324 }
3325 }
3326}
3327
3328void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3329{
3330 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3331
3332 es2::Context *context = es2::getContext();
3333
3334 if(context)
3335 {
3336 if(target != GL_RENDERBUFFER)
3337 {
3338 return error(GL_INVALID_ENUM);
3339 }
3340
3341 if(context->getRenderbufferName() == 0)
3342 {
3343 return error(GL_INVALID_OPERATION);
3344 }
3345
3346 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3347
3348 switch(pname)
3349 {
3350 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3351 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
3352 case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat(); break;
3353 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3354 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3355 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3356 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3357 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3358 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
3359 case GL_RENDERBUFFER_SAMPLES_ANGLE: *params = renderbuffer->getSamples(); break;
3360 default:
3361 return error(GL_INVALID_ENUM);
3362 }
3363 }
3364}
3365
3366void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3367{
3368 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3369
3370 es2::Context *context = es2::getContext();
3371
3372 if(context)
3373 {
3374 es2::Shader *shaderObject = context->getShader(shader);
3375
3376 if(!shaderObject)
3377 {
3378 if(context->getProgram(shader))
3379 {
3380 return error(GL_INVALID_OPERATION);
3381 }
3382 else
3383 {
3384 return error(GL_INVALID_VALUE);
3385 }
3386 }
3387
3388 switch(pname)
3389 {
3390 case GL_SHADER_TYPE:
3391 *params = shaderObject->getType();
3392 return;
3393 case GL_DELETE_STATUS:
3394 *params = shaderObject->isFlaggedForDeletion();
3395 return;
3396 case GL_COMPILE_STATUS:
3397 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3398 return;
3399 case GL_INFO_LOG_LENGTH:
3400 *params = (GLint)shaderObject->getInfoLogLength();
3401 return;
3402 case GL_SHADER_SOURCE_LENGTH:
3403 *params = (GLint)shaderObject->getSourceLength();
3404 return;
3405 default:
3406 return error(GL_INVALID_ENUM);
3407 }
3408 }
3409}
3410
3411void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3412{
3413 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3414 shader, bufsize, length, infolog);
3415
3416 if(bufsize < 0)
3417 {
3418 return error(GL_INVALID_VALUE);
3419 }
3420
3421 es2::Context *context = es2::getContext();
3422
3423 if(context)
3424 {
3425 es2::Shader *shaderObject = context->getShader(shader);
3426
3427 if(!shaderObject)
3428 {
3429 if(context->getProgram(shader))
3430 {
3431 return error(GL_INVALID_OPERATION);
3432 }
3433 else
3434 {
3435 return error(GL_INVALID_VALUE);
3436 }
3437 }
3438
3439 shaderObject->getInfoLog(bufsize, length, infolog);
3440 }
3441}
3442
3443void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3444{
3445 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3446 shadertype, precisiontype, range, precision);
3447
3448 switch(shadertype)
3449 {
3450 case GL_VERTEX_SHADER:
3451 case GL_FRAGMENT_SHADER:
3452 break;
3453 default:
3454 return error(GL_INVALID_ENUM);
3455 }
3456
3457 switch(precisiontype)
3458 {
3459 case GL_LOW_FLOAT:
3460 case GL_MEDIUM_FLOAT:
3461 case GL_HIGH_FLOAT:
3462 // IEEE 754 single-precision
3463 range[0] = 127;
3464 range[1] = 127;
3465 *precision = 23;
3466 break;
3467 case GL_LOW_INT:
3468 case GL_MEDIUM_INT:
3469 case GL_HIGH_INT:
3470 // Full integer precision is supported
3471 range[0] = 31;
3472 range[1] = 30;
3473 *precision = 0;
3474 break;
3475 default:
3476 return error(GL_INVALID_ENUM);
3477 }
3478}
3479
3480void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3481{
3482 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3483 shader, bufsize, length, source);
3484
3485 if(bufsize < 0)
3486 {
3487 return error(GL_INVALID_VALUE);
3488 }
3489
3490 es2::Context *context = es2::getContext();
3491
3492 if(context)
3493 {
3494 es2::Shader *shaderObject = context->getShader(shader);
3495
3496 if(!shaderObject)
3497 {
3498 if(context->getProgram(shader))
3499 {
3500 return error(GL_INVALID_OPERATION);
3501 }
3502 else
3503 {
3504 return error(GL_INVALID_VALUE);
3505 }
3506 }
3507
3508 shaderObject->getSource(bufsize, length, source);
3509 }
3510}
3511
3512const GLubyte* GetString(GLenum name)
3513{
3514 TRACE("(GLenum name = 0x%X)", name);
3515
3516 switch(name)
3517 {
3518 case GL_VENDOR:
3519 return (GLubyte*)"Google Inc.";
3520 case GL_RENDERER:
3521 return (GLubyte*)"Google SwiftShader";
3522 case GL_VERSION:
3523 {
3524 es2::Context *context = es2::getContext();
3525 return (context && (context->getClientVersion() >= 3)) ?
3526 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3527 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3528 }
3529 case GL_SHADING_LANGUAGE_VERSION:
3530 {
3531 es2::Context *context = es2::getContext();
3532 return (context && (context->getClientVersion() >= 3)) ?
3533 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3534 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3535 }
3536 case GL_EXTENSIONS:
3537 {
3538 es2::Context *context = es2::getContext();
3539 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3540 }
3541 default:
3542 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3543 }
3544}
3545
3546void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3547{
3548 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3549
3550 es2::Context *context = es2::getContext();
3551
3552 if(context)
3553 {
3554 es2::Texture *texture;
3555
3556 GLint clientVersion = context->getClientVersion();
3557
3558 switch(target)
3559 {
3560 case GL_TEXTURE_2D:
3561 texture = context->getTexture2D();
3562 break;
3563 case GL_TEXTURE_CUBE_MAP:
3564 texture = context->getTextureCubeMap();
3565 break;
3566 case GL_TEXTURE_EXTERNAL_OES:
3567 texture = context->getTextureExternal();
3568 break;
3569 case GL_TEXTURE_2D_ARRAY:
3570 if(clientVersion < 3)
3571 {
3572 return error(GL_INVALID_ENUM);
3573 }
3574 else
3575 {
3576 texture = context->getTexture2DArray();
3577 }
3578 break;
3579 case GL_TEXTURE_3D_OES:
3580 texture = context->getTexture3D();
3581 break;
3582 default:
3583 return error(GL_INVALID_ENUM);
3584 }
3585
3586 switch(pname)
3587 {
3588 case GL_TEXTURE_MAG_FILTER:
3589 *params = (GLfloat)texture->getMagFilter();
3590 break;
3591 case GL_TEXTURE_MIN_FILTER:
3592 *params = (GLfloat)texture->getMinFilter();
3593 break;
3594 case GL_TEXTURE_WRAP_S:
3595 *params = (GLfloat)texture->getWrapS();
3596 break;
3597 case GL_TEXTURE_WRAP_T:
3598 *params = (GLfloat)texture->getWrapT();
3599 break;
3600 case GL_TEXTURE_WRAP_R_OES:
3601 *params = (GLfloat)texture->getWrapR();
3602 break;
3603 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3604 *params = texture->getMaxAnisotropy();
3605 break;
3606 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3607 *params = (GLfloat)1;
3608 break;
3609 case GL_TEXTURE_BASE_LEVEL:
3610 if(clientVersion >= 3)
3611 {
3612 *params = (GLfloat)texture->getBaseLevel();
3613 break;
3614 }
3615 else return error(GL_INVALID_ENUM);
3616 case GL_TEXTURE_COMPARE_FUNC:
3617 if(clientVersion >= 3)
3618 {
3619 *params = (GLfloat)texture->getCompareFunc();
3620 break;
3621 }
3622 else return error(GL_INVALID_ENUM);
3623 case GL_TEXTURE_COMPARE_MODE:
3624 if(clientVersion >= 3)
3625 {
3626 *params = (GLfloat)texture->getCompareMode();
3627 break;
3628 }
3629 else return error(GL_INVALID_ENUM);
3630 case GL_TEXTURE_IMMUTABLE_FORMAT:
3631 if(clientVersion >= 3)
3632 {
3633 *params = (GLfloat)texture->getImmutableFormat();
3634 break;
3635 }
3636 else return error(GL_INVALID_ENUM);
3637 case GL_TEXTURE_IMMUTABLE_LEVELS:
3638 if(clientVersion >= 3)
3639 {
3640 *params = (GLfloat)texture->getImmutableLevels();
3641 break;
3642 }
3643 else return error(GL_INVALID_ENUM);
3644 case GL_TEXTURE_MAX_LEVEL:
3645 if(clientVersion >= 3)
3646 {
3647 *params = (GLfloat)texture->getMaxLevel();
3648 break;
3649 }
3650 else return error(GL_INVALID_ENUM);
3651 case GL_TEXTURE_MAX_LOD:
3652 if(clientVersion >= 3)
3653 {
3654 *params = texture->getMaxLOD();
3655 break;
3656 }
3657 else return error(GL_INVALID_ENUM);
3658 case GL_TEXTURE_MIN_LOD:
3659 if(clientVersion >= 3)
3660 {
3661 *params = texture->getMinLOD();
3662 break;
3663 }
3664 else return error(GL_INVALID_ENUM);
3665 case GL_TEXTURE_SWIZZLE_R:
3666 if(clientVersion >= 3)
3667 {
3668 *params = (GLfloat)texture->getSwizzleR();
3669 break;
3670 }
3671 else return error(GL_INVALID_ENUM);
3672 case GL_TEXTURE_SWIZZLE_G:
3673 if(clientVersion >= 3)
3674 {
3675 *params = (GLfloat)texture->getSwizzleG();
3676 break;
3677 }
3678 else return error(GL_INVALID_ENUM);
3679 case GL_TEXTURE_SWIZZLE_B:
3680 if(clientVersion >= 3)
3681 {
3682 *params = (GLfloat)texture->getSwizzleB();
3683 break;
3684 }
3685 else return error(GL_INVALID_ENUM);
3686 case GL_TEXTURE_SWIZZLE_A:
3687 if(clientVersion >= 3)
3688 {
3689 *params = (GLfloat)texture->getSwizzleA();
3690 break;
3691 }
3692 else return error(GL_INVALID_ENUM);
3693 default:
3694 return error(GL_INVALID_ENUM);
3695 }
3696 }
3697}
3698
3699void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3700{
3701 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3702
3703 es2::Context *context = es2::getContext();
3704
3705 if(context)
3706 {
3707 es2::Texture *texture;
3708
3709 GLint clientVersion = context->getClientVersion();
3710
3711 switch(target)
3712 {
3713 case GL_TEXTURE_2D:
3714 texture = context->getTexture2D();
3715 break;
3716 case GL_TEXTURE_CUBE_MAP:
3717 texture = context->getTextureCubeMap();
3718 break;
3719 case GL_TEXTURE_EXTERNAL_OES:
3720 texture = context->getTextureExternal();
3721 break;
3722 case GL_TEXTURE_2D_ARRAY:
3723 if(clientVersion < 3)
3724 {
3725 return error(GL_INVALID_ENUM);
3726 }
3727 else
3728 {
3729 texture = context->getTexture2DArray();
3730 }
3731 break;
3732 case GL_TEXTURE_3D_OES:
3733 texture = context->getTexture3D();
3734 break;
3735 default:
3736 return error(GL_INVALID_ENUM);
3737 }
3738
3739 switch(pname)
3740 {
3741 case GL_TEXTURE_MAG_FILTER:
3742 *params = texture->getMagFilter();
3743 break;
3744 case GL_TEXTURE_MIN_FILTER:
3745 *params = texture->getMinFilter();
3746 break;
3747 case GL_TEXTURE_WRAP_S:
3748 *params = texture->getWrapS();
3749 break;
3750 case GL_TEXTURE_WRAP_T:
3751 *params = texture->getWrapT();
3752 break;
3753 case GL_TEXTURE_WRAP_R_OES:
3754 *params = texture->getWrapR();
3755 break;
3756 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3757 *params = (GLint)texture->getMaxAnisotropy();
3758 break;
3759 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3760 *params = 1;
3761 break;
3762 case GL_TEXTURE_BASE_LEVEL:
3763 if(clientVersion >= 3)
3764 {
3765 *params = texture->getBaseLevel();
3766 break;
3767 }
3768 else return error(GL_INVALID_ENUM);
3769 case GL_TEXTURE_COMPARE_FUNC:
3770 if(clientVersion >= 3)
3771 {
3772 *params = (GLint)texture->getCompareFunc();
3773 break;
3774 }
3775 else return error(GL_INVALID_ENUM);
3776 case GL_TEXTURE_COMPARE_MODE:
3777 if(clientVersion >= 3)
3778 {
3779 *params = (GLint)texture->getCompareMode();
3780 break;
3781 }
3782 else return error(GL_INVALID_ENUM);
3783 case GL_TEXTURE_IMMUTABLE_FORMAT:
3784 if(clientVersion >= 3)
3785 {
3786 *params = (GLint)texture->getImmutableFormat();
3787 break;
3788 }
3789 else return error(GL_INVALID_ENUM);
3790 case GL_TEXTURE_IMMUTABLE_LEVELS:
3791 if(clientVersion >= 3)
3792 {
3793 *params = (GLint)texture->getImmutableLevels();
3794 break;
3795 }
3796 else return error(GL_INVALID_ENUM);
3797 case GL_TEXTURE_MAX_LEVEL:
3798 if(clientVersion >= 3)
3799 {
3800 *params = texture->getMaxLevel();
3801 break;
3802 }
3803 else return error(GL_INVALID_ENUM);
3804 case GL_TEXTURE_MAX_LOD:
3805 if(clientVersion >= 3)
3806 {
3807 *params = (GLint)roundf(texture->getMaxLOD());
3808 break;
3809 }
3810 else return error(GL_INVALID_ENUM);
3811 case GL_TEXTURE_MIN_LOD:
3812 if(clientVersion >= 3)
3813 {
3814 *params = (GLint)roundf(texture->getMinLOD());
3815 break;
3816 }
3817 else return error(GL_INVALID_ENUM);
3818 case GL_TEXTURE_SWIZZLE_R:
3819 if(clientVersion >= 3)
3820 {
3821 *params = (GLint)texture->getSwizzleR();
3822 break;
3823 }
3824 else return error(GL_INVALID_ENUM);
3825 case GL_TEXTURE_SWIZZLE_G:
3826 if(clientVersion >= 3)
3827 {
3828 *params = (GLint)texture->getSwizzleG();
3829 break;
3830 }
3831 else return error(GL_INVALID_ENUM);
3832 case GL_TEXTURE_SWIZZLE_B:
3833 if(clientVersion >= 3)
3834 {
3835 *params = (GLint)texture->getSwizzleB();
3836 break;
3837 }
3838 else return error(GL_INVALID_ENUM);
3839 case GL_TEXTURE_SWIZZLE_A:
3840 if(clientVersion >= 3)
3841 {
3842 *params = (GLint)texture->getSwizzleA();
3843 break;
3844 }
3845 else return error(GL_INVALID_ENUM);
3846 default:
3847 return error(GL_INVALID_ENUM);
3848 }
3849 }
3850}
3851
3852void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3853{
3854 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3855 program, location, bufSize, params);
3856
3857 if(bufSize < 0)
3858 {
3859 return error(GL_INVALID_VALUE);
3860 }
3861
3862 es2::Context *context = es2::getContext();
3863
3864 if(context)
3865 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003866 es2::Program *programObject = context->getProgram(program);
3867
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003868 if(!programObject)
3869 {
3870 if(context->getShader(program))
3871 {
3872 return error(GL_INVALID_OPERATION);
3873 }
3874 else
3875 {
3876 return error(GL_INVALID_VALUE);
3877 }
3878 }
3879
3880 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003881 {
3882 return error(GL_INVALID_OPERATION);
3883 }
3884
3885 if(!programObject->getUniformfv(location, &bufSize, params))
3886 {
3887 return error(GL_INVALID_OPERATION);
3888 }
3889 }
3890}
3891
3892void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3893{
3894 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3895
3896 es2::Context *context = es2::getContext();
3897
3898 if(context)
3899 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003900 es2::Program *programObject = context->getProgram(program);
3901
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003902 if(!programObject)
3903 {
3904 if(context->getShader(program))
3905 {
3906 return error(GL_INVALID_OPERATION);
3907 }
3908 else
3909 {
3910 return error(GL_INVALID_VALUE);
3911 }
3912 }
3913
3914 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003915 {
3916 return error(GL_INVALID_OPERATION);
3917 }
3918
3919 if(!programObject->getUniformfv(location, nullptr, params))
3920 {
3921 return error(GL_INVALID_OPERATION);
3922 }
3923 }
3924}
3925
3926void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3927{
3928 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3929 program, location, bufSize, params);
3930
3931 if(bufSize < 0)
3932 {
3933 return error(GL_INVALID_VALUE);
3934 }
3935
3936 es2::Context *context = es2::getContext();
3937
3938 if(context)
3939 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003940 es2::Program *programObject = context->getProgram(program);
3941
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003942 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003943 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003944 if(context->getShader(program))
3945 {
3946 return error(GL_INVALID_OPERATION);
3947 }
3948 else
3949 {
3950 return error(GL_INVALID_VALUE);
3951 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003952 }
3953
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003954 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003955 {
3956 return error(GL_INVALID_OPERATION);
3957 }
3958
3959 if(!programObject->getUniformiv(location, &bufSize, params))
3960 {
3961 return error(GL_INVALID_OPERATION);
3962 }
3963 }
3964}
3965
3966void GetUniformiv(GLuint program, GLint location, GLint* params)
3967{
3968 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3969
3970 es2::Context *context = es2::getContext();
3971
3972 if(context)
3973 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003974 es2::Program *programObject = context->getProgram(program);
3975
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003976 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003977 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003978 if(context->getShader(program))
3979 {
3980 return error(GL_INVALID_OPERATION);
3981 }
3982 else
3983 {
3984 return error(GL_INVALID_VALUE);
3985 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003986 }
3987
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003988 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003989 {
3990 return error(GL_INVALID_OPERATION);
3991 }
3992
3993 if(!programObject->getUniformiv(location, nullptr, params))
3994 {
3995 return error(GL_INVALID_OPERATION);
3996 }
3997 }
3998}
3999
4000int GetUniformLocation(GLuint program, const GLchar* name)
4001{
4002 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
4003
4004 es2::Context *context = es2::getContext();
4005
4006 if(strstr(name, "gl_") == name)
4007 {
4008 return -1;
4009 }
4010
4011 if(context)
4012 {
4013 es2::Program *programObject = context->getProgram(program);
4014
4015 if(!programObject)
4016 {
4017 if(context->getShader(program))
4018 {
4019 return error(GL_INVALID_OPERATION, -1);
4020 }
4021 else
4022 {
4023 return error(GL_INVALID_VALUE, -1);
4024 }
4025 }
4026
4027 if(!programObject->isLinked())
4028 {
4029 return error(GL_INVALID_OPERATION, -1);
4030 }
4031
4032 return programObject->getUniformLocation(name);
4033 }
4034
4035 return -1;
4036}
4037
4038void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
4039{
4040 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
4041
4042 es2::Context *context = es2::getContext();
4043
4044 if(context)
4045 {
4046 if(index >= es2::MAX_VERTEX_ATTRIBS)
4047 {
4048 return error(GL_INVALID_VALUE);
4049 }
4050
4051 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4052
4053 GLint clientVersion = context->getClientVersion();
4054
4055 switch(pname)
4056 {
4057 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4058 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4059 break;
4060 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4061 *params = (GLfloat)attribState.mSize;
4062 break;
4063 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4064 *params = (GLfloat)attribState.mStride;
4065 break;
4066 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4067 *params = (GLfloat)attribState.mType;
4068 break;
4069 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4070 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4071 break;
4072 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4073 *params = (GLfloat)attribState.mBoundBuffer.name();
4074 break;
4075 case GL_CURRENT_VERTEX_ATTRIB:
4076 {
4077 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4078 for(int i = 0; i < 4; ++i)
4079 {
4080 params[i] = attrib.getCurrentValueF(i);
4081 }
4082 }
4083 break;
4084 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4085 if(clientVersion >= 3)
4086 {
4087 switch(attribState.mType)
4088 {
4089 case GL_BYTE:
4090 case GL_UNSIGNED_BYTE:
4091 case GL_SHORT:
4092 case GL_UNSIGNED_SHORT:
4093 case GL_INT:
4094 case GL_INT_2_10_10_10_REV:
4095 case GL_UNSIGNED_INT:
4096 case GL_FIXED:
4097 *params = (GLfloat)GL_TRUE;
4098 break;
4099 default:
4100 *params = (GLfloat)GL_FALSE;
4101 break;
4102 }
4103 break;
4104 }
4105 else return error(GL_INVALID_ENUM);
4106 default: return error(GL_INVALID_ENUM);
4107 }
4108 }
4109}
4110
4111void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4112{
4113 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4114
4115 es2::Context *context = es2::getContext();
4116
4117 if(context)
4118 {
4119 if(index >= es2::MAX_VERTEX_ATTRIBS)
4120 {
4121 return error(GL_INVALID_VALUE);
4122 }
4123
4124 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4125
4126 GLint clientVersion = context->getClientVersion();
4127
4128 switch(pname)
4129 {
4130 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4131 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4132 break;
4133 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4134 *params = attribState.mSize;
4135 break;
4136 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4137 *params = attribState.mStride;
4138 break;
4139 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4140 *params = attribState.mType;
4141 break;
4142 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4143 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4144 break;
4145 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4146 *params = attribState.mBoundBuffer.name();
4147 break;
4148 case GL_CURRENT_VERTEX_ATTRIB:
4149 {
4150 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4151 for(int i = 0; i < 4; ++i)
4152 {
4153 float currentValue = attrib.getCurrentValueF(i);
4154 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4155 }
4156 }
4157 break;
4158 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4159 if(clientVersion >= 3)
4160 {
4161 switch(attribState.mType)
4162 {
4163 case GL_BYTE:
4164 case GL_UNSIGNED_BYTE:
4165 case GL_SHORT:
4166 case GL_UNSIGNED_SHORT:
4167 case GL_INT:
4168 case GL_INT_2_10_10_10_REV:
4169 case GL_UNSIGNED_INT:
4170 case GL_FIXED:
4171 *params = GL_TRUE;
4172 break;
4173 default:
4174 *params = GL_FALSE;
4175 break;
4176 }
4177 break;
4178 }
4179 else return error(GL_INVALID_ENUM);
4180 default: return error(GL_INVALID_ENUM);
4181 }
4182 }
4183}
4184
4185void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4186{
4187 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4188
4189 es2::Context *context = es2::getContext();
4190
4191 if(context)
4192 {
4193 if(index >= es2::MAX_VERTEX_ATTRIBS)
4194 {
4195 return error(GL_INVALID_VALUE);
4196 }
4197
4198 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4199 {
4200 return error(GL_INVALID_ENUM);
4201 }
4202
4203 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4204 }
4205}
4206
4207void Hint(GLenum target, GLenum mode)
4208{
4209 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4210
4211 switch(mode)
4212 {
4213 case GL_FASTEST:
4214 case GL_NICEST:
4215 case GL_DONT_CARE:
4216 break;
4217 default:
4218 return error(GL_INVALID_ENUM);
4219 }
4220
4221 es2::Context *context = es2::getContext();
4222 switch(target)
4223 {
4224 case GL_GENERATE_MIPMAP_HINT:
4225 if(context) context->setGenerateMipmapHint(mode);
4226 break;
4227 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4228 if(context) context->setFragmentShaderDerivativeHint(mode);
4229 break;
Alexis Hetu010a4642017-07-18 14:33:04 -04004230 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4231 if(context) context->setTextureFilteringHint(mode);
4232 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004233 default:
4234 return error(GL_INVALID_ENUM);
4235 }
4236}
4237
4238GLboolean IsBuffer(GLuint buffer)
4239{
4240 TRACE("(GLuint buffer = %d)", buffer);
4241
4242 es2::Context *context = es2::getContext();
4243
4244 if(context && buffer)
4245 {
4246 es2::Buffer *bufferObject = context->getBuffer(buffer);
4247
4248 if(bufferObject)
4249 {
4250 return GL_TRUE;
4251 }
4252 }
4253
4254 return GL_FALSE;
4255}
4256
4257GLboolean IsEnabled(GLenum cap)
4258{
4259 TRACE("(GLenum cap = 0x%X)", cap);
4260
4261 es2::Context *context = es2::getContext();
4262
4263 if(context)
4264 {
4265 GLint clientVersion = context->getClientVersion();
4266
4267 switch(cap)
4268 {
4269 case GL_CULL_FACE: return context->isCullFaceEnabled();
4270 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4271 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4272 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4273 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4274 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4275 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4276 case GL_BLEND: return context->isBlendEnabled();
4277 case GL_DITHER: return context->isDitherEnabled();
4278 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4279 if(clientVersion >= 3)
4280 {
4281 return context->isPrimitiveRestartFixedIndexEnabled();
4282 }
4283 else return error(GL_INVALID_ENUM, false);
4284 case GL_RASTERIZER_DISCARD:
4285 if(clientVersion >= 3)
4286 {
4287 return context->isRasterizerDiscardEnabled();
4288 }
4289 else return error(GL_INVALID_ENUM, false);
4290 default:
4291 return error(GL_INVALID_ENUM, false);
4292 }
4293 }
4294
4295 return false;
4296}
4297
4298GLboolean IsFenceNV(GLuint fence)
4299{
4300 TRACE("(GLuint fence = %d)", fence);
4301
4302 es2::Context *context = es2::getContext();
4303
4304 if(context)
4305 {
4306 es2::Fence *fenceObject = context->getFence(fence);
4307
4308 if(!fenceObject)
4309 {
4310 return GL_FALSE;
4311 }
4312
4313 return fenceObject->isFence();
4314 }
4315
4316 return GL_FALSE;
4317}
4318
4319GLboolean IsFramebuffer(GLuint framebuffer)
4320{
4321 TRACE("(GLuint framebuffer = %d)", framebuffer);
4322
4323 es2::Context *context = es2::getContext();
4324
4325 if(context && framebuffer)
4326 {
4327 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4328
4329 if(framebufferObject)
4330 {
4331 return GL_TRUE;
4332 }
4333 }
4334
4335 return GL_FALSE;
4336}
4337
4338GLboolean IsProgram(GLuint program)
4339{
4340 TRACE("(GLuint program = %d)", program);
4341
4342 es2::Context *context = es2::getContext();
4343
4344 if(context && program)
4345 {
4346 es2::Program *programObject = context->getProgram(program);
4347
4348 if(programObject)
4349 {
4350 return GL_TRUE;
4351 }
4352 }
4353
4354 return GL_FALSE;
4355}
4356
4357GLboolean IsQueryEXT(GLuint name)
4358{
4359 TRACE("(GLuint name = %d)", name);
4360
4361 if(name == 0)
4362 {
4363 return GL_FALSE;
4364 }
4365
4366 es2::Context *context = es2::getContext();
4367
4368 if(context)
4369 {
4370 es2::Query *queryObject = context->getQuery(name);
4371
4372 if(queryObject)
4373 {
4374 return GL_TRUE;
4375 }
4376 }
4377
4378 return GL_FALSE;
4379}
4380
4381GLboolean IsRenderbuffer(GLuint renderbuffer)
4382{
4383 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4384
4385 es2::Context *context = es2::getContext();
4386
4387 if(context && renderbuffer)
4388 {
4389 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4390
4391 if(renderbufferObject)
4392 {
4393 return GL_TRUE;
4394 }
4395 }
4396
4397 return GL_FALSE;
4398}
4399
4400GLboolean IsShader(GLuint shader)
4401{
4402 TRACE("(GLuint shader = %d)", shader);
4403
4404 es2::Context *context = es2::getContext();
4405
4406 if(context && shader)
4407 {
4408 es2::Shader *shaderObject = context->getShader(shader);
4409
4410 if(shaderObject)
4411 {
4412 return GL_TRUE;
4413 }
4414 }
4415
4416 return GL_FALSE;
4417}
4418
4419GLboolean IsTexture(GLuint texture)
4420{
4421 TRACE("(GLuint texture = %d)", texture);
4422
4423 es2::Context *context = es2::getContext();
4424
4425 if(context && texture)
4426 {
4427 es2::Texture *textureObject = context->getTexture(texture);
4428
4429 if(textureObject)
4430 {
4431 return GL_TRUE;
4432 }
4433 }
4434
4435 return GL_FALSE;
4436}
4437
4438void LineWidth(GLfloat width)
4439{
4440 TRACE("(GLfloat width = %f)", width);
4441
4442 if(width <= 0.0f)
4443 {
4444 return error(GL_INVALID_VALUE);
4445 }
4446
4447 es2::Context *context = es2::getContext();
4448
4449 if(context)
4450 {
4451 context->setLineWidth(width);
4452 }
4453}
4454
4455void LinkProgram(GLuint program)
4456{
4457 TRACE("(GLuint program = %d)", program);
4458
4459 es2::Context *context = es2::getContext();
4460
4461 if(context)
4462 {
4463 es2::Program *programObject = context->getProgram(program);
4464
4465 if(!programObject)
4466 {
4467 if(context->getShader(program))
4468 {
4469 return error(GL_INVALID_OPERATION);
4470 }
4471 else
4472 {
4473 return error(GL_INVALID_VALUE);
4474 }
4475 }
4476
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004477 if(programObject == context->getCurrentProgram())
4478 {
4479 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4480 if(transformFeedback && transformFeedback->isActive())
4481 {
4482 return error(GL_INVALID_OPERATION);
4483 }
4484 }
4485
Nicolas Capens0bac2852016-05-07 06:09:58 -04004486 programObject->link();
4487 }
4488}
4489
4490void PixelStorei(GLenum pname, GLint param)
4491{
4492 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4493
4494 es2::Context *context = es2::getContext();
4495
4496 if(context)
4497 {
4498 GLint clientVersion = context->getClientVersion();
4499
4500 switch(pname)
4501 {
4502 case GL_UNPACK_ALIGNMENT:
4503 if(param != 1 && param != 2 && param != 4 && param != 8)
4504 {
4505 return error(GL_INVALID_VALUE);
4506 }
4507 context->setUnpackAlignment(param);
4508 break;
4509 case GL_PACK_ALIGNMENT:
4510 if(param != 1 && param != 2 && param != 4 && param != 8)
4511 {
4512 return error(GL_INVALID_VALUE);
4513 }
4514 context->setPackAlignment(param);
4515 break;
4516 case GL_PACK_ROW_LENGTH:
4517 if(clientVersion >= 3)
4518 {
4519 if(param < 0)
4520 {
4521 return error(GL_INVALID_VALUE);
4522 }
4523 context->setPackRowLength(param);
4524 break;
4525 }
4526 else return error(GL_INVALID_ENUM);
4527 case GL_PACK_SKIP_PIXELS:
4528 if(clientVersion >= 3)
4529 {
4530 if(param < 0)
4531 {
4532 return error(GL_INVALID_VALUE);
4533 }
4534 context->setPackSkipPixels(param);
4535 break;
4536 }
4537 else return error(GL_INVALID_ENUM);
4538 case GL_PACK_SKIP_ROWS:
4539 if(clientVersion >= 3)
4540 {
4541 if(param < 0)
4542 {
4543 return error(GL_INVALID_VALUE);
4544 }
4545 context->setPackSkipRows(param);
4546 break;
4547 }
4548 else return error(GL_INVALID_ENUM);
4549 case GL_UNPACK_ROW_LENGTH:
4550 if(clientVersion >= 3)
4551 {
4552 if(param < 0)
4553 {
4554 return error(GL_INVALID_VALUE);
4555 }
4556 context->setUnpackRowLength(param);
4557 break;
4558 }
4559 else return error(GL_INVALID_ENUM);
4560 case GL_UNPACK_IMAGE_HEIGHT:
4561 if(clientVersion >= 3)
4562 {
4563 if(param < 0)
4564 {
4565 return error(GL_INVALID_VALUE);
4566 }
4567 context->setUnpackImageHeight(param);
4568 break;
4569 }
4570 else return error(GL_INVALID_ENUM);
4571 case GL_UNPACK_SKIP_PIXELS:
4572 if(clientVersion >= 3)
4573 {
4574 if(param < 0)
4575 {
4576 return error(GL_INVALID_VALUE);
4577 }
4578 context->setUnpackSkipPixels(param);
4579 break;
4580 }
4581 else return error(GL_INVALID_ENUM);
4582 case GL_UNPACK_SKIP_ROWS:
4583 if(clientVersion >= 3)
4584 {
4585 if(param < 0)
4586 {
4587 return error(GL_INVALID_VALUE);
4588 }
4589 context->setUnpackSkipRows(param);
4590 break;
4591 }
4592 else return error(GL_INVALID_ENUM);
4593 case GL_UNPACK_SKIP_IMAGES:
4594 if(clientVersion >= 3) {
4595 if(param < 0)
4596 {
4597 return error(GL_INVALID_VALUE);
4598 }
4599 context->setUnpackSkipImages(param);
4600 break;
4601 }
4602 else return error(GL_INVALID_ENUM);
4603 default:
4604 return error(GL_INVALID_ENUM);
4605 }
4606 }
4607}
4608
4609void PolygonOffset(GLfloat factor, GLfloat units)
4610{
4611 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4612
4613 es2::Context *context = es2::getContext();
4614
4615 if(context)
4616 {
4617 context->setPolygonOffsetParams(factor, units);
4618 }
4619}
4620
4621void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4622 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4623{
4624 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4625 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4626 x, y, width, height, format, type, bufSize, data);
4627
4628 if(width < 0 || height < 0 || bufSize < 0)
4629 {
4630 return error(GL_INVALID_VALUE);
4631 }
4632
4633 es2::Context *context = es2::getContext();
4634
4635 if(context)
4636 {
4637 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4638 }
4639}
4640
4641void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4642{
4643 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4644 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4645 x, y, width, height, format, type, pixels);
4646
4647 if(width < 0 || height < 0)
4648 {
4649 return error(GL_INVALID_VALUE);
4650 }
4651
4652 es2::Context *context = es2::getContext();
4653
4654 if(context)
4655 {
4656 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4657 }
4658}
4659
4660void ReleaseShaderCompiler(void)
4661{
4662 TRACE("()");
4663
4664 es2::Shader::releaseCompiler();
4665}
4666
Nicolas Capens400667e2017-03-29 14:40:14 -04004667void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004668{
4669 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4670 target, samples, internalformat, width, height);
4671
4672 switch(target)
4673 {
4674 case GL_RENDERBUFFER:
4675 break;
4676 default:
4677 return error(GL_INVALID_ENUM);
4678 }
4679
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004680 if(width < 0 || height < 0 || samples < 0 ||
4681 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4682 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004683 {
4684 return error(GL_INVALID_VALUE);
4685 }
4686
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004687 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
4688 (sw::Surface::isNonNormalizedInteger(es2sw::ConvertRenderbufferFormat(internalformat)) && samples > 0))
4689 {
4690 return error(GL_INVALID_OPERATION);
4691 }
4692
Nicolas Capens0bac2852016-05-07 06:09:58 -04004693 es2::Context *context = es2::getContext();
4694
4695 if(context)
4696 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004697 GLuint handle = context->getRenderbufferName();
4698 if(handle == 0)
4699 {
4700 return error(GL_INVALID_OPERATION);
4701 }
4702
4703 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004704
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004705 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004706 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004707 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004708 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004709 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4710 {
4711 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4712 }
4713 else if(IsDepthRenderable(internalformat, clientVersion))
4714 {
4715 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4716 }
4717 else if(IsStencilRenderable(internalformat, clientVersion))
4718 {
4719 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4720 }
4721 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004722 }
4723}
4724
Nicolas Capens400667e2017-03-29 14:40:14 -04004725void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4726{
4727 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4728}
4729
Nicolas Capens0bac2852016-05-07 06:09:58 -04004730void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4731{
Nicolas Capens400667e2017-03-29 14:40:14 -04004732 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004733}
4734
4735void SampleCoverage(GLclampf value, GLboolean invert)
4736{
4737 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4738
4739 es2::Context* context = es2::getContext();
4740
4741 if(context)
4742 {
4743 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4744 }
4745}
4746
4747void SetFenceNV(GLuint fence, GLenum condition)
4748{
4749 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4750
4751 if(condition != GL_ALL_COMPLETED_NV)
4752 {
4753 return error(GL_INVALID_ENUM);
4754 }
4755
4756 es2::Context *context = es2::getContext();
4757
4758 if(context)
4759 {
4760 es2::Fence *fenceObject = context->getFence(fence);
4761
4762 if(!fenceObject)
4763 {
4764 return error(GL_INVALID_OPERATION);
4765 }
4766
4767 fenceObject->setFence(condition);
4768 }
4769}
4770
4771void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4772{
4773 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4774
4775 if(width < 0 || height < 0)
4776 {
4777 return error(GL_INVALID_VALUE);
4778 }
4779
4780 es2::Context* context = es2::getContext();
4781
4782 if(context)
4783 {
4784 context->setScissorParams(x, y, width, height);
4785 }
4786}
4787
4788void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4789{
4790 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4791 "const GLvoid* binary = %p, GLsizei length = %d)",
4792 n, shaders, binaryformat, binary, length);
4793
4794 // No binary shader formats are supported.
4795 return error(GL_INVALID_ENUM);
4796}
4797
4798void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4799{
4800 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4801 shader, count, string, length);
4802
4803 if(count < 0)
4804 {
4805 return error(GL_INVALID_VALUE);
4806 }
4807
4808 es2::Context *context = es2::getContext();
4809
4810 if(context)
4811 {
4812 es2::Shader *shaderObject = context->getShader(shader);
4813
4814 if(!shaderObject)
4815 {
4816 if(context->getProgram(shader))
4817 {
4818 return error(GL_INVALID_OPERATION);
4819 }
4820 else
4821 {
4822 return error(GL_INVALID_VALUE);
4823 }
4824 }
4825
4826 shaderObject->setSource(count, string, length);
4827 }
4828}
4829
4830void StencilFunc(GLenum func, GLint ref, GLuint mask)
4831{
4832 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4833}
4834
4835void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4836{
4837 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4838
4839 switch(face)
4840 {
4841 case GL_FRONT:
4842 case GL_BACK:
4843 case GL_FRONT_AND_BACK:
4844 break;
4845 default:
4846 return error(GL_INVALID_ENUM);
4847 }
4848
4849 switch(func)
4850 {
4851 case GL_NEVER:
4852 case GL_ALWAYS:
4853 case GL_LESS:
4854 case GL_LEQUAL:
4855 case GL_EQUAL:
4856 case GL_GEQUAL:
4857 case GL_GREATER:
4858 case GL_NOTEQUAL:
4859 break;
4860 default:
4861 return error(GL_INVALID_ENUM);
4862 }
4863
4864 es2::Context *context = es2::getContext();
4865
4866 if(context)
4867 {
4868 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4869 {
4870 context->setStencilParams(func, ref, mask);
4871 }
4872
4873 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4874 {
4875 context->setStencilBackParams(func, ref, mask);
4876 }
4877 }
4878}
4879
4880void StencilMask(GLuint mask)
4881{
4882 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4883}
4884
4885void StencilMaskSeparate(GLenum face, GLuint mask)
4886{
4887 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4888
4889 switch(face)
4890 {
4891 case GL_FRONT:
4892 case GL_BACK:
4893 case GL_FRONT_AND_BACK:
4894 break;
4895 default:
4896 return error(GL_INVALID_ENUM);
4897 }
4898
4899 es2::Context *context = es2::getContext();
4900
4901 if(context)
4902 {
4903 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4904 {
4905 context->setStencilWritemask(mask);
4906 }
4907
4908 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4909 {
4910 context->setStencilBackWritemask(mask);
4911 }
4912 }
4913}
4914
4915void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4916{
4917 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4918}
4919
4920void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4921{
4922 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4923 face, fail, zfail, zpass);
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 switch(fail)
4936 {
4937 case GL_ZERO:
4938 case GL_KEEP:
4939 case GL_REPLACE:
4940 case GL_INCR:
4941 case GL_DECR:
4942 case GL_INVERT:
4943 case GL_INCR_WRAP:
4944 case GL_DECR_WRAP:
4945 break;
4946 default:
4947 return error(GL_INVALID_ENUM);
4948 }
4949
4950 switch(zfail)
4951 {
4952 case GL_ZERO:
4953 case GL_KEEP:
4954 case GL_REPLACE:
4955 case GL_INCR:
4956 case GL_DECR:
4957 case GL_INVERT:
4958 case GL_INCR_WRAP:
4959 case GL_DECR_WRAP:
4960 break;
4961 default:
4962 return error(GL_INVALID_ENUM);
4963 }
4964
4965 switch(zpass)
4966 {
4967 case GL_ZERO:
4968 case GL_KEEP:
4969 case GL_REPLACE:
4970 case GL_INCR:
4971 case GL_DECR:
4972 case GL_INVERT:
4973 case GL_INCR_WRAP:
4974 case GL_DECR_WRAP:
4975 break;
4976 default:
4977 return error(GL_INVALID_ENUM);
4978 }
4979
4980 es2::Context *context = es2::getContext();
4981
4982 if(context)
4983 {
4984 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4985 {
4986 context->setStencilOperations(fail, zfail, zpass);
4987 }
4988
4989 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4990 {
4991 context->setStencilBackOperations(fail, zfail, zpass);
4992 }
4993 }
4994}
4995
4996GLboolean TestFenceNV(GLuint fence)
4997{
4998 TRACE("(GLuint fence = %d)", fence);
4999
5000 es2::Context *context = es2::getContext();
5001
5002 if(context)
5003 {
5004 es2::Fence *fenceObject = context->getFence(fence);
5005
5006 if(!fenceObject)
5007 {
5008 return error(GL_INVALID_OPERATION, GL_TRUE);
5009 }
5010
5011 return fenceObject->testFence();
5012 }
5013
5014 return GL_TRUE;
5015}
5016
5017void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005018 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005019{
5020 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005021 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
5022 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005023
5024 if(!validImageSize(level, width, height))
5025 {
5026 return error(GL_INVALID_VALUE);
5027 }
5028
5029 es2::Context *context = es2::getContext();
5030
5031 if(context)
5032 {
5033 GLint clientVersion = context->getClientVersion();
5034 if(clientVersion < 3)
5035 {
5036 if(internalformat != (GLint)format)
5037 {
5038 return error(GL_INVALID_OPERATION);
5039 }
5040 }
5041
5042 GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
5043 if(validationError != GL_NONE)
5044 {
5045 return error(validationError);
5046 }
5047
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005048 validationError = ValidateTextureFormatType(format, type, internalformat, context->getClientVersion());
5049 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005050 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005051 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005052 }
5053
5054 if(border != 0)
5055 {
5056 return error(GL_INVALID_VALUE);
5057 }
5058
5059 switch(target)
5060 {
5061 case GL_TEXTURE_2D:
5062 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5063 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5064 {
5065 return error(GL_INVALID_VALUE);
5066 }
5067 break;
5068 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5069 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5070 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5071 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5072 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5073 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5074 if(width != height)
5075 {
5076 return error(GL_INVALID_VALUE);
5077 }
5078
5079 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5080 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5081 {
5082 return error(GL_INVALID_VALUE);
5083 }
5084 break;
5085 default:
5086 return error(GL_INVALID_ENUM);
5087 }
5088
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005089 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005090
Alexis Hetu848aa7f2017-11-17 13:15:32 -05005091 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005092 if(validationError != GL_NONE)
5093 {
5094 return error(validationError);
5095 }
5096
Nicolas Capens0bac2852016-05-07 06:09:58 -04005097 if(target == GL_TEXTURE_2D)
5098 {
5099 es2::Texture2D *texture = context->getTexture2D();
5100
5101 if(!texture)
5102 {
5103 return error(GL_INVALID_OPERATION);
5104 }
5105
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005106 texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005107 }
5108 else
5109 {
5110 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5111
5112 if(!texture)
5113 {
5114 return error(GL_INVALID_OPERATION);
5115 }
5116
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005117 texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005118 }
5119 }
5120}
5121
5122void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5123{
5124 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5125
5126 es2::Context *context = es2::getContext();
5127
5128 if(context)
5129 {
5130 es2::Texture *texture;
5131
5132 GLint clientVersion = context->getClientVersion();
5133
5134 switch(target)
5135 {
5136 case GL_TEXTURE_2D:
5137 texture = context->getTexture2D();
5138 break;
5139 case GL_TEXTURE_2D_ARRAY:
5140 if(clientVersion < 3)
5141 {
5142 return error(GL_INVALID_ENUM);
5143 }
5144 else
5145 {
5146 texture = context->getTexture2DArray();
5147 }
5148 break;
5149 case GL_TEXTURE_3D_OES:
5150 texture = context->getTexture3D();
5151 break;
5152 case GL_TEXTURE_CUBE_MAP:
5153 texture = context->getTextureCubeMap();
5154 break;
5155 case GL_TEXTURE_EXTERNAL_OES:
5156 texture = context->getTextureExternal();
5157 break;
5158 default:
5159 return error(GL_INVALID_ENUM);
5160 }
5161
5162 switch(pname)
5163 {
5164 case GL_TEXTURE_WRAP_S:
5165 if(!texture->setWrapS((GLenum)param))
5166 {
5167 return error(GL_INVALID_ENUM);
5168 }
5169 break;
5170 case GL_TEXTURE_WRAP_T:
5171 if(!texture->setWrapT((GLenum)param))
5172 {
5173 return error(GL_INVALID_ENUM);
5174 }
5175 break;
5176 case GL_TEXTURE_WRAP_R_OES:
5177 if(!texture->setWrapR((GLenum)param))
5178 {
5179 return error(GL_INVALID_ENUM);
5180 }
5181 break;
5182 case GL_TEXTURE_MIN_FILTER:
5183 if(!texture->setMinFilter((GLenum)param))
5184 {
5185 return error(GL_INVALID_ENUM);
5186 }
5187 break;
5188 case GL_TEXTURE_MAG_FILTER:
5189 if(!texture->setMagFilter((GLenum)param))
5190 {
5191 return error(GL_INVALID_ENUM);
5192 }
5193 break;
5194 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5195 if(!texture->setMaxAnisotropy(param))
5196 {
5197 return error(GL_INVALID_VALUE);
5198 }
5199 break;
5200 case GL_TEXTURE_BASE_LEVEL:
5201 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5202 {
5203 return error(GL_INVALID_VALUE);
5204 }
5205 break;
5206 case GL_TEXTURE_COMPARE_FUNC:
5207 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5208 {
5209 return error(GL_INVALID_VALUE);
5210 }
5211 break;
5212 case GL_TEXTURE_COMPARE_MODE:
5213 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5214 {
5215 return error(GL_INVALID_VALUE);
5216 }
5217 break;
5218 case GL_TEXTURE_MAX_LEVEL:
5219 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5220 {
5221 return error(GL_INVALID_VALUE);
5222 }
5223 break;
5224 case GL_TEXTURE_MAX_LOD:
5225 if(clientVersion < 3 || !texture->setMaxLOD(param))
5226 {
5227 return error(GL_INVALID_VALUE);
5228 }
5229 break;
5230 case GL_TEXTURE_MIN_LOD:
5231 if(clientVersion < 3 || !texture->setMinLOD(param))
5232 {
5233 return error(GL_INVALID_VALUE);
5234 }
5235 break;
5236 case GL_TEXTURE_SWIZZLE_R:
5237 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5238 {
5239 return error(GL_INVALID_VALUE);
5240 }
5241 break;
5242 case GL_TEXTURE_SWIZZLE_G:
5243 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5244 {
5245 return error(GL_INVALID_VALUE);
5246 }
5247 break;
5248 case GL_TEXTURE_SWIZZLE_B:
5249 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5250 {
5251 return error(GL_INVALID_VALUE);
5252 }
5253 break;
5254 case GL_TEXTURE_SWIZZLE_A:
5255 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5256 {
5257 return error(GL_INVALID_VALUE);
5258 }
5259 break;
5260 default:
5261 return error(GL_INVALID_ENUM);
5262 }
5263 }
5264}
5265
5266void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5267{
5268 glTexParameterf(target, pname, *params);
5269}
5270
5271void TexParameteri(GLenum target, GLenum pname, GLint param)
5272{
5273 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5274
5275 es2::Context *context = es2::getContext();
5276
5277 if(context)
5278 {
5279 es2::Texture *texture;
5280
5281 GLint clientVersion = context->getClientVersion();
5282
5283 switch(target)
5284 {
5285 case GL_TEXTURE_2D:
5286 texture = context->getTexture2D();
5287 break;
5288 case GL_TEXTURE_2D_ARRAY:
5289 if(clientVersion < 3)
5290 {
5291 return error(GL_INVALID_ENUM);
5292 }
5293 else
5294 {
5295 texture = context->getTexture2DArray();
5296 }
5297 break;
5298 case GL_TEXTURE_3D_OES:
5299 texture = context->getTexture3D();
5300 break;
5301 case GL_TEXTURE_CUBE_MAP:
5302 texture = context->getTextureCubeMap();
5303 break;
5304 case GL_TEXTURE_EXTERNAL_OES:
5305 texture = context->getTextureExternal();
5306 break;
5307 default:
5308 return error(GL_INVALID_ENUM);
5309 }
5310
5311 switch(pname)
5312 {
5313 case GL_TEXTURE_WRAP_S:
5314 if(!texture->setWrapS((GLenum)param))
5315 {
5316 return error(GL_INVALID_ENUM);
5317 }
5318 break;
5319 case GL_TEXTURE_WRAP_T:
5320 if(!texture->setWrapT((GLenum)param))
5321 {
5322 return error(GL_INVALID_ENUM);
5323 }
5324 break;
5325 case GL_TEXTURE_WRAP_R_OES:
5326 if(!texture->setWrapR((GLenum)param))
5327 {
5328 return error(GL_INVALID_ENUM);
5329 }
5330 break;
5331 case GL_TEXTURE_MIN_FILTER:
5332 if(!texture->setMinFilter((GLenum)param))
5333 {
5334 return error(GL_INVALID_ENUM);
5335 }
5336 break;
5337 case GL_TEXTURE_MAG_FILTER:
5338 if(!texture->setMagFilter((GLenum)param))
5339 {
5340 return error(GL_INVALID_ENUM);
5341 }
5342 break;
5343 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5344 if(!texture->setMaxAnisotropy((GLfloat)param))
5345 {
5346 return error(GL_INVALID_VALUE);
5347 }
5348 break;
5349 case GL_TEXTURE_BASE_LEVEL:
5350 if(clientVersion < 3 || !texture->setBaseLevel(param))
5351 {
5352 return error(GL_INVALID_VALUE);
5353 }
5354 break;
5355 case GL_TEXTURE_COMPARE_FUNC:
5356 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5357 {
5358 return error(GL_INVALID_VALUE);
5359 }
5360 break;
5361 case GL_TEXTURE_COMPARE_MODE:
5362 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5363 {
5364 return error(GL_INVALID_VALUE);
5365 }
5366 break;
5367 case GL_TEXTURE_MAX_LEVEL:
5368 if(clientVersion < 3 || !texture->setMaxLevel(param))
5369 {
5370 return error(GL_INVALID_VALUE);
5371 }
5372 break;
5373 case GL_TEXTURE_MAX_LOD:
5374 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5375 {
5376 return error(GL_INVALID_VALUE);
5377 }
5378 break;
5379 case GL_TEXTURE_MIN_LOD:
5380 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5381 {
5382 return error(GL_INVALID_VALUE);
5383 }
5384 break;
5385 case GL_TEXTURE_SWIZZLE_R:
5386 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5387 {
5388 return error(GL_INVALID_VALUE);
5389 }
5390 break;
5391 case GL_TEXTURE_SWIZZLE_G:
5392 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5393 {
5394 return error(GL_INVALID_VALUE);
5395 }
5396 break;
5397 case GL_TEXTURE_SWIZZLE_B:
5398 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5399 {
5400 return error(GL_INVALID_VALUE);
5401 }
5402 break;
5403 case GL_TEXTURE_SWIZZLE_A:
5404 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5405 {
5406 return error(GL_INVALID_VALUE);
5407 }
5408 break;
5409 default:
5410 return error(GL_INVALID_ENUM);
5411 }
5412 }
5413}
5414
5415void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5416{
5417 glTexParameteri(target, pname, *params);
5418}
5419
5420void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005421 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005422{
5423 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5424 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005425 "const GLvoid* data = %p)",
5426 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005427
5428 if(!es2::IsTextureTarget(target))
5429 {
5430 return error(GL_INVALID_ENUM);
5431 }
5432
5433 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5434 {
5435 return error(GL_INVALID_VALUE);
5436 }
5437
5438 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5439 {
5440 return error(GL_INVALID_VALUE);
5441 }
5442
5443 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5444 {
5445 return error(GL_INVALID_VALUE);
5446 }
5447
Nicolas Capens0bac2852016-05-07 06:09:58 -04005448 es2::Context *context = es2::getContext();
5449
5450 if(context)
5451 {
5452 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
5453
5454 if(target == GL_TEXTURE_2D)
5455 {
5456 es2::Texture2D *texture = context->getTexture2D();
5457
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005458 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5459 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005460 {
5461 return error(validationError);
5462 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005463
5464 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
5465 if(validationError != GL_NONE)
5466 {
5467 return error(validationError);
5468 }
5469
5470 texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005471 }
5472 else if(es2::IsCubemapTextureTarget(target))
5473 {
5474 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5475
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005476 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5477 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005478 {
5479 return error(validationError);
5480 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005481
5482 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
5483 if(validationError != GL_NONE)
5484 {
5485 return error(validationError);
5486 }
5487
5488 texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005489 }
5490 else UNREACHABLE(target);
5491 }
5492}
5493
5494void Uniform1f(GLint location, GLfloat x)
5495{
5496 glUniform1fv(location, 1, &x);
5497}
5498
5499void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5500{
5501 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5502
5503 if(count < 0)
5504 {
5505 return error(GL_INVALID_VALUE);
5506 }
5507
Nicolas Capens0bac2852016-05-07 06:09:58 -04005508 es2::Context *context = es2::getContext();
5509
5510 if(context)
5511 {
5512 es2::Program *program = context->getCurrentProgram();
5513
5514 if(!program)
5515 {
5516 return error(GL_INVALID_OPERATION);
5517 }
5518
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005519 if(location == -1)
5520 {
5521 return;
5522 }
5523
Nicolas Capens0bac2852016-05-07 06:09:58 -04005524 if(!program->setUniform1fv(location, count, v))
5525 {
5526 return error(GL_INVALID_OPERATION);
5527 }
5528 }
5529}
5530
5531void Uniform1i(GLint location, GLint x)
5532{
5533 glUniform1iv(location, 1, &x);
5534}
5535
5536void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5537{
5538 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5539
5540 if(count < 0)
5541 {
5542 return error(GL_INVALID_VALUE);
5543 }
5544
Nicolas Capens0bac2852016-05-07 06:09:58 -04005545 es2::Context *context = es2::getContext();
5546
5547 if(context)
5548 {
5549 es2::Program *program = context->getCurrentProgram();
5550
5551 if(!program)
5552 {
5553 return error(GL_INVALID_OPERATION);
5554 }
5555
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005556 if(location == -1)
5557 {
5558 return;
5559 }
5560
Nicolas Capens0bac2852016-05-07 06:09:58 -04005561 if(!program->setUniform1iv(location, count, v))
5562 {
5563 return error(GL_INVALID_OPERATION);
5564 }
5565 }
5566}
5567
5568void Uniform2f(GLint location, GLfloat x, GLfloat y)
5569{
5570 GLfloat xy[2] = {x, y};
5571
5572 glUniform2fv(location, 1, (GLfloat*)&xy);
5573}
5574
5575void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5576{
5577 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5578
5579 if(count < 0)
5580 {
5581 return error(GL_INVALID_VALUE);
5582 }
5583
Nicolas Capens0bac2852016-05-07 06:09:58 -04005584 es2::Context *context = es2::getContext();
5585
5586 if(context)
5587 {
5588 es2::Program *program = context->getCurrentProgram();
5589
5590 if(!program)
5591 {
5592 return error(GL_INVALID_OPERATION);
5593 }
5594
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005595 if(location == -1)
5596 {
5597 return;
5598 }
5599
Nicolas Capens0bac2852016-05-07 06:09:58 -04005600 if(!program->setUniform2fv(location, count, v))
5601 {
5602 return error(GL_INVALID_OPERATION);
5603 }
5604 }
5605}
5606
5607void Uniform2i(GLint location, GLint x, GLint y)
5608{
5609 GLint xy[4] = {x, y};
5610
5611 glUniform2iv(location, 1, (GLint*)&xy);
5612}
5613
5614void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5615{
5616 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5617
5618 if(count < 0)
5619 {
5620 return error(GL_INVALID_VALUE);
5621 }
5622
Nicolas Capens0bac2852016-05-07 06:09:58 -04005623 es2::Context *context = es2::getContext();
5624
5625 if(context)
5626 {
5627 es2::Program *program = context->getCurrentProgram();
5628
5629 if(!program)
5630 {
5631 return error(GL_INVALID_OPERATION);
5632 }
5633
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005634 if(location == -1)
5635 {
5636 return;
5637 }
5638
Nicolas Capens0bac2852016-05-07 06:09:58 -04005639 if(!program->setUniform2iv(location, count, v))
5640 {
5641 return error(GL_INVALID_OPERATION);
5642 }
5643 }
5644}
5645
5646void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5647{
5648 GLfloat xyz[3] = {x, y, z};
5649
5650 glUniform3fv(location, 1, (GLfloat*)&xyz);
5651}
5652
5653void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5654{
5655 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5656
5657 if(count < 0)
5658 {
5659 return error(GL_INVALID_VALUE);
5660 }
5661
Nicolas Capens0bac2852016-05-07 06:09:58 -04005662 es2::Context *context = es2::getContext();
5663
5664 if(context)
5665 {
5666 es2::Program *program = context->getCurrentProgram();
5667
5668 if(!program)
5669 {
5670 return error(GL_INVALID_OPERATION);
5671 }
5672
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005673 if(location == -1)
5674 {
5675 return;
5676 }
5677
Nicolas Capens0bac2852016-05-07 06:09:58 -04005678 if(!program->setUniform3fv(location, count, v))
5679 {
5680 return error(GL_INVALID_OPERATION);
5681 }
5682 }
5683}
5684
5685void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5686{
5687 GLint xyz[3] = {x, y, z};
5688
5689 glUniform3iv(location, 1, (GLint*)&xyz);
5690}
5691
5692void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5693{
5694 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5695
5696 if(count < 0)
5697 {
5698 return error(GL_INVALID_VALUE);
5699 }
5700
Nicolas Capens0bac2852016-05-07 06:09:58 -04005701 es2::Context *context = es2::getContext();
5702
5703 if(context)
5704 {
5705 es2::Program *program = context->getCurrentProgram();
5706
5707 if(!program)
5708 {
5709 return error(GL_INVALID_OPERATION);
5710 }
5711
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005712 if(location == -1)
5713 {
5714 return;
5715 }
5716
Nicolas Capens0bac2852016-05-07 06:09:58 -04005717 if(!program->setUniform3iv(location, count, v))
5718 {
5719 return error(GL_INVALID_OPERATION);
5720 }
5721 }
5722}
5723
5724void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5725{
5726 GLfloat xyzw[4] = {x, y, z, w};
5727
5728 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5729}
5730
5731void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5732{
5733 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5734
5735 if(count < 0)
5736 {
5737 return error(GL_INVALID_VALUE);
5738 }
5739
Nicolas Capens0bac2852016-05-07 06:09:58 -04005740 es2::Context *context = es2::getContext();
5741
5742 if(context)
5743 {
5744 es2::Program *program = context->getCurrentProgram();
5745
5746 if(!program)
5747 {
5748 return error(GL_INVALID_OPERATION);
5749 }
5750
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005751 if(location == -1)
5752 {
5753 return;
5754 }
5755
Nicolas Capens0bac2852016-05-07 06:09:58 -04005756 if(!program->setUniform4fv(location, count, v))
5757 {
5758 return error(GL_INVALID_OPERATION);
5759 }
5760 }
5761}
5762
5763void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5764{
5765 GLint xyzw[4] = {x, y, z, w};
5766
5767 glUniform4iv(location, 1, (GLint*)&xyzw);
5768}
5769
5770void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5771{
5772 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5773
5774 if(count < 0)
5775 {
5776 return error(GL_INVALID_VALUE);
5777 }
5778
Nicolas Capens0bac2852016-05-07 06:09:58 -04005779 es2::Context *context = es2::getContext();
5780
5781 if(context)
5782 {
5783 es2::Program *program = context->getCurrentProgram();
5784
5785 if(!program)
5786 {
5787 return error(GL_INVALID_OPERATION);
5788 }
5789
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005790 if(location == -1)
5791 {
5792 return;
5793 }
5794
Nicolas Capens0bac2852016-05-07 06:09:58 -04005795 if(!program->setUniform4iv(location, count, v))
5796 {
5797 return error(GL_INVALID_OPERATION);
5798 }
5799 }
5800}
5801
5802void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5803{
5804 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5805 location, count, transpose, value);
5806
5807 if(count < 0)
5808 {
5809 return error(GL_INVALID_VALUE);
5810 }
5811
Nicolas Capens0bac2852016-05-07 06:09:58 -04005812 es2::Context *context = es2::getContext();
5813
5814 if(context)
5815 {
5816 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5817 {
5818 return error(GL_INVALID_VALUE);
5819 }
5820
5821 es2::Program *program = context->getCurrentProgram();
5822
5823 if(!program)
5824 {
5825 return error(GL_INVALID_OPERATION);
5826 }
5827
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005828 if(location == -1)
5829 {
5830 return;
5831 }
5832
Nicolas Capens0bac2852016-05-07 06:09:58 -04005833 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5834 {
5835 return error(GL_INVALID_OPERATION);
5836 }
5837 }
5838}
5839
5840void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5841{
5842 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5843 location, count, transpose, value);
5844
5845 if(count < 0)
5846 {
5847 return error(GL_INVALID_VALUE);
5848 }
5849
Nicolas Capens0bac2852016-05-07 06:09:58 -04005850 es2::Context *context = es2::getContext();
5851
5852 if(context)
5853 {
5854 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5855 {
5856 return error(GL_INVALID_VALUE);
5857 }
5858
5859 es2::Program *program = context->getCurrentProgram();
5860
5861 if(!program)
5862 {
5863 return error(GL_INVALID_OPERATION);
5864 }
5865
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005866 if(location == -1)
5867 {
5868 return;
5869 }
5870
Nicolas Capens0bac2852016-05-07 06:09:58 -04005871 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5872 {
5873 return error(GL_INVALID_OPERATION);
5874 }
5875 }
5876}
5877
5878void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5879{
5880 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5881 location, count, transpose, value);
5882
5883 if(count < 0)
5884 {
5885 return error(GL_INVALID_VALUE);
5886 }
5887
Nicolas Capens0bac2852016-05-07 06:09:58 -04005888 es2::Context *context = es2::getContext();
5889
5890 if(context)
5891 {
5892 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5893 {
5894 return error(GL_INVALID_VALUE);
5895 }
5896
5897 es2::Program *program = context->getCurrentProgram();
5898
5899 if(!program)
5900 {
5901 return error(GL_INVALID_OPERATION);
5902 }
5903
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005904 if(location == -1)
5905 {
5906 return;
5907 }
5908
Nicolas Capens0bac2852016-05-07 06:09:58 -04005909 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5910 {
5911 return error(GL_INVALID_OPERATION);
5912 }
5913 }
5914}
5915
5916void UseProgram(GLuint program)
5917{
5918 TRACE("(GLuint program = %d)", program);
5919
5920 es2::Context *context = es2::getContext();
5921
5922 if(context)
5923 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005924 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5925 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5926 {
5927 return error(GL_INVALID_OPERATION);
5928 }
5929
Nicolas Capens0bac2852016-05-07 06:09:58 -04005930 es2::Program *programObject = context->getProgram(program);
5931
5932 if(!programObject && program != 0)
5933 {
5934 if(context->getShader(program))
5935 {
5936 return error(GL_INVALID_OPERATION);
5937 }
5938 else
5939 {
5940 return error(GL_INVALID_VALUE);
5941 }
5942 }
5943
5944 if(program != 0 && !programObject->isLinked())
5945 {
5946 return error(GL_INVALID_OPERATION);
5947 }
5948
5949 context->useProgram(program);
5950 }
5951}
5952
5953void ValidateProgram(GLuint program)
5954{
5955 TRACE("(GLuint program = %d)", program);
5956
5957 es2::Context *context = es2::getContext();
5958
5959 if(context)
5960 {
5961 es2::Program *programObject = context->getProgram(program);
5962
5963 if(!programObject)
5964 {
5965 if(context->getShader(program))
5966 {
5967 return error(GL_INVALID_OPERATION);
5968 }
5969 else
5970 {
5971 return error(GL_INVALID_VALUE);
5972 }
5973 }
5974
Ben Vanik1fd3b282017-07-10 14:08:12 -07005975 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005976 }
5977}
5978
5979void VertexAttrib1f(GLuint index, GLfloat x)
5980{
5981 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5982
5983 if(index >= es2::MAX_VERTEX_ATTRIBS)
5984 {
5985 return error(GL_INVALID_VALUE);
5986 }
5987
5988 es2::Context *context = es2::getContext();
5989
5990 if(context)
5991 {
5992 GLfloat vals[4] = { x, 0, 0, 1 };
5993 context->setVertexAttrib(index, vals);
5994 }
5995}
5996
5997void VertexAttrib1fv(GLuint index, const GLfloat* values)
5998{
5999 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6000
6001 if(index >= es2::MAX_VERTEX_ATTRIBS)
6002 {
6003 return error(GL_INVALID_VALUE);
6004 }
6005
6006 es2::Context *context = es2::getContext();
6007
6008 if(context)
6009 {
6010 GLfloat vals[4] = { values[0], 0, 0, 1 };
6011 context->setVertexAttrib(index, vals);
6012 }
6013}
6014
6015void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
6016{
6017 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
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, y, 0, 1 };
6029 context->setVertexAttrib(index, vals);
6030 }
6031}
6032
6033void VertexAttrib2fv(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], values[1], 0, 1 };
6047 context->setVertexAttrib(index, vals);
6048 }
6049}
6050
6051void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6052{
6053 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
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, z, 1 };
6065 context->setVertexAttrib(index, vals);
6066 }
6067}
6068
6069void VertexAttrib3fv(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], values[2], 1 };
6083 context->setVertexAttrib(index, vals);
6084 }
6085}
6086
6087void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6088{
6089 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
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, w };
6101 context->setVertexAttrib(index, vals);
6102 }
6103}
6104
6105void VertexAttrib4fv(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 context->setVertexAttrib(index, values);
6119 }
6120}
6121
6122void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6123{
6124 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6125 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6126 index, size, type, normalized, stride, ptr);
6127
6128 if(index >= es2::MAX_VERTEX_ATTRIBS)
6129 {
6130 return error(GL_INVALID_VALUE);
6131 }
6132
6133 if(size < 1 || size > 4)
6134 {
6135 return error(GL_INVALID_VALUE);
6136 }
6137
6138 GLint clientVersion = egl::getClientVersion();
6139
6140 switch(type)
6141 {
6142 case GL_BYTE:
6143 case GL_UNSIGNED_BYTE:
6144 case GL_SHORT:
6145 case GL_UNSIGNED_SHORT:
6146 case GL_FIXED:
6147 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006148 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006149 break;
6150 case GL_INT_2_10_10_10_REV:
6151 case GL_UNSIGNED_INT_2_10_10_10_REV:
6152 if(clientVersion >= 3)
6153 {
6154 if(size != 4)
6155 {
6156 return error(GL_INVALID_OPERATION);
6157 }
6158 break;
6159 }
6160 else return error(GL_INVALID_ENUM);
6161 case GL_INT:
6162 case GL_UNSIGNED_INT:
6163 case GL_HALF_FLOAT:
6164 if(clientVersion >= 3)
6165 {
6166 break;
6167 }
6168 else return error(GL_INVALID_ENUM);
6169 default:
6170 return error(GL_INVALID_ENUM);
6171 }
6172
6173 if(stride < 0)
6174 {
6175 return error(GL_INVALID_VALUE);
6176 }
6177
6178 es2::Context *context = es2::getContext();
6179
6180 if(context)
6181 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006182 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6183 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6184 {
6185 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6186 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6187 return error(GL_INVALID_OPERATION);
6188 }
6189
Nicolas Capens0bac2852016-05-07 06:09:58 -04006190 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
6191 }
6192}
6193
6194void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6195{
6196 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6197
6198 if(width < 0 || height < 0)
6199 {
6200 return error(GL_INVALID_VALUE);
6201 }
6202
6203 es2::Context *context = es2::getContext();
6204
6205 if(context)
6206 {
6207 context->setViewportParams(x, y, width, height);
6208 }
6209}
6210
Alexis Hetub9dda642016-10-06 11:25:32 -04006211static 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 -04006212{
6213 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6214 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6215 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6216 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6217
6218 switch(filter)
6219 {
6220 case GL_NEAREST:
6221 break;
6222 default:
6223 return error(GL_INVALID_ENUM);
6224 }
6225
6226 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6227 {
6228 return error(GL_INVALID_VALUE);
6229 }
6230
6231 es2::Context *context = es2::getContext();
6232
6233 if(context)
6234 {
6235 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6236 {
6237 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6238 return error(GL_INVALID_OPERATION);
6239 }
6240
Alexis Hetub9dda642016-10-06 11:25:32 -04006241 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006242 }
6243}
6244
Alexis Hetub9dda642016-10-06 11:25:32 -04006245void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6246{
6247 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6248}
6249
Nicolas Capens0bac2852016-05-07 06:09:58 -04006250void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6251 GLbitfield mask, GLenum filter)
6252{
6253 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6254 {
6255 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6256 return error(GL_INVALID_OPERATION);
6257 }
6258
Alexis Hetub9dda642016-10-06 11:25:32 -04006259 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006260}
6261
6262void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006263 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006264{
6265 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6266 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006267 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6268 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006269
6270 switch(target)
6271 {
6272 case GL_TEXTURE_3D_OES:
6273 switch(format)
6274 {
6275 case GL_DEPTH_COMPONENT:
6276 case GL_DEPTH_STENCIL_OES:
6277 return error(GL_INVALID_OPERATION);
6278 default:
6279 break;
6280 }
6281 break;
6282 default:
6283 return error(GL_INVALID_ENUM);
6284 }
6285
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006286 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006287 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006288 return error(GL_INVALID_OPERATION);
6289 }
6290
6291 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion());
6292 if(validationError != GL_NONE)
6293 {
6294 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006295 }
6296
6297 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6298 {
6299 return error(GL_INVALID_VALUE);
6300 }
6301
6302 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6303 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6304 {
6305 return error(GL_INVALID_VALUE);
6306 }
6307
6308 if(border != 0)
6309 {
6310 return error(GL_INVALID_VALUE);
6311 }
6312
6313 es2::Context *context = es2::getContext();
6314
6315 if(context)
6316 {
6317 es2::Texture3D *texture = context->getTexture3D();
6318
6319 if(!texture)
6320 {
6321 return error(GL_INVALID_OPERATION);
6322 }
6323
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006324 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006325 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006326 if(validationError != GL_NONE)
6327 {
6328 return error(validationError);
6329 }
6330
6331 texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006332 }
6333}
6334
Alexis Hetu53f48092016-06-17 14:08:06 -04006335void 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 -04006336{
6337 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6338 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006339 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6340 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006341
6342 switch(target)
6343 {
6344 case GL_TEXTURE_3D_OES:
6345 break;
6346 default:
6347 return error(GL_INVALID_ENUM);
6348 }
6349
6350 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6351 {
6352 return;
6353 }
6354
6355 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6356 {
6357 return error(GL_INVALID_VALUE);
6358 }
6359
6360 if((width < 0) || (height < 0) || (depth < 0))
6361 {
6362 return error(GL_INVALID_VALUE);
6363 }
6364
6365 es2::Context *context = es2::getContext();
6366
6367 if(context)
6368 {
6369 es2::Texture3D *texture = context->getTexture3D();
6370
6371 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
6372
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006373 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
6374 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006375 {
6376 return error(validationError);
6377 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006378
6379 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
6380 if(validationError != GL_NONE)
6381 {
6382 return error(validationError);
6383 }
6384
6385 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006386 }
6387}
6388
6389void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6390{
6391 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6392 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6393 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6394
6395 switch(target)
6396 {
6397 case GL_TEXTURE_3D_OES:
6398 break;
6399 default:
6400 return error(GL_INVALID_ENUM);
6401 }
6402
6403 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6404 {
6405 return error(GL_INVALID_VALUE);
6406 }
6407
6408 es2::Context *context = es2::getContext();
6409
6410 if(context)
6411 {
6412 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6413
6414 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6415 {
6416 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6417 }
6418
6419 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6420
6421 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6422 {
6423 return error(GL_INVALID_OPERATION);
6424 }
6425
6426 es2::Texture3D *texture = context->getTexture3D();
6427
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006428 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 -04006429 if(validationError != GL_NONE)
6430 {
6431 return error(validationError);
6432 }
6433
6434 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6435 }
6436}
6437
6438void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6439{
6440 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6441 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6442 target, level, internalformat, width, height, depth, border, imageSize, data);
6443
6444 switch(target)
6445 {
6446 case GL_TEXTURE_3D_OES:
6447 break;
6448 default:
6449 return error(GL_INVALID_ENUM);
6450 }
6451
6452 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6453 {
6454 return error(GL_INVALID_VALUE);
6455 }
6456
6457 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6458 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6459 {
6460 return error(GL_INVALID_VALUE);
6461 }
6462
6463 switch(internalformat)
6464 {
6465 case GL_DEPTH_COMPONENT:
6466 case GL_DEPTH_COMPONENT16:
6467 case GL_DEPTH_COMPONENT32_OES:
6468 case GL_DEPTH_STENCIL_OES:
6469 case GL_DEPTH24_STENCIL8_OES:
6470 return error(GL_INVALID_OPERATION);
6471 default:
6472 {
6473 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
6474 if(validationError != GL_NONE)
6475 {
6476 return error(validationError);
6477 }
6478 }
6479 }
6480
6481 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6482 {
6483 return error(GL_INVALID_VALUE);
6484 }
6485
6486 es2::Context *context = es2::getContext();
6487
6488 if(context)
6489 {
6490 es2::Texture3D *texture = context->getTexture3D();
6491
6492 if(!texture)
6493 {
6494 return error(GL_INVALID_OPERATION);
6495 }
6496
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006497 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006498
6499 if(validationError != GL_NONE)
6500 {
6501 return error(validationError);
6502 }
6503
Nicolas Capens0bac2852016-05-07 06:09:58 -04006504 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6505 }
6506}
6507
6508void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6509{
6510 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6511 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6512 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6513 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6514
6515 switch(target)
6516 {
6517 case GL_TEXTURE_3D_OES:
6518 break;
6519 default:
6520 return error(GL_INVALID_ENUM);
6521 }
6522
6523 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6524 {
6525 return error(GL_INVALID_VALUE);
6526 }
6527
6528 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6529 {
6530 return error(GL_INVALID_VALUE);
6531 }
6532
6533 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
6534 if(validationError != GL_NONE)
6535 {
6536 return error(validationError);
6537 }
6538
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006539 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006540 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006541 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006542 }
6543
6544 es2::Context *context = es2::getContext();
6545
6546 if(context)
6547 {
6548 es2::Texture3D *texture = context->getTexture3D();
6549
6550 if(!texture)
6551 {
6552 return error(GL_INVALID_OPERATION);
6553 }
6554
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006555 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006556 if(validationError != GL_NONE)
6557 {
6558 return error(validationError);
6559 }
6560
6561 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006562 }
6563}
6564
6565void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6566{
6567 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6568 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6569
6570 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
6571 {
6572 return error(GL_INVALID_ENUM);
6573 }
6574
6575 es2::Context *context = es2::getContext();
6576
6577 if(context)
6578 {
6579 if(texture == 0)
6580 {
6581 textarget = GL_NONE;
6582 }
6583 else
6584 {
6585 es2::Texture *tex = context->getTexture(texture);
6586
6587 if(!tex)
6588 {
6589 return error(GL_INVALID_OPERATION);
6590 }
6591
6592 if(tex->isCompressed(textarget, level))
6593 {
6594 return error(GL_INVALID_OPERATION);
6595 }
6596
6597 switch(textarget)
6598 {
6599 case GL_TEXTURE_3D_OES:
6600 if(tex->getTarget() != GL_TEXTURE_3D_OES)
6601 {
6602 return error(GL_INVALID_OPERATION);
6603 }
6604 break;
6605 default:
6606 return error(GL_INVALID_ENUM);
6607 }
6608
6609 if(level != 0)
6610 {
6611 return error(GL_INVALID_VALUE);
6612 }
6613 }
6614
6615 es2::Framebuffer *framebuffer = nullptr;
6616 GLuint framebufferName = 0;
6617 if(target == GL_READ_FRAMEBUFFER_ANGLE)
6618 {
6619 framebuffer = context->getReadFramebuffer();
6620 framebufferName = context->getReadFramebufferName();
6621 }
6622 else
6623 {
6624 framebuffer = context->getDrawFramebuffer();
6625 framebufferName = context->getDrawFramebufferName();
6626 }
6627
6628 if(framebufferName == 0 || !framebuffer)
6629 {
6630 return error(GL_INVALID_OPERATION);
6631 }
6632
6633 GLint clientVersion = context->getClientVersion();
6634
6635 switch(attachment)
6636 {
6637 case GL_COLOR_ATTACHMENT1:
6638 case GL_COLOR_ATTACHMENT2:
6639 case GL_COLOR_ATTACHMENT3:
6640 case GL_COLOR_ATTACHMENT4:
6641 case GL_COLOR_ATTACHMENT5:
6642 case GL_COLOR_ATTACHMENT6:
6643 case GL_COLOR_ATTACHMENT7:
6644 case GL_COLOR_ATTACHMENT8:
6645 case GL_COLOR_ATTACHMENT9:
6646 case GL_COLOR_ATTACHMENT10:
6647 case GL_COLOR_ATTACHMENT11:
6648 case GL_COLOR_ATTACHMENT12:
6649 case GL_COLOR_ATTACHMENT13:
6650 case GL_COLOR_ATTACHMENT14:
6651 case GL_COLOR_ATTACHMENT15:
6652 case GL_COLOR_ATTACHMENT16:
6653 case GL_COLOR_ATTACHMENT17:
6654 case GL_COLOR_ATTACHMENT18:
6655 case GL_COLOR_ATTACHMENT19:
6656 case GL_COLOR_ATTACHMENT20:
6657 case GL_COLOR_ATTACHMENT21:
6658 case GL_COLOR_ATTACHMENT22:
6659 case GL_COLOR_ATTACHMENT23:
6660 case GL_COLOR_ATTACHMENT24:
6661 case GL_COLOR_ATTACHMENT25:
6662 case GL_COLOR_ATTACHMENT26:
6663 case GL_COLOR_ATTACHMENT27:
6664 case GL_COLOR_ATTACHMENT28:
6665 case GL_COLOR_ATTACHMENT29:
6666 case GL_COLOR_ATTACHMENT30:
6667 case GL_COLOR_ATTACHMENT31:
6668 if(clientVersion < 3)
6669 {
6670 return error(GL_INVALID_ENUM);
6671 }
6672 // fall through
6673 case GL_COLOR_ATTACHMENT0:
6674 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6675 {
6676 return error(GL_INVALID_ENUM);
6677 }
6678 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6679 break;
6680 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6681 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6682 default:
6683 return error(GL_INVALID_ENUM);
6684 }
6685 }
6686}
6687
6688void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6689{
6690 if(egl::getClientVersion() == 1)
6691 {
6692 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6693 }
6694
6695 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6696
6697 switch(target)
6698 {
6699 case GL_TEXTURE_2D:
6700 case GL_TEXTURE_EXTERNAL_OES:
6701 break;
6702 default:
6703 return error(GL_INVALID_ENUM);
6704 }
6705
Nicolas Capens0bac2852016-05-07 06:09:58 -04006706 es2::Context *context = es2::getContext();
6707
6708 if(context)
6709 {
Nicolas Capens58df2f62016-06-07 14:48:56 -04006710 es2::Texture2D *texture = nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006711
6712 switch(target)
6713 {
6714 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
6715 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
6716 default: UNREACHABLE(target);
6717 }
6718
6719 if(!texture)
6720 {
6721 return error(GL_INVALID_OPERATION);
6722 }
6723
Nicolas Capens58df2f62016-06-07 14:48:56 -04006724 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006725
Nicolas Capens58df2f62016-06-07 14:48:56 -04006726 if(!eglImage)
6727 {
6728 return error(GL_INVALID_OPERATION);
6729 }
6730
6731 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006732 }
6733}
6734
6735void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6736{
6737 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6738
6739 UNIMPLEMENTED();
6740}
6741
6742GLboolean IsRenderbufferOES(GLuint renderbuffer)
6743{
6744 return IsRenderbuffer(renderbuffer);
6745}
6746
6747void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6748{
6749 BindRenderbuffer(target, renderbuffer);
6750}
6751
6752void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6753{
6754 DeleteRenderbuffers(n, renderbuffers);
6755}
6756
6757void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6758{
6759 GenRenderbuffers(n, renderbuffers);
6760}
6761
6762void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6763{
6764 RenderbufferStorage(target, internalformat, width, height);
6765}
6766
6767void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6768{
6769 GetRenderbufferParameteriv(target, pname, params);
6770}
6771
6772GLboolean IsFramebufferOES(GLuint framebuffer)
6773{
6774 return IsFramebuffer(framebuffer);
6775}
6776
6777void BindFramebufferOES(GLenum target, GLuint framebuffer)
6778{
6779 BindFramebuffer(target, framebuffer);
6780}
6781
6782void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6783{
6784 DeleteFramebuffers(n, framebuffers);
6785}
6786
6787void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6788{
6789 GenFramebuffers(n, framebuffers);
6790}
6791
6792GLenum CheckFramebufferStatusOES(GLenum target)
6793{
6794 return CheckFramebufferStatus(target);
6795}
6796
6797void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6798{
6799 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6800}
6801
6802void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6803{
6804 FramebufferTexture2D(target, attachment, textarget, texture, level);
6805}
6806
6807void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6808{
6809 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6810}
6811
6812void GenerateMipmapOES(GLenum target)
6813{
6814 GenerateMipmap(target);
6815}
6816
6817void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6818{
6819 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6820
6821 if(n < 0 || n > MAX_DRAW_BUFFERS)
6822 {
6823 return error(GL_INVALID_VALUE);
6824 }
6825
6826 es2::Context *context = es2::getContext();
6827
6828 if(context)
6829 {
6830 GLuint drawFramebufferName = context->getDrawFramebufferName();
6831
6832 if((drawFramebufferName == 0) && (n != 1))
6833 {
6834 return error(GL_INVALID_OPERATION);
6835 }
6836
6837 for(unsigned int i = 0; i < (unsigned)n; i++)
6838 {
6839 switch(bufs[i])
6840 {
6841 case GL_BACK:
6842 if(drawFramebufferName != 0)
6843 {
6844 return error(GL_INVALID_OPERATION);
6845 }
6846 break;
6847 case GL_NONE:
6848 break;
6849 case GL_COLOR_ATTACHMENT0_EXT:
6850 case GL_COLOR_ATTACHMENT1_EXT:
6851 case GL_COLOR_ATTACHMENT2_EXT:
6852 case GL_COLOR_ATTACHMENT3_EXT:
6853 case GL_COLOR_ATTACHMENT4_EXT:
6854 case GL_COLOR_ATTACHMENT5_EXT:
6855 case GL_COLOR_ATTACHMENT6_EXT:
6856 case GL_COLOR_ATTACHMENT7_EXT:
6857 case GL_COLOR_ATTACHMENT8_EXT:
6858 case GL_COLOR_ATTACHMENT9_EXT:
6859 case GL_COLOR_ATTACHMENT10_EXT:
6860 case GL_COLOR_ATTACHMENT11_EXT:
6861 case GL_COLOR_ATTACHMENT12_EXT:
6862 case GL_COLOR_ATTACHMENT13_EXT:
6863 case GL_COLOR_ATTACHMENT14_EXT:
6864 case GL_COLOR_ATTACHMENT15_EXT:
6865 {
6866 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6867
6868 if(index >= MAX_COLOR_ATTACHMENTS)
6869 {
6870 return error(GL_INVALID_OPERATION);
6871 }
6872
6873 if(index != i)
6874 {
6875 return error(GL_INVALID_OPERATION);
6876 }
6877
6878 if(drawFramebufferName == 0)
6879 {
6880 return error(GL_INVALID_OPERATION);
6881 }
6882 }
6883 break;
6884 default:
6885 return error(GL_INVALID_ENUM);
6886 }
6887 }
6888
6889 context->setFramebufferDrawBuffers(n, bufs);
6890 }
6891}
6892
6893}
6894
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006895extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006896{
6897 struct Extension
6898 {
6899 const char *name;
6900 __eglMustCastToProperFunctionPointerType address;
6901 };
6902
6903 static const Extension glExtensions[] =
6904 {
6905 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6906
6907 EXTENSION(glTexImage3DOES),
6908 EXTENSION(glBlitFramebufferANGLE),
6909 EXTENSION(glBlitFramebufferNV),
6910 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6911 EXTENSION(glDeleteFencesNV),
6912 EXTENSION(glGenFencesNV),
6913 EXTENSION(glIsFenceNV),
6914 EXTENSION(glTestFenceNV),
6915 EXTENSION(glGetFenceivNV),
6916 EXTENSION(glFinishFenceNV),
6917 EXTENSION(glSetFenceNV),
6918 EXTENSION(glGetGraphicsResetStatusEXT),
6919 EXTENSION(glReadnPixelsEXT),
6920 EXTENSION(glGetnUniformfvEXT),
6921 EXTENSION(glGetnUniformivEXT),
6922 EXTENSION(glGenQueriesEXT),
6923 EXTENSION(glDeleteQueriesEXT),
6924 EXTENSION(glIsQueryEXT),
6925 EXTENSION(glBeginQueryEXT),
6926 EXTENSION(glEndQueryEXT),
6927 EXTENSION(glGetQueryivEXT),
6928 EXTENSION(glGetQueryObjectuivEXT),
6929 EXTENSION(glEGLImageTargetTexture2DOES),
6930 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
6931 EXTENSION(glDrawElementsInstancedEXT),
6932 EXTENSION(glDrawArraysInstancedEXT),
6933 EXTENSION(glVertexAttribDivisorEXT),
6934 EXTENSION(glDrawArraysInstancedANGLE),
6935 EXTENSION(glDrawElementsInstancedANGLE),
6936 EXTENSION(glVertexAttribDivisorANGLE),
6937 EXTENSION(glIsRenderbufferOES),
6938 EXTENSION(glBindRenderbufferOES),
6939 EXTENSION(glDeleteRenderbuffersOES),
6940 EXTENSION(glGenRenderbuffersOES),
6941 EXTENSION(glRenderbufferStorageOES),
6942 EXTENSION(glGetRenderbufferParameterivOES),
6943 EXTENSION(glIsFramebufferOES),
6944 EXTENSION(glBindFramebufferOES),
6945 EXTENSION(glDeleteFramebuffersOES),
6946 EXTENSION(glGenFramebuffersOES),
6947 EXTENSION(glCheckFramebufferStatusOES),
6948 EXTENSION(glFramebufferRenderbufferOES),
6949 EXTENSION(glFramebufferTexture2DOES),
6950 EXTENSION(glGetFramebufferAttachmentParameterivOES),
6951 EXTENSION(glGenerateMipmapOES),
6952 EXTENSION(glDrawBuffersEXT),
6953
6954 #undef EXTENSION
6955 };
6956
6957 for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
6958 {
6959 if(strcmp(procname, glExtensions[ext].name) == 0)
6960 {
6961 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
6962 }
6963 }
6964
6965 return nullptr;
6966}