blob: 3d7aa427f3b5a46ac84d49faf65b8ef30ac81c76 [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 {
905
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500906 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500907 if(validationError != GL_NONE)
908 {
909 return error(validationError);
910 }
911
912 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
913 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400914 break;
915 default: UNREACHABLE(target);
916 }
917 }
918 }
919}
920
921void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
922 GLenum format, GLsizei imageSize, const GLvoid* data)
923{
924 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
925 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
926 "GLsizei imageSize = %d, const GLvoid* data = %p)",
927 target, level, xoffset, yoffset, width, height, format, imageSize, data);
928
929 if(!es2::IsTextureTarget(target))
930 {
931 return error(GL_INVALID_ENUM);
932 }
933
934 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
935 {
936 return error(GL_INVALID_VALUE);
937 }
938
939 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
940 {
941 return error(GL_INVALID_VALUE);
942 }
943
944 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
945 if(validationError != GL_NONE)
946 {
947 return error(validationError);
948 }
949
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500950 if(imageSize != egl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400951 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500952 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400953 }
954
955 es2::Context *context = es2::getContext();
956
957 if(context)
958 {
959 if(imageSize != egl::ComputeCompressedSize(width, height, format))
960 {
961 return error(GL_INVALID_VALUE);
962 }
963
964 if(xoffset % 4 != 0 || yoffset % 4 != 0)
965 {
966 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
967 return error(GL_INVALID_OPERATION);
968 }
969
970 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_NONE);
971
972 if(target == GL_TEXTURE_2D)
973 {
974 es2::Texture2D *texture = context->getTexture2D();
975
976 GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
977
978 if(validationError == GL_NONE)
979 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500980 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500981 }
982
983 if(validationError == GL_NONE)
984 {
985 texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400986 }
987 else
988 {
989 return error(validationError);
990 }
991 }
992 else if(es2::IsCubemapTextureTarget(target))
993 {
994 es2::TextureCubeMap *texture = context->getTextureCubeMap();
995
996 GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
997
998 if(validationError == GL_NONE)
999 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -05001000 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05001001 }
1002
1003 if(validationError == GL_NONE)
1004 {
1005 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001006 }
1007 else
1008 {
1009 return error(validationError);
1010 }
1011 }
1012 else UNREACHABLE(target);
1013 }
1014}
1015
1016void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
1017{
1018 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
1019 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
1020 target, level, internalformat, x, y, width, height, border);
1021
1022 if(!validImageSize(level, width, height))
1023 {
1024 return error(GL_INVALID_VALUE);
1025 }
1026
1027 if(border != 0)
1028 {
1029 return error(GL_INVALID_VALUE);
1030 }
1031
1032 es2::Context *context = es2::getContext();
1033
1034 if(context)
1035 {
1036 switch(target)
1037 {
1038 case GL_TEXTURE_2D:
1039 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
1040 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
1041 {
1042 return error(GL_INVALID_VALUE);
1043 }
1044 break;
1045 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1046 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1047 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1048 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1049 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1050 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1051 if(width != height)
1052 {
1053 return error(GL_INVALID_VALUE);
1054 }
1055
1056 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
1057 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
1058 {
1059 return error(GL_INVALID_VALUE);
1060 }
1061 break;
1062 default:
1063 return error(GL_INVALID_ENUM);
1064 }
1065
1066 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1067
1068 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1069 {
1070 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1071 }
1072
1073 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1074
1075 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1076 {
1077 return error(GL_INVALID_OPERATION);
1078 }
1079
1080 GLenum colorbufferFormat = source->getFormat();
1081
1082 if(!validateColorBufferFormat(internalformat, colorbufferFormat))
1083 {
1084 return;
1085 }
1086
1087 if(target == GL_TEXTURE_2D)
1088 {
1089 es2::Texture2D *texture = context->getTexture2D();
1090
1091 if(!texture)
1092 {
1093 return error(GL_INVALID_OPERATION);
1094 }
1095
1096 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
1097 }
1098 else if(es2::IsCubemapTextureTarget(target))
1099 {
1100 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1101
1102 if(!texture)
1103 {
1104 return error(GL_INVALID_OPERATION);
1105 }
1106
1107 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1108 }
1109 else UNREACHABLE(target);
1110 }
1111}
1112
1113void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1114{
1115 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1116 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1117 target, level, xoffset, yoffset, x, y, width, height);
1118
1119 if(!es2::IsTextureTarget(target))
1120 {
1121 return error(GL_INVALID_ENUM);
1122 }
1123
1124 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1125 {
1126 return error(GL_INVALID_VALUE);
1127 }
1128
1129 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1130 {
1131 return error(GL_INVALID_VALUE);
1132 }
1133
1134 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1135 {
1136 return error(GL_INVALID_VALUE);
1137 }
1138
1139 if(width == 0 || height == 0)
1140 {
1141 return;
1142 }
1143
1144 es2::Context *context = es2::getContext();
1145
1146 if(context)
1147 {
1148 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1149
1150 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1151 {
1152 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1153 }
1154
1155 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1156
1157 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1158 {
1159 return error(GL_INVALID_OPERATION);
1160 }
1161
1162 es2::Texture *texture = nullptr;
1163
1164 if(target == GL_TEXTURE_2D)
1165 {
1166 texture = context->getTexture2D();
1167 }
1168 else if(es2::IsCubemapTextureTarget(target))
1169 {
1170 texture = context->getTextureCubeMap();
1171 }
1172 else UNREACHABLE(target);
1173
1174 GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture);
1175 if(validationError != GL_NONE)
1176 {
1177 return error(validationError);
1178 }
1179
1180 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
1181 }
1182}
1183
1184GLuint CreateProgram(void)
1185{
1186 TRACE("()");
1187
1188 es2::Context *context = es2::getContext();
1189
1190 if(context)
1191 {
1192 return context->createProgram();
1193 }
1194
1195 return 0;
1196}
1197
1198GLuint CreateShader(GLenum type)
1199{
1200 TRACE("(GLenum type = 0x%X)", type);
1201
1202 es2::Context *context = es2::getContext();
1203
1204 if(context)
1205 {
1206 switch(type)
1207 {
1208 case GL_FRAGMENT_SHADER:
1209 case GL_VERTEX_SHADER:
1210 return context->createShader(type);
1211 default:
1212 return error(GL_INVALID_ENUM, 0);
1213 }
1214 }
1215
1216 return 0;
1217}
1218
1219void CullFace(GLenum mode)
1220{
1221 TRACE("(GLenum mode = 0x%X)", mode);
1222
1223 switch(mode)
1224 {
1225 case GL_FRONT:
1226 case GL_BACK:
1227 case GL_FRONT_AND_BACK:
1228 {
1229 es2::Context *context = es2::getContext();
1230
1231 if(context)
1232 {
1233 context->setCullMode(mode);
1234 }
1235 }
1236 break;
1237 default:
1238 return error(GL_INVALID_ENUM);
1239 }
1240}
1241
1242void DeleteBuffers(GLsizei n, const GLuint* buffers)
1243{
1244 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1245
1246 if(n < 0)
1247 {
1248 return error(GL_INVALID_VALUE);
1249 }
1250
1251 es2::Context *context = es2::getContext();
1252
1253 if(context)
1254 {
1255 for(int i = 0; i < n; i++)
1256 {
1257 context->deleteBuffer(buffers[i]);
1258 }
1259 }
1260}
1261
1262void DeleteFencesNV(GLsizei n, const GLuint* fences)
1263{
1264 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1265
1266 if(n < 0)
1267 {
1268 return error(GL_INVALID_VALUE);
1269 }
1270
1271 es2::Context *context = es2::getContext();
1272
1273 if(context)
1274 {
1275 for(int i = 0; i < n; i++)
1276 {
1277 context->deleteFence(fences[i]);
1278 }
1279 }
1280}
1281
1282void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1283{
1284 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1285
1286 if(n < 0)
1287 {
1288 return error(GL_INVALID_VALUE);
1289 }
1290
1291 es2::Context *context = es2::getContext();
1292
1293 if(context)
1294 {
1295 for(int i = 0; i < n; i++)
1296 {
1297 if(framebuffers[i] != 0)
1298 {
1299 context->deleteFramebuffer(framebuffers[i]);
1300 }
1301 }
1302 }
1303}
1304
1305void DeleteProgram(GLuint program)
1306{
1307 TRACE("(GLuint program = %d)", program);
1308
1309 if(program == 0)
1310 {
1311 return;
1312 }
1313
1314 es2::Context *context = es2::getContext();
1315
1316 if(context)
1317 {
1318 if(!context->getProgram(program))
1319 {
1320 if(context->getShader(program))
1321 {
1322 return error(GL_INVALID_OPERATION);
1323 }
1324 else
1325 {
1326 return error(GL_INVALID_VALUE);
1327 }
1328 }
1329
1330 context->deleteProgram(program);
1331 }
1332}
1333
1334void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1335{
1336 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1337
1338 if(n < 0)
1339 {
1340 return error(GL_INVALID_VALUE);
1341 }
1342
1343 es2::Context *context = es2::getContext();
1344
1345 if(context)
1346 {
1347 for(int i = 0; i < n; i++)
1348 {
1349 context->deleteQuery(ids[i]);
1350 }
1351 }
1352}
1353
1354void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1355{
1356 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1357
1358 if(n < 0)
1359 {
1360 return error(GL_INVALID_VALUE);
1361 }
1362
1363 es2::Context *context = es2::getContext();
1364
1365 if(context)
1366 {
1367 for(int i = 0; i < n; i++)
1368 {
1369 context->deleteRenderbuffer(renderbuffers[i]);
1370 }
1371 }
1372}
1373
1374void DeleteShader(GLuint shader)
1375{
1376 TRACE("(GLuint shader = %d)", shader);
1377
1378 if(shader == 0)
1379 {
1380 return;
1381 }
1382
1383 es2::Context *context = es2::getContext();
1384
1385 if(context)
1386 {
1387 if(!context->getShader(shader))
1388 {
1389 if(context->getProgram(shader))
1390 {
1391 return error(GL_INVALID_OPERATION);
1392 }
1393 else
1394 {
1395 return error(GL_INVALID_VALUE);
1396 }
1397 }
1398
1399 context->deleteShader(shader);
1400 }
1401}
1402
1403void DeleteTextures(GLsizei n, const GLuint* textures)
1404{
1405 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1406
1407 if(n < 0)
1408 {
1409 return error(GL_INVALID_VALUE);
1410 }
1411
1412 es2::Context *context = es2::getContext();
1413
1414 if(context)
1415 {
1416 for(int i = 0; i < n; i++)
1417 {
1418 if(textures[i] != 0)
1419 {
1420 context->deleteTexture(textures[i]);
1421 }
1422 }
1423 }
1424}
1425
1426void DepthFunc(GLenum func)
1427{
1428 TRACE("(GLenum func = 0x%X)", func);
1429
1430 switch(func)
1431 {
1432 case GL_NEVER:
1433 case GL_ALWAYS:
1434 case GL_LESS:
1435 case GL_LEQUAL:
1436 case GL_EQUAL:
1437 case GL_GREATER:
1438 case GL_GEQUAL:
1439 case GL_NOTEQUAL:
1440 break;
1441 default:
1442 return error(GL_INVALID_ENUM);
1443 }
1444
1445 es2::Context *context = es2::getContext();
1446
1447 if(context)
1448 {
1449 context->setDepthFunc(func);
1450 }
1451}
1452
1453void DepthMask(GLboolean flag)
1454{
1455 TRACE("(GLboolean flag = %d)", flag);
1456
1457 es2::Context *context = es2::getContext();
1458
1459 if(context)
1460 {
1461 context->setDepthMask(flag != GL_FALSE);
1462 }
1463}
1464
1465void DepthRangef(GLclampf zNear, GLclampf zFar)
1466{
1467 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1468
1469 es2::Context *context = es2::getContext();
1470
1471 if(context)
1472 {
1473 context->setDepthRange(zNear, zFar);
1474 }
1475}
1476
1477void DetachShader(GLuint program, GLuint shader)
1478{
1479 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1480
1481 es2::Context *context = es2::getContext();
1482
1483 if(context)
1484 {
1485
1486 es2::Program *programObject = context->getProgram(program);
1487 es2::Shader *shaderObject = context->getShader(shader);
1488
1489 if(!programObject)
1490 {
1491 es2::Shader *shaderByProgramHandle;
1492 shaderByProgramHandle = context->getShader(program);
1493 if(!shaderByProgramHandle)
1494 {
1495 return error(GL_INVALID_VALUE);
1496 }
1497 else
1498 {
1499 return error(GL_INVALID_OPERATION);
1500 }
1501 }
1502
1503 if(!shaderObject)
1504 {
1505 es2::Program *programByShaderHandle = context->getProgram(shader);
1506 if(!programByShaderHandle)
1507 {
1508 return error(GL_INVALID_VALUE);
1509 }
1510 else
1511 {
1512 return error(GL_INVALID_OPERATION);
1513 }
1514 }
1515
1516 if(!programObject->detachShader(shaderObject))
1517 {
1518 return error(GL_INVALID_OPERATION);
1519 }
1520 }
1521}
1522
1523void Disable(GLenum cap)
1524{
1525 TRACE("(GLenum cap = 0x%X)", cap);
1526
1527 es2::Context *context = es2::getContext();
1528
1529 if(context)
1530 {
1531 switch(cap)
1532 {
1533 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1534 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1535 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1536 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1537 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1538 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1539 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1540 case GL_BLEND: context->setBlendEnabled(false); break;
1541 case GL_DITHER: context->setDitherEnabled(false); break;
1542 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1543 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1544 default:
1545 return error(GL_INVALID_ENUM);
1546 }
1547 }
1548}
1549
1550void DisableVertexAttribArray(GLuint index)
1551{
1552 TRACE("(GLuint index = %d)", index);
1553
1554 if(index >= es2::MAX_VERTEX_ATTRIBS)
1555 {
1556 return error(GL_INVALID_VALUE);
1557 }
1558
1559 es2::Context *context = es2::getContext();
1560
1561 if(context)
1562 {
1563 context->setVertexAttribArrayEnabled(index, false);
1564 }
1565}
1566
1567void DrawArrays(GLenum mode, GLint first, GLsizei count)
1568{
1569 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1570
1571 switch(mode)
1572 {
1573 case GL_POINTS:
1574 case GL_LINES:
1575 case GL_LINE_LOOP:
1576 case GL_LINE_STRIP:
1577 case GL_TRIANGLES:
1578 case GL_TRIANGLE_FAN:
1579 case GL_TRIANGLE_STRIP:
1580 break;
1581 default:
1582 return error(GL_INVALID_ENUM);
1583 }
1584
1585 if(count < 0 || first < 0)
1586 {
1587 return error(GL_INVALID_VALUE);
1588 }
1589
1590 es2::Context *context = es2::getContext();
1591
1592 if(context)
1593 {
1594 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1595 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1596 {
1597 return error(GL_INVALID_OPERATION);
1598 }
1599
1600 context->drawArrays(mode, first, count);
1601 }
1602}
1603
1604void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1605{
1606 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1607 mode, count, type, indices);
1608
1609 switch(mode)
1610 {
1611 case GL_POINTS:
1612 case GL_LINES:
1613 case GL_LINE_LOOP:
1614 case GL_LINE_STRIP:
1615 case GL_TRIANGLES:
1616 case GL_TRIANGLE_FAN:
1617 case GL_TRIANGLE_STRIP:
1618 break;
1619 default:
1620 return error(GL_INVALID_ENUM);
1621 }
1622
1623 if(count < 0)
1624 {
1625 return error(GL_INVALID_VALUE);
1626 }
1627
1628 es2::Context *context = es2::getContext();
1629
1630 if(context)
1631 {
1632 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1633 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1634 {
1635 return error(GL_INVALID_OPERATION);
1636 }
1637
1638 switch(type)
1639 {
1640 case GL_UNSIGNED_BYTE:
1641 case GL_UNSIGNED_SHORT:
1642 case GL_UNSIGNED_INT:
1643 break;
1644 default:
1645 return error(GL_INVALID_ENUM);
1646 }
1647
1648 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1649 }
1650}
1651
1652void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1653{
1654 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1655 mode, first, count, instanceCount);
1656
1657 switch(mode)
1658 {
1659 case GL_POINTS:
1660 case GL_LINES:
1661 case GL_LINE_LOOP:
1662 case GL_LINE_STRIP:
1663 case GL_TRIANGLES:
1664 case GL_TRIANGLE_FAN:
1665 case GL_TRIANGLE_STRIP:
1666 break;
1667 default:
1668 return error(GL_INVALID_ENUM);
1669 }
1670
1671 if(count < 0 || instanceCount < 0)
1672 {
1673 return error(GL_INVALID_VALUE);
1674 }
1675
1676 es2::Context *context = es2::getContext();
1677
1678 if(context)
1679 {
1680 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1681 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1682 {
1683 return error(GL_INVALID_OPERATION);
1684 }
1685
1686 context->drawArrays(mode, first, count, instanceCount);
1687 }
1688}
1689
1690void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1691{
1692 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1693 mode, count, type, indices, instanceCount);
1694
1695 switch(mode)
1696 {
1697 case GL_POINTS:
1698 case GL_LINES:
1699 case GL_LINE_LOOP:
1700 case GL_LINE_STRIP:
1701 case GL_TRIANGLES:
1702 case GL_TRIANGLE_FAN:
1703 case GL_TRIANGLE_STRIP:
1704 break;
1705 default:
1706 return error(GL_INVALID_ENUM);
1707 }
1708
1709 switch(type)
1710 {
1711 case GL_UNSIGNED_BYTE:
1712 case GL_UNSIGNED_SHORT:
1713 case GL_UNSIGNED_INT:
1714 break;
1715 default:
1716 return error(GL_INVALID_ENUM);
1717 }
1718
1719 if(count < 0 || instanceCount < 0)
1720 {
1721 return error(GL_INVALID_VALUE);
1722 }
1723
1724 es2::Context *context = es2::getContext();
1725
1726 if(context)
1727 {
1728 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1729 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1730 {
1731 return error(GL_INVALID_OPERATION);
1732 }
1733
1734 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1735 }
1736}
1737
1738void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1739{
1740 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1741
1742 es2::Context *context = es2::getContext();
1743
1744 if(context)
1745 {
1746 if(index >= es2::MAX_VERTEX_ATTRIBS)
1747 {
1748 return error(GL_INVALID_VALUE);
1749 }
1750
1751 context->setVertexAttribDivisor(index, divisor);
1752 }
1753}
1754
1755void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1756{
1757 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1758 mode, first, count, instanceCount);
1759
1760 switch(mode)
1761 {
1762 case GL_POINTS:
1763 case GL_LINES:
1764 case GL_LINE_LOOP:
1765 case GL_LINE_STRIP:
1766 case GL_TRIANGLES:
1767 case GL_TRIANGLE_FAN:
1768 case GL_TRIANGLE_STRIP:
1769 break;
1770 default:
1771 return error(GL_INVALID_ENUM);
1772 }
1773
1774 if(count < 0 || instanceCount < 0)
1775 {
1776 return error(GL_INVALID_VALUE);
1777 }
1778
1779 es2::Context *context = es2::getContext();
1780
1781 if(context)
1782 {
1783 if(!context->hasZeroDivisor())
1784 {
1785 return error(GL_INVALID_OPERATION);
1786 }
1787
1788 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1789 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1790 {
1791 return error(GL_INVALID_OPERATION);
1792 }
1793
1794 context->drawArrays(mode, first, count, instanceCount);
1795 }
1796}
1797
1798void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1799{
1800 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1801 mode, count, type, indices, instanceCount);
1802
1803 switch(mode)
1804 {
1805 case GL_POINTS:
1806 case GL_LINES:
1807 case GL_LINE_LOOP:
1808 case GL_LINE_STRIP:
1809 case GL_TRIANGLES:
1810 case GL_TRIANGLE_FAN:
1811 case GL_TRIANGLE_STRIP:
1812 break;
1813 default:
1814 return error(GL_INVALID_ENUM);
1815 }
1816
1817 switch(type)
1818 {
1819 case GL_UNSIGNED_BYTE:
1820 case GL_UNSIGNED_SHORT:
1821 case GL_UNSIGNED_INT:
1822 break;
1823 default:
1824 return error(GL_INVALID_ENUM);
1825 }
1826
1827 if(count < 0 || instanceCount < 0)
1828 {
1829 return error(GL_INVALID_VALUE);
1830 }
1831
1832 es2::Context *context = es2::getContext();
1833
1834 if(context)
1835 {
1836 if(!context->hasZeroDivisor())
1837 {
1838 return error(GL_INVALID_OPERATION);
1839 }
1840
1841 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1842 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1843 {
1844 return error(GL_INVALID_OPERATION);
1845 }
1846
1847 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1848 }
1849}
1850
1851void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1852{
1853 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1854
1855 es2::Context *context = es2::getContext();
1856
1857 if(context)
1858 {
1859 if(index >= MAX_VERTEX_ATTRIBS)
1860 {
1861 return error(GL_INVALID_VALUE);
1862 }
1863
1864 context->setVertexAttribDivisor(index, divisor);
1865 }
1866}
1867
1868void Enable(GLenum cap)
1869{
1870 TRACE("(GLenum cap = 0x%X)", cap);
1871
1872 es2::Context *context = es2::getContext();
1873
1874 if(context)
1875 {
1876 switch(cap)
1877 {
1878 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1879 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1880 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1881 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1882 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1883 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1884 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1885 case GL_BLEND: context->setBlendEnabled(true); break;
1886 case GL_DITHER: context->setDitherEnabled(true); break;
1887 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1888 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1889 default:
1890 return error(GL_INVALID_ENUM);
1891 }
1892 }
1893}
1894
1895void EnableVertexAttribArray(GLuint index)
1896{
1897 TRACE("(GLuint index = %d)", index);
1898
1899 if(index >= es2::MAX_VERTEX_ATTRIBS)
1900 {
1901 return error(GL_INVALID_VALUE);
1902 }
1903
1904 es2::Context *context = es2::getContext();
1905
1906 if(context)
1907 {
1908 context->setVertexAttribArrayEnabled(index, true);
1909 }
1910}
1911
1912void EndQueryEXT(GLenum target)
1913{
1914 TRACE("GLenum target = 0x%X)", target);
1915
1916 switch(target)
1917 {
1918 case GL_ANY_SAMPLES_PASSED_EXT:
1919 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1920 break;
1921 default:
1922 return error(GL_INVALID_ENUM);
1923 }
1924
1925 es2::Context *context = es2::getContext();
1926
1927 if(context)
1928 {
1929 context->endQuery(target);
1930 }
1931}
1932
1933void FinishFenceNV(GLuint fence)
1934{
1935 TRACE("(GLuint fence = %d)", fence);
1936
1937 es2::Context *context = es2::getContext();
1938
1939 if(context)
1940 {
1941 es2::Fence *fenceObject = context->getFence(fence);
1942
1943 if(!fenceObject)
1944 {
1945 return error(GL_INVALID_OPERATION);
1946 }
1947
1948 fenceObject->finishFence();
1949 }
1950}
1951
1952void Finish(void)
1953{
1954 TRACE("()");
1955
1956 es2::Context *context = es2::getContext();
1957
1958 if(context)
1959 {
1960 context->finish();
1961 }
1962}
1963
1964void Flush(void)
1965{
1966 TRACE("()");
1967
1968 es2::Context *context = es2::getContext();
1969
1970 if(context)
1971 {
1972 context->flush();
1973 }
1974}
1975
1976void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1977{
1978 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1979 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1980
1981 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) ||
1982 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1983 {
1984 return error(GL_INVALID_ENUM);
1985 }
1986
1987 es2::Context *context = es2::getContext();
1988
1989 if(context)
1990 {
1991 es2::Framebuffer *framebuffer = nullptr;
1992 GLuint framebufferName = 0;
1993 if(target == GL_READ_FRAMEBUFFER_ANGLE)
1994 {
1995 framebuffer = context->getReadFramebuffer();
1996 framebufferName = context->getReadFramebufferName();
1997 }
1998 else
1999 {
2000 framebuffer = context->getDrawFramebuffer();
2001 framebufferName = context->getDrawFramebufferName();
2002 }
2003
2004 if(!framebuffer || framebufferName == 0)
2005 {
2006 return error(GL_INVALID_OPERATION);
2007 }
2008
2009 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2010 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2011 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2012 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2013 if(renderbuffer != 0)
2014 {
2015 if(!context->getRenderbuffer(renderbuffer))
2016 {
2017 return error(GL_INVALID_OPERATION);
2018 }
2019 }
2020
2021 GLint clientVersion = context->getClientVersion();
2022
2023 switch(attachment)
2024 {
2025 case GL_COLOR_ATTACHMENT0:
2026 case GL_COLOR_ATTACHMENT1:
2027 case GL_COLOR_ATTACHMENT2:
2028 case GL_COLOR_ATTACHMENT3:
2029 case GL_COLOR_ATTACHMENT4:
2030 case GL_COLOR_ATTACHMENT5:
2031 case GL_COLOR_ATTACHMENT6:
2032 case GL_COLOR_ATTACHMENT7:
2033 case GL_COLOR_ATTACHMENT8:
2034 case GL_COLOR_ATTACHMENT9:
2035 case GL_COLOR_ATTACHMENT10:
2036 case GL_COLOR_ATTACHMENT11:
2037 case GL_COLOR_ATTACHMENT12:
2038 case GL_COLOR_ATTACHMENT13:
2039 case GL_COLOR_ATTACHMENT14:
2040 case GL_COLOR_ATTACHMENT15:
2041 case GL_COLOR_ATTACHMENT16:
2042 case GL_COLOR_ATTACHMENT17:
2043 case GL_COLOR_ATTACHMENT18:
2044 case GL_COLOR_ATTACHMENT19:
2045 case GL_COLOR_ATTACHMENT20:
2046 case GL_COLOR_ATTACHMENT21:
2047 case GL_COLOR_ATTACHMENT22:
2048 case GL_COLOR_ATTACHMENT23:
2049 case GL_COLOR_ATTACHMENT24:
2050 case GL_COLOR_ATTACHMENT25:
2051 case GL_COLOR_ATTACHMENT26:
2052 case GL_COLOR_ATTACHMENT27:
2053 case GL_COLOR_ATTACHMENT28:
2054 case GL_COLOR_ATTACHMENT29:
2055 case GL_COLOR_ATTACHMENT30:
2056 case GL_COLOR_ATTACHMENT31:
2057 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2058 {
2059 return error(GL_INVALID_ENUM);
2060 }
2061 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
2062 break;
2063 case GL_DEPTH_ATTACHMENT:
2064 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
2065 break;
2066 case GL_STENCIL_ATTACHMENT:
2067 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
2068 break;
2069 case GL_DEPTH_STENCIL_ATTACHMENT:
2070 if(clientVersion >= 3)
2071 {
2072 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
2073 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
2074 break;
2075 }
2076 else return error(GL_INVALID_ENUM);
2077 default:
2078 return error(GL_INVALID_ENUM);
2079 }
2080 }
2081}
2082
2083void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
2084{
2085 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
2086 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
2087
2088 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2089 {
2090 return error(GL_INVALID_ENUM);
2091 }
2092
2093 es2::Context *context = es2::getContext();
2094
2095 if(context)
2096 {
Nicolas Capensd5401e22017-03-16 17:32:43 -04002097 GLint clientVersion = context->getClientVersion();
2098
Nicolas Capens0bac2852016-05-07 06:09:58 -04002099 if(texture == 0)
2100 {
2101 textarget = GL_NONE;
2102 }
2103 else
2104 {
2105 es2::Texture *tex = context->getTexture(texture);
2106
2107 if(!tex)
2108 {
2109 return error(GL_INVALID_OPERATION);
2110 }
2111
2112 switch(textarget)
2113 {
2114 case GL_TEXTURE_2D:
2115 if(tex->getTarget() != GL_TEXTURE_2D)
2116 {
2117 return error(GL_INVALID_OPERATION);
2118 }
2119 break;
2120 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2121 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2122 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2123 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2124 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2125 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2126 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2127 {
2128 return error(GL_INVALID_OPERATION);
2129 }
2130 break;
2131 default:
2132 return error(GL_INVALID_ENUM);
2133 }
2134
Nicolas Capensd5401e22017-03-16 17:32:43 -04002135 if((level != 0) && (clientVersion < 3))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002136 {
2137 return error(GL_INVALID_VALUE);
2138 }
2139
2140 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2141 {
2142 return error(GL_INVALID_VALUE);
2143 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002144
2145 if(tex->isCompressed(textarget, level))
2146 {
2147 return error(GL_INVALID_OPERATION);
2148 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002149 }
2150
2151 es2::Framebuffer *framebuffer = nullptr;
2152 GLuint framebufferName = 0;
2153 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2154 {
2155 framebuffer = context->getReadFramebuffer();
2156 framebufferName = context->getReadFramebufferName();
2157 }
2158 else
2159 {
2160 framebuffer = context->getDrawFramebuffer();
2161 framebufferName = context->getDrawFramebufferName();
2162 }
2163
2164 if(framebufferName == 0 || !framebuffer)
2165 {
2166 return error(GL_INVALID_OPERATION);
2167 }
2168
2169 switch(attachment)
2170 {
2171 case GL_COLOR_ATTACHMENT0:
2172 case GL_COLOR_ATTACHMENT1:
2173 case GL_COLOR_ATTACHMENT2:
2174 case GL_COLOR_ATTACHMENT3:
2175 case GL_COLOR_ATTACHMENT4:
2176 case GL_COLOR_ATTACHMENT5:
2177 case GL_COLOR_ATTACHMENT6:
2178 case GL_COLOR_ATTACHMENT7:
2179 case GL_COLOR_ATTACHMENT8:
2180 case GL_COLOR_ATTACHMENT9:
2181 case GL_COLOR_ATTACHMENT10:
2182 case GL_COLOR_ATTACHMENT11:
2183 case GL_COLOR_ATTACHMENT12:
2184 case GL_COLOR_ATTACHMENT13:
2185 case GL_COLOR_ATTACHMENT14:
2186 case GL_COLOR_ATTACHMENT15:
2187 case GL_COLOR_ATTACHMENT16:
2188 case GL_COLOR_ATTACHMENT17:
2189 case GL_COLOR_ATTACHMENT18:
2190 case GL_COLOR_ATTACHMENT19:
2191 case GL_COLOR_ATTACHMENT20:
2192 case GL_COLOR_ATTACHMENT21:
2193 case GL_COLOR_ATTACHMENT22:
2194 case GL_COLOR_ATTACHMENT23:
2195 case GL_COLOR_ATTACHMENT24:
2196 case GL_COLOR_ATTACHMENT25:
2197 case GL_COLOR_ATTACHMENT26:
2198 case GL_COLOR_ATTACHMENT27:
2199 case GL_COLOR_ATTACHMENT28:
2200 case GL_COLOR_ATTACHMENT29:
2201 case GL_COLOR_ATTACHMENT30:
2202 case GL_COLOR_ATTACHMENT31:
2203 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2204 {
2205 return error(GL_INVALID_ENUM);
2206 }
2207 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2208 break;
2209 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2210 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capensd5401e22017-03-16 17:32:43 -04002211 case GL_DEPTH_STENCIL_ATTACHMENT:
2212 if(clientVersion >= 3)
2213 {
2214 framebuffer->setDepthbuffer(textarget, texture, level);
2215 framebuffer->setStencilbuffer(textarget, texture, level);
2216 break;
2217 }
2218 else return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002219 default:
2220 return error(GL_INVALID_ENUM);
2221 }
2222 }
2223}
2224
2225void FrontFace(GLenum mode)
2226{
2227 TRACE("(GLenum mode = 0x%X)", mode);
2228
2229 switch(mode)
2230 {
2231 case GL_CW:
2232 case GL_CCW:
2233 {
2234 es2::Context *context = es2::getContext();
2235
2236 if(context)
2237 {
2238 context->setFrontFace(mode);
2239 }
2240 }
2241 break;
2242 default:
2243 return error(GL_INVALID_ENUM);
2244 }
2245}
2246
2247void GenBuffers(GLsizei n, GLuint* buffers)
2248{
2249 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2250
2251 if(n < 0)
2252 {
2253 return error(GL_INVALID_VALUE);
2254 }
2255
2256 es2::Context *context = es2::getContext();
2257
2258 if(context)
2259 {
2260 for(int i = 0; i < n; i++)
2261 {
2262 buffers[i] = context->createBuffer();
2263 }
2264 }
2265}
2266
2267void GenerateMipmap(GLenum target)
2268{
2269 TRACE("(GLenum target = 0x%X)", target);
2270
2271 es2::Context *context = es2::getContext();
2272
2273 if(context)
2274 {
2275 es2::Texture *texture = nullptr;
2276
2277 GLint clientVersion = context->getClientVersion();
2278
2279 switch(target)
2280 {
2281 case GL_TEXTURE_2D:
2282 texture = context->getTexture2D();
2283 break;
2284 case GL_TEXTURE_CUBE_MAP:
2285 texture = context->getTextureCubeMap();
2286 break;
2287 case GL_TEXTURE_2D_ARRAY:
2288 if(clientVersion < 3)
2289 {
2290 return error(GL_INVALID_ENUM);
2291 }
2292 else
2293 {
2294 texture = context->getTexture2DArray();
2295 }
2296 break;
2297 case GL_TEXTURE_3D_OES:
2298 texture = context->getTexture3D();
2299 break;
2300 default:
2301 return error(GL_INVALID_ENUM);
2302 }
2303
2304 if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
2305 {
2306 return error(GL_INVALID_OPERATION);
2307 }
2308
Alexis Hetu05bcbe62017-11-22 16:44:23 -05002309 if(!IsMipmappable(texture->getFormat(target, 0), texture->getInternalFormat(target, 0), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002310 {
2311 return error(GL_INVALID_OPERATION);
2312 }
2313
Nicolas Capens0bac2852016-05-07 06:09:58 -04002314 texture->generateMipmaps();
2315 }
2316}
2317
2318void GenFencesNV(GLsizei n, GLuint* fences)
2319{
2320 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2321
2322 if(n < 0)
2323 {
2324 return error(GL_INVALID_VALUE);
2325 }
2326
2327 es2::Context *context = es2::getContext();
2328
2329 if(context)
2330 {
2331 for(int i = 0; i < n; i++)
2332 {
2333 fences[i] = context->createFence();
2334 }
2335 }
2336}
2337
2338void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2339{
2340 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2341
2342 if(n < 0)
2343 {
2344 return error(GL_INVALID_VALUE);
2345 }
2346
2347 es2::Context *context = es2::getContext();
2348
2349 if(context)
2350 {
2351 for(int i = 0; i < n; i++)
2352 {
2353 framebuffers[i] = context->createFramebuffer();
2354 }
2355 }
2356}
2357
2358void GenQueriesEXT(GLsizei n, GLuint* ids)
2359{
2360 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2361
2362 if(n < 0)
2363 {
2364 return error(GL_INVALID_VALUE);
2365 }
2366
2367 es2::Context *context = es2::getContext();
2368
2369 if(context)
2370 {
2371 for(int i = 0; i < n; i++)
2372 {
2373 ids[i] = context->createQuery();
2374 }
2375 }
2376}
2377
2378void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2379{
2380 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2381
2382 if(n < 0)
2383 {
2384 return error(GL_INVALID_VALUE);
2385 }
2386
2387 es2::Context *context = es2::getContext();
2388
2389 if(context)
2390 {
2391 for(int i = 0; i < n; i++)
2392 {
2393 renderbuffers[i] = context->createRenderbuffer();
2394 }
2395 }
2396}
2397
2398void GenTextures(GLsizei n, GLuint* textures)
2399{
2400 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2401
2402 if(n < 0)
2403 {
2404 return error(GL_INVALID_VALUE);
2405 }
2406
2407 es2::Context *context = es2::getContext();
2408
2409 if(context)
2410 {
2411 for(int i = 0; i < n; i++)
2412 {
2413 textures[i] = context->createTexture();
2414 }
2415 }
2416}
2417
2418void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2419{
2420 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2421 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2422 program, index, bufsize, length, size, type, name);
2423
2424 if(bufsize < 0)
2425 {
2426 return error(GL_INVALID_VALUE);
2427 }
2428
2429 es2::Context *context = es2::getContext();
2430
2431 if(context)
2432 {
2433 es2::Program *programObject = context->getProgram(program);
2434
2435 if(!programObject)
2436 {
2437 if(context->getShader(program))
2438 {
2439 return error(GL_INVALID_OPERATION);
2440 }
2441 else
2442 {
2443 return error(GL_INVALID_VALUE);
2444 }
2445 }
2446
2447 if(index >= programObject->getActiveAttributeCount())
2448 {
2449 return error(GL_INVALID_VALUE);
2450 }
2451
2452 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2453 }
2454}
2455
2456void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2457{
2458 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2459 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2460 program, index, bufsize, length, size, type, name);
2461
2462 if(bufsize < 0)
2463 {
2464 return error(GL_INVALID_VALUE);
2465 }
2466
2467 es2::Context *context = es2::getContext();
2468
2469 if(context)
2470 {
2471 es2::Program *programObject = context->getProgram(program);
2472
2473 if(!programObject)
2474 {
2475 if(context->getShader(program))
2476 {
2477 return error(GL_INVALID_OPERATION);
2478 }
2479 else
2480 {
2481 return error(GL_INVALID_VALUE);
2482 }
2483 }
2484
2485 if(index >= programObject->getActiveUniformCount())
2486 {
2487 return error(GL_INVALID_VALUE);
2488 }
2489
2490 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2491 }
2492}
2493
2494void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2495{
2496 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2497 program, maxcount, count, shaders);
2498
2499 if(maxcount < 0)
2500 {
2501 return error(GL_INVALID_VALUE);
2502 }
2503
2504 es2::Context *context = es2::getContext();
2505
2506 if(context)
2507 {
2508 es2::Program *programObject = context->getProgram(program);
2509
2510 if(!programObject)
2511 {
2512 if(context->getShader(program))
2513 {
2514 return error(GL_INVALID_OPERATION);
2515 }
2516 else
2517 {
2518 return error(GL_INVALID_VALUE);
2519 }
2520 }
2521
2522 return programObject->getAttachedShaders(maxcount, count, shaders);
2523 }
2524}
2525
2526int GetAttribLocation(GLuint program, const GLchar* name)
2527{
2528 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2529
2530 es2::Context *context = es2::getContext();
2531
2532 if(context)
2533 {
2534
2535 es2::Program *programObject = context->getProgram(program);
2536
2537 if(!programObject)
2538 {
2539 if(context->getShader(program))
2540 {
2541 return error(GL_INVALID_OPERATION, -1);
2542 }
2543 else
2544 {
2545 return error(GL_INVALID_VALUE, -1);
2546 }
2547 }
2548
2549 if(!programObject->isLinked())
2550 {
2551 return error(GL_INVALID_OPERATION, -1);
2552 }
2553
2554 return programObject->getAttributeLocation(name);
2555 }
2556
2557 return -1;
2558}
2559
2560void GetBooleanv(GLenum pname, GLboolean* params)
2561{
2562 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2563
2564 es2::Context *context = es2::getContext();
2565
2566 if(context)
2567 {
2568 if(!(context->getBooleanv(pname, params)))
2569 {
2570 GLenum nativeType;
2571 unsigned int numParams = 0;
2572 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2573 return error(GL_INVALID_ENUM);
2574
2575 if(numParams == 0)
2576 return; // it is known that the pname is valid, but there are no parameters to return
2577
2578 if(nativeType == GL_FLOAT)
2579 {
2580 GLfloat *floatParams = nullptr;
2581 floatParams = new GLfloat[numParams];
2582
2583 context->getFloatv(pname, floatParams);
2584
2585 for(unsigned int i = 0; i < numParams; ++i)
2586 {
2587 if(floatParams[i] == 0.0f)
2588 params[i] = GL_FALSE;
2589 else
2590 params[i] = GL_TRUE;
2591 }
2592
2593 delete [] floatParams;
2594 }
2595 else if(nativeType == GL_INT)
2596 {
2597 GLint *intParams = nullptr;
2598 intParams = new GLint[numParams];
2599
2600 context->getIntegerv(pname, intParams);
2601
2602 for(unsigned int i = 0; i < numParams; ++i)
2603 {
2604 if(intParams[i] == 0)
2605 params[i] = GL_FALSE;
2606 else
2607 params[i] = GL_TRUE;
2608 }
2609
2610 delete [] intParams;
2611 }
2612 }
2613 }
2614}
2615
2616void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2617{
2618 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2619
2620 es2::Context *context = es2::getContext();
2621
2622 if(context)
2623 {
2624 es2::Buffer *buffer;
2625 if(!context->getBuffer(target, &buffer))
2626 {
2627 return error(GL_INVALID_ENUM);
2628 }
2629
2630 if(!buffer)
2631 {
2632 // A null buffer means that "0" is bound to the requested buffer target
2633 return error(GL_INVALID_OPERATION);
2634 }
2635
2636 GLint clientVersion = context->getClientVersion();
2637
2638 switch(pname)
2639 {
2640 case GL_BUFFER_USAGE:
2641 *params = buffer->usage();
2642 break;
2643 case GL_BUFFER_SIZE:
2644 *params = (GLint)buffer->size();
2645 break;
2646 case GL_BUFFER_ACCESS_FLAGS:
2647 if(clientVersion >= 3)
2648 {
2649 *params = buffer->access();
2650 break;
2651 }
2652 else return error(GL_INVALID_ENUM);
2653 case GL_BUFFER_MAPPED:
2654 if(clientVersion >= 3)
2655 {
2656 *params = buffer->isMapped();
2657 break;
2658 }
2659 else return error(GL_INVALID_ENUM);
2660 case GL_BUFFER_MAP_LENGTH:
2661 if(clientVersion >= 3)
2662 {
2663 *params = (GLint)buffer->length();
2664 break;
2665 }
2666 else return error(GL_INVALID_ENUM);
2667 case GL_BUFFER_MAP_OFFSET:
2668 if(clientVersion >= 3)
2669 {
2670 *params = (GLint)buffer->offset();
2671 break;
2672 }
2673 else return error(GL_INVALID_ENUM);
2674 default:
2675 return error(GL_INVALID_ENUM);
2676 }
2677 }
2678}
2679
2680GLenum GetError(void)
2681{
2682 TRACE("()");
2683
2684 es2::Context *context = es2::getContext();
2685
2686 if(context)
2687 {
2688 return context->getError();
2689 }
2690
2691 return GL_NO_ERROR;
2692}
2693
2694void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2695{
2696 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2697
2698 es2::Context *context = es2::getContext();
2699
2700 if(context)
2701 {
2702 es2::Fence *fenceObject = context->getFence(fence);
2703
2704 if(!fenceObject)
2705 {
2706 return error(GL_INVALID_OPERATION);
2707 }
2708
2709 fenceObject->getFenceiv(pname, params);
2710 }
2711}
2712
2713void GetFloatv(GLenum pname, GLfloat* params)
2714{
2715 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2716
2717 es2::Context *context = es2::getContext();
2718
2719 if(context)
2720 {
2721 if(!(context->getFloatv(pname, params)))
2722 {
2723 GLenum nativeType;
2724 unsigned int numParams = 0;
2725 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2726 return error(GL_INVALID_ENUM);
2727
2728 if(numParams == 0)
2729 return; // it is known that the pname is valid, but that there are no parameters to return.
2730
2731 if(nativeType == GL_BOOL)
2732 {
2733 GLboolean *boolParams = nullptr;
2734 boolParams = new GLboolean[numParams];
2735
2736 context->getBooleanv(pname, boolParams);
2737
2738 for(unsigned int i = 0; i < numParams; ++i)
2739 {
2740 if(boolParams[i] == GL_FALSE)
2741 params[i] = 0.0f;
2742 else
2743 params[i] = 1.0f;
2744 }
2745
2746 delete [] boolParams;
2747 }
2748 else if(nativeType == GL_INT)
2749 {
2750 GLint *intParams = nullptr;
2751 intParams = new GLint[numParams];
2752
2753 context->getIntegerv(pname, intParams);
2754
2755 for(unsigned int i = 0; i < numParams; ++i)
2756 {
2757 params[i] = (GLfloat)intParams[i];
2758 }
2759
2760 delete [] intParams;
2761 }
2762 }
2763 }
2764}
2765
2766void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2767{
2768 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2769 target, attachment, pname, params);
2770
2771 es2::Context *context = es2::getContext();
2772
2773 if(context)
2774 {
2775 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2776 {
2777 return error(GL_INVALID_ENUM);
2778 }
2779
2780 GLint clientVersion = context->getClientVersion();
2781
2782 es2::Framebuffer *framebuffer = nullptr;
2783 if(target == GL_READ_FRAMEBUFFER)
2784 {
2785 if(context->getReadFramebufferName() == 0)
2786 {
2787 if(clientVersion < 3)
2788 {
2789 return error(GL_INVALID_OPERATION);
2790 }
2791 else
2792 {
2793 switch(attachment)
2794 {
2795 case GL_BACK:
2796 case GL_DEPTH:
2797 case GL_STENCIL:
2798 break;
2799 default:
2800 return error(GL_INVALID_ENUM);
2801 }
2802 }
2803 }
2804
2805 framebuffer = context->getReadFramebuffer();
2806 }
2807 else
2808 {
2809 if(context->getDrawFramebufferName() == 0)
2810 {
2811 if(clientVersion < 3)
2812 {
2813 return error(GL_INVALID_OPERATION);
2814 }
2815 else
2816 {
2817 switch(attachment)
2818 {
2819 case GL_BACK:
2820 case GL_DEPTH:
2821 case GL_STENCIL:
2822 break;
2823 default:
2824 return error(GL_INVALID_ENUM);
2825 }
2826 }
2827 }
2828
2829 framebuffer = context->getDrawFramebuffer();
2830 }
2831
2832 GLenum attachmentType;
2833 GLuint attachmentHandle;
2834 GLint attachmentLayer;
2835 Renderbuffer* renderbuffer = nullptr;
2836 switch(attachment)
2837 {
2838 case GL_BACK:
2839 if(clientVersion >= 3)
2840 {
2841 attachmentType = framebuffer->getColorbufferType(0);
2842 attachmentHandle = framebuffer->getColorbufferName(0);
2843 attachmentLayer = framebuffer->getColorbufferLayer(0);
2844 renderbuffer = framebuffer->getColorbuffer(0);
2845 }
2846 else return error(GL_INVALID_ENUM);
2847 break;
2848 case GL_COLOR_ATTACHMENT0:
2849 case GL_COLOR_ATTACHMENT1:
2850 case GL_COLOR_ATTACHMENT2:
2851 case GL_COLOR_ATTACHMENT3:
2852 case GL_COLOR_ATTACHMENT4:
2853 case GL_COLOR_ATTACHMENT5:
2854 case GL_COLOR_ATTACHMENT6:
2855 case GL_COLOR_ATTACHMENT7:
2856 case GL_COLOR_ATTACHMENT8:
2857 case GL_COLOR_ATTACHMENT9:
2858 case GL_COLOR_ATTACHMENT10:
2859 case GL_COLOR_ATTACHMENT11:
2860 case GL_COLOR_ATTACHMENT12:
2861 case GL_COLOR_ATTACHMENT13:
2862 case GL_COLOR_ATTACHMENT14:
2863 case GL_COLOR_ATTACHMENT15:
2864 case GL_COLOR_ATTACHMENT16:
2865 case GL_COLOR_ATTACHMENT17:
2866 case GL_COLOR_ATTACHMENT18:
2867 case GL_COLOR_ATTACHMENT19:
2868 case GL_COLOR_ATTACHMENT20:
2869 case GL_COLOR_ATTACHMENT21:
2870 case GL_COLOR_ATTACHMENT22:
2871 case GL_COLOR_ATTACHMENT23:
2872 case GL_COLOR_ATTACHMENT24:
2873 case GL_COLOR_ATTACHMENT25:
2874 case GL_COLOR_ATTACHMENT26:
2875 case GL_COLOR_ATTACHMENT27:
2876 case GL_COLOR_ATTACHMENT28:
2877 case GL_COLOR_ATTACHMENT29:
2878 case GL_COLOR_ATTACHMENT30:
2879 case GL_COLOR_ATTACHMENT31:
2880 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2881 {
2882 return error(GL_INVALID_ENUM);
2883 }
2884 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2885 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2886 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2887 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2888 break;
2889 case GL_DEPTH:
2890 if(clientVersion < 3)
2891 {
2892 return error(GL_INVALID_ENUM);
2893 }
2894 // fall through
2895 case GL_DEPTH_ATTACHMENT:
2896 attachmentType = framebuffer->getDepthbufferType();
2897 attachmentHandle = framebuffer->getDepthbufferName();
2898 attachmentLayer = framebuffer->getDepthbufferLayer();
2899 renderbuffer = framebuffer->getDepthbuffer();
2900 break;
2901 case GL_STENCIL:
2902 if(clientVersion < 3)
2903 {
2904 return error(GL_INVALID_ENUM);
2905 }
2906 // fall through
2907 case GL_STENCIL_ATTACHMENT:
2908 attachmentType = framebuffer->getStencilbufferType();
2909 attachmentHandle = framebuffer->getStencilbufferName();
2910 attachmentLayer = framebuffer->getStencilbufferLayer();
2911 renderbuffer = framebuffer->getStencilbuffer();
2912 break;
2913 case GL_DEPTH_STENCIL_ATTACHMENT:
2914 if(clientVersion >= 3)
2915 {
2916 attachmentType = framebuffer->getDepthbufferType();
2917 attachmentHandle = framebuffer->getDepthbufferName();
2918 attachmentLayer = framebuffer->getDepthbufferLayer();
2919 if(attachmentHandle != framebuffer->getStencilbufferName())
2920 {
2921 // Different attachments to DEPTH and STENCIL, query fails
2922 return error(GL_INVALID_OPERATION);
2923 }
2924 renderbuffer = framebuffer->getDepthbuffer();
2925 }
2926 else return error(GL_INVALID_ENUM);
2927 break;
2928 default:
2929 return error(GL_INVALID_ENUM);
2930 }
2931
2932 GLenum attachmentObjectType = GL_NONE; // Type category
2933 if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
2934 {
2935 attachmentObjectType = attachmentType;
2936 }
2937 else if(es2::IsTextureTarget(attachmentType))
2938 {
2939 attachmentObjectType = GL_TEXTURE;
2940 }
2941 else UNREACHABLE(attachmentType);
2942
2943 if(attachmentObjectType != GL_NONE)
2944 {
2945 switch(pname)
2946 {
2947 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2948 *params = attachmentObjectType;
2949 break;
2950 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2951 if(Framebuffer::IsRenderbuffer(attachmentObjectType) || attachmentObjectType == GL_TEXTURE)
2952 {
2953 *params = attachmentHandle;
2954 }
2955 else
2956 {
2957 return error(GL_INVALID_ENUM);
2958 }
2959 break;
2960 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2961 if(attachmentObjectType == GL_TEXTURE)
2962 {
2963 *params = clientVersion < 3 ? 0 : renderbuffer->getLevel(); // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
2964 }
2965 else
2966 {
2967 return error(GL_INVALID_ENUM);
2968 }
2969 break;
2970 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2971 if(attachmentObjectType == GL_TEXTURE)
2972 {
2973 if(es2::IsCubemapTextureTarget(attachmentType))
2974 {
2975 *params = attachmentType;
2976 }
2977 else
2978 {
2979 *params = 0;
2980 }
2981 }
2982 else
2983 {
2984 return error(GL_INVALID_ENUM);
2985 }
2986 break;
2987 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2988 if(clientVersion >= 3)
2989 {
2990 *params = attachmentLayer;
2991 }
2992 else return error(GL_INVALID_ENUM);
2993 break;
2994 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2995 if(clientVersion >= 3)
2996 {
2997 *params = renderbuffer->getRedSize();
2998 }
2999 else return error(GL_INVALID_ENUM);
3000 break;
3001 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3002 if(clientVersion >= 3)
3003 {
3004 *params = renderbuffer->getGreenSize();
3005 }
3006 else return error(GL_INVALID_ENUM);
3007 break;
3008 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3009 if(clientVersion >= 3)
3010 {
3011 *params = renderbuffer->getBlueSize();
3012 }
3013 else return error(GL_INVALID_ENUM);
3014 break;
3015 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3016 if(clientVersion >= 3)
3017 {
3018 *params = renderbuffer->getAlphaSize();
3019 }
3020 else return error(GL_INVALID_ENUM);
3021 break;
3022 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3023 if(clientVersion >= 3)
3024 {
3025 *params = renderbuffer->getDepthSize();
3026 }
3027 else return error(GL_INVALID_ENUM);
3028 break;
3029 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3030 if(clientVersion >= 3)
3031 {
3032 *params = renderbuffer->getStencilSize();
3033 }
3034 else return error(GL_INVALID_ENUM);
3035 break;
3036 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04003037 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
3038 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003039 {
Nicolas Capens505b7712016-06-14 01:08:12 -04003040 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003041 }
Nicolas Capens505b7712016-06-14 01:08:12 -04003042
3043 *params = sw2es::GetComponentType(renderbuffer->getInternalFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003044 break;
3045 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3046 if(clientVersion >= 3)
3047 {
3048 *params = GL_LINEAR; // FIXME: GL_SRGB will also be possible, when sRGB is added
3049 }
3050 else return error(GL_INVALID_ENUM);
3051 break;
3052 default:
3053 return error(GL_INVALID_ENUM);
3054 }
3055 }
3056 else
3057 {
3058 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3059 // is NONE, then querying any other pname will generate INVALID_ENUM.
3060
3061 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3062 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3063 // INVALID_OPERATION for all other pnames
3064
3065 switch(pname)
3066 {
3067 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3068 *params = GL_NONE;
3069 break;
3070
3071 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3072 if(clientVersion < 3)
3073 {
3074 return error(GL_INVALID_ENUM);
3075 }
3076 *params = 0;
3077 break;
3078
3079 default:
3080 if(clientVersion < 3)
3081 {
3082 return error(GL_INVALID_ENUM);
3083 }
3084 else
3085 {
3086 return error(GL_INVALID_OPERATION);
3087 }
3088 }
3089 }
3090 }
3091}
3092
3093GLenum GetGraphicsResetStatusEXT(void)
3094{
3095 TRACE("()");
3096
3097 return GL_NO_ERROR;
3098}
3099
3100void GetIntegerv(GLenum pname, GLint* params)
3101{
3102 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
3103
3104 es2::Context *context = es2::getContext();
3105
3106 if(!context)
3107 {
3108 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
3109 #ifdef __ANDROID__
3110 ALOGI("expected_badness glGetIntegerv() called without current context.");
3111 #else
3112 ERR("glGetIntegerv() called without current context.");
3113 #endif
3114
3115 // This is not spec compliant! When there is no current GL context, functions should
3116 // have no side effects. Google Maps queries these values before creating a context,
3117 // so we need this as a bug-compatible workaround.
3118 switch(pname)
3119 {
3120 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3121 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3122 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3123 case GL_STENCIL_BITS: *params = 8; return;
3124 case GL_ALIASED_LINE_WIDTH_RANGE:
3125 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3126 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3127 return;
3128 }
3129 }
3130
3131 if(context)
3132 {
3133 if(!(context->getIntegerv(pname, params)))
3134 {
3135 GLenum nativeType;
3136 unsigned int numParams = 0;
3137 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3138 return error(GL_INVALID_ENUM);
3139
3140 if(numParams == 0)
3141 return; // it is known that pname is valid, but there are no parameters to return
3142
3143 if(nativeType == GL_BOOL)
3144 {
3145 GLboolean *boolParams = nullptr;
3146 boolParams = new GLboolean[numParams];
3147
3148 context->getBooleanv(pname, boolParams);
3149
3150 for(unsigned int i = 0; i < numParams; ++i)
3151 {
3152 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3153 }
3154
3155 delete [] boolParams;
3156 }
3157 else if(nativeType == GL_FLOAT)
3158 {
3159 GLfloat *floatParams = nullptr;
3160 floatParams = new GLfloat[numParams];
3161
3162 context->getFloatv(pname, floatParams);
3163
3164 for(unsigned int i = 0; i < numParams; ++i)
3165 {
3166 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3167 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003168 params[i] = convert_float_int(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003169 }
3170 else
3171 {
3172 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3173 }
3174 }
3175
3176 delete [] floatParams;
3177 }
3178 }
3179 }
3180}
3181
3182void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3183{
3184 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3185
3186 es2::Context *context = es2::getContext();
3187
3188 if(context)
3189 {
3190 es2::Program *programObject = context->getProgram(program);
3191
3192 if(!programObject)
3193 {
3194 if(context->getShader(program))
3195 {
3196 return error(GL_INVALID_OPERATION);
3197 }
3198 else
3199 {
3200 return error(GL_INVALID_VALUE);
3201 }
3202 }
3203
3204 GLint clientVersion = egl::getClientVersion();
3205
3206 switch(pname)
3207 {
3208 case GL_DELETE_STATUS:
3209 *params = programObject->isFlaggedForDeletion();
3210 return;
3211 case GL_LINK_STATUS:
3212 *params = programObject->isLinked();
3213 return;
3214 case GL_VALIDATE_STATUS:
3215 *params = programObject->isValidated();
3216 return;
3217 case GL_INFO_LOG_LENGTH:
3218 *params = (GLint)programObject->getInfoLogLength();
3219 return;
3220 case GL_ATTACHED_SHADERS:
3221 *params = programObject->getAttachedShadersCount();
3222 return;
3223 case GL_ACTIVE_ATTRIBUTES:
3224 *params = (GLint)programObject->getActiveAttributeCount();
3225 return;
3226 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3227 *params = programObject->getActiveAttributeMaxLength();
3228 return;
3229 case GL_ACTIVE_UNIFORMS:
3230 *params = (GLint)programObject->getActiveUniformCount();
3231 return;
3232 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3233 *params = programObject->getActiveUniformMaxLength();
3234 return;
3235 case GL_ACTIVE_UNIFORM_BLOCKS:
3236 if(clientVersion >= 3)
3237 {
3238 *params = (GLint)programObject->getActiveUniformBlockCount();
3239 return;
3240 }
3241 else return error(GL_INVALID_ENUM);
3242 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3243 if(clientVersion >= 3)
3244 {
3245 *params = programObject->getActiveUniformBlockMaxLength();
3246 return;
3247 }
3248 else return error(GL_INVALID_ENUM);
3249 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3250 if(clientVersion >= 3)
3251 {
3252 *params = programObject->getTransformFeedbackBufferMode();
3253 return;
3254 }
3255 else return error(GL_INVALID_ENUM);
3256 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3257 if(clientVersion >= 3)
3258 {
3259 *params = programObject->getTransformFeedbackVaryingCount();
3260 return;
3261 }
3262 else return error(GL_INVALID_ENUM);
3263 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3264 if(clientVersion >= 3)
3265 {
3266 *params = programObject->getTransformFeedbackVaryingMaxLength();
3267 return;
3268 }
3269 else return error(GL_INVALID_ENUM);
3270 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3271 if(clientVersion >= 3)
3272 {
3273 *params = programObject->getBinaryRetrievableHint();
3274 return;
3275 }
3276 else return error(GL_INVALID_ENUM);
3277 case GL_PROGRAM_BINARY_LENGTH:
3278 if(clientVersion >= 3)
3279 {
3280 *params = programObject->getBinaryLength();
3281 return;
3282 }
3283 else return error(GL_INVALID_ENUM);
3284 default:
3285 return error(GL_INVALID_ENUM);
3286 }
3287 }
3288}
3289
3290void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3291{
3292 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3293 program, bufsize, length, infolog);
3294
3295 if(bufsize < 0)
3296 {
3297 return error(GL_INVALID_VALUE);
3298 }
3299
3300 es2::Context *context = es2::getContext();
3301
3302 if(context)
3303 {
3304 es2::Program *programObject = context->getProgram(program);
3305
3306 if(!programObject)
3307 {
3308 if(context->getShader(program))
3309 {
3310 return error(GL_INVALID_OPERATION);
3311 }
3312 else
3313 {
3314 return error(GL_INVALID_VALUE);
3315 }
3316 }
3317
3318 programObject->getInfoLog(bufsize, length, infolog);
3319 }
3320}
3321
3322void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3323{
3324 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3325
3326 switch(pname)
3327 {
3328 case GL_CURRENT_QUERY_EXT:
3329 break;
3330 default:
3331 return error(GL_INVALID_ENUM);
3332 }
3333
3334 es2::Context *context = es2::getContext();
3335
3336 if(context)
3337 {
3338 params[0] = context->getActiveQuery(target);
3339 }
3340}
3341
3342void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3343{
3344 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3345
3346 switch(pname)
3347 {
3348 case GL_QUERY_RESULT_EXT:
3349 case GL_QUERY_RESULT_AVAILABLE_EXT:
3350 break;
3351 default:
3352 return error(GL_INVALID_ENUM);
3353 }
3354
3355 es2::Context *context = es2::getContext();
3356
3357 if(context)
3358 {
3359 es2::Query *queryObject = context->getQuery(name);
3360
3361 if(!queryObject)
3362 {
3363 return error(GL_INVALID_OPERATION);
3364 }
3365
3366 if(context->getActiveQuery(queryObject->getType()) == name)
3367 {
3368 return error(GL_INVALID_OPERATION);
3369 }
3370
3371 switch(pname)
3372 {
3373 case GL_QUERY_RESULT_EXT:
3374 params[0] = queryObject->getResult();
3375 break;
3376 case GL_QUERY_RESULT_AVAILABLE_EXT:
3377 params[0] = queryObject->isResultAvailable();
3378 break;
3379 default:
3380 ASSERT(false);
3381 }
3382 }
3383}
3384
3385void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3386{
3387 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3388
3389 es2::Context *context = es2::getContext();
3390
3391 if(context)
3392 {
3393 if(target != GL_RENDERBUFFER)
3394 {
3395 return error(GL_INVALID_ENUM);
3396 }
3397
3398 if(context->getRenderbufferName() == 0)
3399 {
3400 return error(GL_INVALID_OPERATION);
3401 }
3402
3403 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3404
3405 switch(pname)
3406 {
3407 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3408 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
3409 case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat(); break;
3410 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3411 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3412 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3413 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3414 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3415 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
3416 case GL_RENDERBUFFER_SAMPLES_ANGLE: *params = renderbuffer->getSamples(); break;
3417 default:
3418 return error(GL_INVALID_ENUM);
3419 }
3420 }
3421}
3422
3423void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3424{
3425 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3426
3427 es2::Context *context = es2::getContext();
3428
3429 if(context)
3430 {
3431 es2::Shader *shaderObject = context->getShader(shader);
3432
3433 if(!shaderObject)
3434 {
3435 if(context->getProgram(shader))
3436 {
3437 return error(GL_INVALID_OPERATION);
3438 }
3439 else
3440 {
3441 return error(GL_INVALID_VALUE);
3442 }
3443 }
3444
3445 switch(pname)
3446 {
3447 case GL_SHADER_TYPE:
3448 *params = shaderObject->getType();
3449 return;
3450 case GL_DELETE_STATUS:
3451 *params = shaderObject->isFlaggedForDeletion();
3452 return;
3453 case GL_COMPILE_STATUS:
3454 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3455 return;
3456 case GL_INFO_LOG_LENGTH:
3457 *params = (GLint)shaderObject->getInfoLogLength();
3458 return;
3459 case GL_SHADER_SOURCE_LENGTH:
3460 *params = (GLint)shaderObject->getSourceLength();
3461 return;
3462 default:
3463 return error(GL_INVALID_ENUM);
3464 }
3465 }
3466}
3467
3468void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3469{
3470 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3471 shader, bufsize, length, infolog);
3472
3473 if(bufsize < 0)
3474 {
3475 return error(GL_INVALID_VALUE);
3476 }
3477
3478 es2::Context *context = es2::getContext();
3479
3480 if(context)
3481 {
3482 es2::Shader *shaderObject = context->getShader(shader);
3483
3484 if(!shaderObject)
3485 {
3486 if(context->getProgram(shader))
3487 {
3488 return error(GL_INVALID_OPERATION);
3489 }
3490 else
3491 {
3492 return error(GL_INVALID_VALUE);
3493 }
3494 }
3495
3496 shaderObject->getInfoLog(bufsize, length, infolog);
3497 }
3498}
3499
3500void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3501{
3502 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3503 shadertype, precisiontype, range, precision);
3504
3505 switch(shadertype)
3506 {
3507 case GL_VERTEX_SHADER:
3508 case GL_FRAGMENT_SHADER:
3509 break;
3510 default:
3511 return error(GL_INVALID_ENUM);
3512 }
3513
3514 switch(precisiontype)
3515 {
3516 case GL_LOW_FLOAT:
3517 case GL_MEDIUM_FLOAT:
3518 case GL_HIGH_FLOAT:
3519 // IEEE 754 single-precision
3520 range[0] = 127;
3521 range[1] = 127;
3522 *precision = 23;
3523 break;
3524 case GL_LOW_INT:
3525 case GL_MEDIUM_INT:
3526 case GL_HIGH_INT:
3527 // Full integer precision is supported
3528 range[0] = 31;
3529 range[1] = 30;
3530 *precision = 0;
3531 break;
3532 default:
3533 return error(GL_INVALID_ENUM);
3534 }
3535}
3536
3537void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3538{
3539 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3540 shader, bufsize, length, source);
3541
3542 if(bufsize < 0)
3543 {
3544 return error(GL_INVALID_VALUE);
3545 }
3546
3547 es2::Context *context = es2::getContext();
3548
3549 if(context)
3550 {
3551 es2::Shader *shaderObject = context->getShader(shader);
3552
3553 if(!shaderObject)
3554 {
3555 if(context->getProgram(shader))
3556 {
3557 return error(GL_INVALID_OPERATION);
3558 }
3559 else
3560 {
3561 return error(GL_INVALID_VALUE);
3562 }
3563 }
3564
3565 shaderObject->getSource(bufsize, length, source);
3566 }
3567}
3568
3569const GLubyte* GetString(GLenum name)
3570{
3571 TRACE("(GLenum name = 0x%X)", name);
3572
3573 switch(name)
3574 {
3575 case GL_VENDOR:
3576 return (GLubyte*)"Google Inc.";
3577 case GL_RENDERER:
3578 return (GLubyte*)"Google SwiftShader";
3579 case GL_VERSION:
3580 {
3581 es2::Context *context = es2::getContext();
3582 return (context && (context->getClientVersion() >= 3)) ?
3583 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3584 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3585 }
3586 case GL_SHADING_LANGUAGE_VERSION:
3587 {
3588 es2::Context *context = es2::getContext();
3589 return (context && (context->getClientVersion() >= 3)) ?
3590 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3591 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3592 }
3593 case GL_EXTENSIONS:
3594 {
3595 es2::Context *context = es2::getContext();
3596 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3597 }
3598 default:
3599 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3600 }
3601}
3602
3603void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3604{
3605 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3606
3607 es2::Context *context = es2::getContext();
3608
3609 if(context)
3610 {
3611 es2::Texture *texture;
3612
3613 GLint clientVersion = context->getClientVersion();
3614
3615 switch(target)
3616 {
3617 case GL_TEXTURE_2D:
3618 texture = context->getTexture2D();
3619 break;
3620 case GL_TEXTURE_CUBE_MAP:
3621 texture = context->getTextureCubeMap();
3622 break;
3623 case GL_TEXTURE_EXTERNAL_OES:
3624 texture = context->getTextureExternal();
3625 break;
3626 case GL_TEXTURE_2D_ARRAY:
3627 if(clientVersion < 3)
3628 {
3629 return error(GL_INVALID_ENUM);
3630 }
3631 else
3632 {
3633 texture = context->getTexture2DArray();
3634 }
3635 break;
3636 case GL_TEXTURE_3D_OES:
3637 texture = context->getTexture3D();
3638 break;
3639 default:
3640 return error(GL_INVALID_ENUM);
3641 }
3642
3643 switch(pname)
3644 {
3645 case GL_TEXTURE_MAG_FILTER:
3646 *params = (GLfloat)texture->getMagFilter();
3647 break;
3648 case GL_TEXTURE_MIN_FILTER:
3649 *params = (GLfloat)texture->getMinFilter();
3650 break;
3651 case GL_TEXTURE_WRAP_S:
3652 *params = (GLfloat)texture->getWrapS();
3653 break;
3654 case GL_TEXTURE_WRAP_T:
3655 *params = (GLfloat)texture->getWrapT();
3656 break;
3657 case GL_TEXTURE_WRAP_R_OES:
3658 *params = (GLfloat)texture->getWrapR();
3659 break;
3660 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3661 *params = texture->getMaxAnisotropy();
3662 break;
3663 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3664 *params = (GLfloat)1;
3665 break;
3666 case GL_TEXTURE_BASE_LEVEL:
3667 if(clientVersion >= 3)
3668 {
3669 *params = (GLfloat)texture->getBaseLevel();
3670 break;
3671 }
3672 else return error(GL_INVALID_ENUM);
3673 case GL_TEXTURE_COMPARE_FUNC:
3674 if(clientVersion >= 3)
3675 {
3676 *params = (GLfloat)texture->getCompareFunc();
3677 break;
3678 }
3679 else return error(GL_INVALID_ENUM);
3680 case GL_TEXTURE_COMPARE_MODE:
3681 if(clientVersion >= 3)
3682 {
3683 *params = (GLfloat)texture->getCompareMode();
3684 break;
3685 }
3686 else return error(GL_INVALID_ENUM);
3687 case GL_TEXTURE_IMMUTABLE_FORMAT:
3688 if(clientVersion >= 3)
3689 {
3690 *params = (GLfloat)texture->getImmutableFormat();
3691 break;
3692 }
3693 else return error(GL_INVALID_ENUM);
3694 case GL_TEXTURE_IMMUTABLE_LEVELS:
3695 if(clientVersion >= 3)
3696 {
3697 *params = (GLfloat)texture->getImmutableLevels();
3698 break;
3699 }
3700 else return error(GL_INVALID_ENUM);
3701 case GL_TEXTURE_MAX_LEVEL:
3702 if(clientVersion >= 3)
3703 {
3704 *params = (GLfloat)texture->getMaxLevel();
3705 break;
3706 }
3707 else return error(GL_INVALID_ENUM);
3708 case GL_TEXTURE_MAX_LOD:
3709 if(clientVersion >= 3)
3710 {
3711 *params = texture->getMaxLOD();
3712 break;
3713 }
3714 else return error(GL_INVALID_ENUM);
3715 case GL_TEXTURE_MIN_LOD:
3716 if(clientVersion >= 3)
3717 {
3718 *params = texture->getMinLOD();
3719 break;
3720 }
3721 else return error(GL_INVALID_ENUM);
3722 case GL_TEXTURE_SWIZZLE_R:
3723 if(clientVersion >= 3)
3724 {
3725 *params = (GLfloat)texture->getSwizzleR();
3726 break;
3727 }
3728 else return error(GL_INVALID_ENUM);
3729 case GL_TEXTURE_SWIZZLE_G:
3730 if(clientVersion >= 3)
3731 {
3732 *params = (GLfloat)texture->getSwizzleG();
3733 break;
3734 }
3735 else return error(GL_INVALID_ENUM);
3736 case GL_TEXTURE_SWIZZLE_B:
3737 if(clientVersion >= 3)
3738 {
3739 *params = (GLfloat)texture->getSwizzleB();
3740 break;
3741 }
3742 else return error(GL_INVALID_ENUM);
3743 case GL_TEXTURE_SWIZZLE_A:
3744 if(clientVersion >= 3)
3745 {
3746 *params = (GLfloat)texture->getSwizzleA();
3747 break;
3748 }
3749 else return error(GL_INVALID_ENUM);
3750 default:
3751 return error(GL_INVALID_ENUM);
3752 }
3753 }
3754}
3755
3756void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3757{
3758 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3759
3760 es2::Context *context = es2::getContext();
3761
3762 if(context)
3763 {
3764 es2::Texture *texture;
3765
3766 GLint clientVersion = context->getClientVersion();
3767
3768 switch(target)
3769 {
3770 case GL_TEXTURE_2D:
3771 texture = context->getTexture2D();
3772 break;
3773 case GL_TEXTURE_CUBE_MAP:
3774 texture = context->getTextureCubeMap();
3775 break;
3776 case GL_TEXTURE_EXTERNAL_OES:
3777 texture = context->getTextureExternal();
3778 break;
3779 case GL_TEXTURE_2D_ARRAY:
3780 if(clientVersion < 3)
3781 {
3782 return error(GL_INVALID_ENUM);
3783 }
3784 else
3785 {
3786 texture = context->getTexture2DArray();
3787 }
3788 break;
3789 case GL_TEXTURE_3D_OES:
3790 texture = context->getTexture3D();
3791 break;
3792 default:
3793 return error(GL_INVALID_ENUM);
3794 }
3795
3796 switch(pname)
3797 {
3798 case GL_TEXTURE_MAG_FILTER:
3799 *params = texture->getMagFilter();
3800 break;
3801 case GL_TEXTURE_MIN_FILTER:
3802 *params = texture->getMinFilter();
3803 break;
3804 case GL_TEXTURE_WRAP_S:
3805 *params = texture->getWrapS();
3806 break;
3807 case GL_TEXTURE_WRAP_T:
3808 *params = texture->getWrapT();
3809 break;
3810 case GL_TEXTURE_WRAP_R_OES:
3811 *params = texture->getWrapR();
3812 break;
3813 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3814 *params = (GLint)texture->getMaxAnisotropy();
3815 break;
3816 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3817 *params = 1;
3818 break;
3819 case GL_TEXTURE_BASE_LEVEL:
3820 if(clientVersion >= 3)
3821 {
3822 *params = texture->getBaseLevel();
3823 break;
3824 }
3825 else return error(GL_INVALID_ENUM);
3826 case GL_TEXTURE_COMPARE_FUNC:
3827 if(clientVersion >= 3)
3828 {
3829 *params = (GLint)texture->getCompareFunc();
3830 break;
3831 }
3832 else return error(GL_INVALID_ENUM);
3833 case GL_TEXTURE_COMPARE_MODE:
3834 if(clientVersion >= 3)
3835 {
3836 *params = (GLint)texture->getCompareMode();
3837 break;
3838 }
3839 else return error(GL_INVALID_ENUM);
3840 case GL_TEXTURE_IMMUTABLE_FORMAT:
3841 if(clientVersion >= 3)
3842 {
3843 *params = (GLint)texture->getImmutableFormat();
3844 break;
3845 }
3846 else return error(GL_INVALID_ENUM);
3847 case GL_TEXTURE_IMMUTABLE_LEVELS:
3848 if(clientVersion >= 3)
3849 {
3850 *params = (GLint)texture->getImmutableLevels();
3851 break;
3852 }
3853 else return error(GL_INVALID_ENUM);
3854 case GL_TEXTURE_MAX_LEVEL:
3855 if(clientVersion >= 3)
3856 {
3857 *params = texture->getMaxLevel();
3858 break;
3859 }
3860 else return error(GL_INVALID_ENUM);
3861 case GL_TEXTURE_MAX_LOD:
3862 if(clientVersion >= 3)
3863 {
3864 *params = (GLint)roundf(texture->getMaxLOD());
3865 break;
3866 }
3867 else return error(GL_INVALID_ENUM);
3868 case GL_TEXTURE_MIN_LOD:
3869 if(clientVersion >= 3)
3870 {
3871 *params = (GLint)roundf(texture->getMinLOD());
3872 break;
3873 }
3874 else return error(GL_INVALID_ENUM);
3875 case GL_TEXTURE_SWIZZLE_R:
3876 if(clientVersion >= 3)
3877 {
3878 *params = (GLint)texture->getSwizzleR();
3879 break;
3880 }
3881 else return error(GL_INVALID_ENUM);
3882 case GL_TEXTURE_SWIZZLE_G:
3883 if(clientVersion >= 3)
3884 {
3885 *params = (GLint)texture->getSwizzleG();
3886 break;
3887 }
3888 else return error(GL_INVALID_ENUM);
3889 case GL_TEXTURE_SWIZZLE_B:
3890 if(clientVersion >= 3)
3891 {
3892 *params = (GLint)texture->getSwizzleB();
3893 break;
3894 }
3895 else return error(GL_INVALID_ENUM);
3896 case GL_TEXTURE_SWIZZLE_A:
3897 if(clientVersion >= 3)
3898 {
3899 *params = (GLint)texture->getSwizzleA();
3900 break;
3901 }
3902 else return error(GL_INVALID_ENUM);
3903 default:
3904 return error(GL_INVALID_ENUM);
3905 }
3906 }
3907}
3908
3909void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3910{
3911 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3912 program, location, bufSize, params);
3913
3914 if(bufSize < 0)
3915 {
3916 return error(GL_INVALID_VALUE);
3917 }
3918
3919 es2::Context *context = es2::getContext();
3920
3921 if(context)
3922 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003923 es2::Program *programObject = context->getProgram(program);
3924
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003925 if(!programObject)
3926 {
3927 if(context->getShader(program))
3928 {
3929 return error(GL_INVALID_OPERATION);
3930 }
3931 else
3932 {
3933 return error(GL_INVALID_VALUE);
3934 }
3935 }
3936
3937 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003938 {
3939 return error(GL_INVALID_OPERATION);
3940 }
3941
3942 if(!programObject->getUniformfv(location, &bufSize, params))
3943 {
3944 return error(GL_INVALID_OPERATION);
3945 }
3946 }
3947}
3948
3949void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3950{
3951 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3952
3953 es2::Context *context = es2::getContext();
3954
3955 if(context)
3956 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003957 es2::Program *programObject = context->getProgram(program);
3958
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003959 if(!programObject)
3960 {
3961 if(context->getShader(program))
3962 {
3963 return error(GL_INVALID_OPERATION);
3964 }
3965 else
3966 {
3967 return error(GL_INVALID_VALUE);
3968 }
3969 }
3970
3971 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003972 {
3973 return error(GL_INVALID_OPERATION);
3974 }
3975
3976 if(!programObject->getUniformfv(location, nullptr, params))
3977 {
3978 return error(GL_INVALID_OPERATION);
3979 }
3980 }
3981}
3982
3983void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3984{
3985 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3986 program, location, bufSize, params);
3987
3988 if(bufSize < 0)
3989 {
3990 return error(GL_INVALID_VALUE);
3991 }
3992
3993 es2::Context *context = es2::getContext();
3994
3995 if(context)
3996 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003997 es2::Program *programObject = context->getProgram(program);
3998
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003999 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004000 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004001 if(context->getShader(program))
4002 {
4003 return error(GL_INVALID_OPERATION);
4004 }
4005 else
4006 {
4007 return error(GL_INVALID_VALUE);
4008 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004009 }
4010
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004011 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04004012 {
4013 return error(GL_INVALID_OPERATION);
4014 }
4015
4016 if(!programObject->getUniformiv(location, &bufSize, params))
4017 {
4018 return error(GL_INVALID_OPERATION);
4019 }
4020 }
4021}
4022
4023void GetUniformiv(GLuint program, GLint location, GLint* params)
4024{
4025 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
4026
4027 es2::Context *context = es2::getContext();
4028
4029 if(context)
4030 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004031 es2::Program *programObject = context->getProgram(program);
4032
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004033 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004034 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004035 if(context->getShader(program))
4036 {
4037 return error(GL_INVALID_OPERATION);
4038 }
4039 else
4040 {
4041 return error(GL_INVALID_VALUE);
4042 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004043 }
4044
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004045 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04004046 {
4047 return error(GL_INVALID_OPERATION);
4048 }
4049
4050 if(!programObject->getUniformiv(location, nullptr, params))
4051 {
4052 return error(GL_INVALID_OPERATION);
4053 }
4054 }
4055}
4056
4057int GetUniformLocation(GLuint program, const GLchar* name)
4058{
4059 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
4060
4061 es2::Context *context = es2::getContext();
4062
4063 if(strstr(name, "gl_") == name)
4064 {
4065 return -1;
4066 }
4067
4068 if(context)
4069 {
4070 es2::Program *programObject = context->getProgram(program);
4071
4072 if(!programObject)
4073 {
4074 if(context->getShader(program))
4075 {
4076 return error(GL_INVALID_OPERATION, -1);
4077 }
4078 else
4079 {
4080 return error(GL_INVALID_VALUE, -1);
4081 }
4082 }
4083
4084 if(!programObject->isLinked())
4085 {
4086 return error(GL_INVALID_OPERATION, -1);
4087 }
4088
4089 return programObject->getUniformLocation(name);
4090 }
4091
4092 return -1;
4093}
4094
4095void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
4096{
4097 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
4098
4099 es2::Context *context = es2::getContext();
4100
4101 if(context)
4102 {
4103 if(index >= es2::MAX_VERTEX_ATTRIBS)
4104 {
4105 return error(GL_INVALID_VALUE);
4106 }
4107
4108 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4109
4110 GLint clientVersion = context->getClientVersion();
4111
4112 switch(pname)
4113 {
4114 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4115 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4116 break;
4117 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4118 *params = (GLfloat)attribState.mSize;
4119 break;
4120 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4121 *params = (GLfloat)attribState.mStride;
4122 break;
4123 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4124 *params = (GLfloat)attribState.mType;
4125 break;
4126 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4127 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4128 break;
4129 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4130 *params = (GLfloat)attribState.mBoundBuffer.name();
4131 break;
4132 case GL_CURRENT_VERTEX_ATTRIB:
4133 {
4134 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4135 for(int i = 0; i < 4; ++i)
4136 {
4137 params[i] = attrib.getCurrentValueF(i);
4138 }
4139 }
4140 break;
4141 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4142 if(clientVersion >= 3)
4143 {
4144 switch(attribState.mType)
4145 {
4146 case GL_BYTE:
4147 case GL_UNSIGNED_BYTE:
4148 case GL_SHORT:
4149 case GL_UNSIGNED_SHORT:
4150 case GL_INT:
4151 case GL_INT_2_10_10_10_REV:
4152 case GL_UNSIGNED_INT:
4153 case GL_FIXED:
4154 *params = (GLfloat)GL_TRUE;
4155 break;
4156 default:
4157 *params = (GLfloat)GL_FALSE;
4158 break;
4159 }
4160 break;
4161 }
4162 else return error(GL_INVALID_ENUM);
4163 default: return error(GL_INVALID_ENUM);
4164 }
4165 }
4166}
4167
4168void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4169{
4170 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4171
4172 es2::Context *context = es2::getContext();
4173
4174 if(context)
4175 {
4176 if(index >= es2::MAX_VERTEX_ATTRIBS)
4177 {
4178 return error(GL_INVALID_VALUE);
4179 }
4180
4181 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4182
4183 GLint clientVersion = context->getClientVersion();
4184
4185 switch(pname)
4186 {
4187 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4188 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4189 break;
4190 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4191 *params = attribState.mSize;
4192 break;
4193 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4194 *params = attribState.mStride;
4195 break;
4196 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4197 *params = attribState.mType;
4198 break;
4199 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4200 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4201 break;
4202 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4203 *params = attribState.mBoundBuffer.name();
4204 break;
4205 case GL_CURRENT_VERTEX_ATTRIB:
4206 {
4207 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4208 for(int i = 0; i < 4; ++i)
4209 {
4210 float currentValue = attrib.getCurrentValueF(i);
4211 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4212 }
4213 }
4214 break;
4215 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4216 if(clientVersion >= 3)
4217 {
4218 switch(attribState.mType)
4219 {
4220 case GL_BYTE:
4221 case GL_UNSIGNED_BYTE:
4222 case GL_SHORT:
4223 case GL_UNSIGNED_SHORT:
4224 case GL_INT:
4225 case GL_INT_2_10_10_10_REV:
4226 case GL_UNSIGNED_INT:
4227 case GL_FIXED:
4228 *params = GL_TRUE;
4229 break;
4230 default:
4231 *params = GL_FALSE;
4232 break;
4233 }
4234 break;
4235 }
4236 else return error(GL_INVALID_ENUM);
4237 default: return error(GL_INVALID_ENUM);
4238 }
4239 }
4240}
4241
4242void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4243{
4244 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4245
4246 es2::Context *context = es2::getContext();
4247
4248 if(context)
4249 {
4250 if(index >= es2::MAX_VERTEX_ATTRIBS)
4251 {
4252 return error(GL_INVALID_VALUE);
4253 }
4254
4255 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4256 {
4257 return error(GL_INVALID_ENUM);
4258 }
4259
4260 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4261 }
4262}
4263
4264void Hint(GLenum target, GLenum mode)
4265{
4266 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4267
4268 switch(mode)
4269 {
4270 case GL_FASTEST:
4271 case GL_NICEST:
4272 case GL_DONT_CARE:
4273 break;
4274 default:
4275 return error(GL_INVALID_ENUM);
4276 }
4277
4278 es2::Context *context = es2::getContext();
4279 switch(target)
4280 {
4281 case GL_GENERATE_MIPMAP_HINT:
4282 if(context) context->setGenerateMipmapHint(mode);
4283 break;
4284 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4285 if(context) context->setFragmentShaderDerivativeHint(mode);
4286 break;
Alexis Hetu010a4642017-07-18 14:33:04 -04004287 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4288 if(context) context->setTextureFilteringHint(mode);
4289 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004290 default:
4291 return error(GL_INVALID_ENUM);
4292 }
4293}
4294
4295GLboolean IsBuffer(GLuint buffer)
4296{
4297 TRACE("(GLuint buffer = %d)", buffer);
4298
4299 es2::Context *context = es2::getContext();
4300
4301 if(context && buffer)
4302 {
4303 es2::Buffer *bufferObject = context->getBuffer(buffer);
4304
4305 if(bufferObject)
4306 {
4307 return GL_TRUE;
4308 }
4309 }
4310
4311 return GL_FALSE;
4312}
4313
4314GLboolean IsEnabled(GLenum cap)
4315{
4316 TRACE("(GLenum cap = 0x%X)", cap);
4317
4318 es2::Context *context = es2::getContext();
4319
4320 if(context)
4321 {
4322 GLint clientVersion = context->getClientVersion();
4323
4324 switch(cap)
4325 {
4326 case GL_CULL_FACE: return context->isCullFaceEnabled();
4327 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4328 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4329 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4330 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4331 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4332 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4333 case GL_BLEND: return context->isBlendEnabled();
4334 case GL_DITHER: return context->isDitherEnabled();
4335 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4336 if(clientVersion >= 3)
4337 {
4338 return context->isPrimitiveRestartFixedIndexEnabled();
4339 }
4340 else return error(GL_INVALID_ENUM, false);
4341 case GL_RASTERIZER_DISCARD:
4342 if(clientVersion >= 3)
4343 {
4344 return context->isRasterizerDiscardEnabled();
4345 }
4346 else return error(GL_INVALID_ENUM, false);
4347 default:
4348 return error(GL_INVALID_ENUM, false);
4349 }
4350 }
4351
4352 return false;
4353}
4354
4355GLboolean IsFenceNV(GLuint fence)
4356{
4357 TRACE("(GLuint fence = %d)", fence);
4358
4359 es2::Context *context = es2::getContext();
4360
4361 if(context)
4362 {
4363 es2::Fence *fenceObject = context->getFence(fence);
4364
4365 if(!fenceObject)
4366 {
4367 return GL_FALSE;
4368 }
4369
4370 return fenceObject->isFence();
4371 }
4372
4373 return GL_FALSE;
4374}
4375
4376GLboolean IsFramebuffer(GLuint framebuffer)
4377{
4378 TRACE("(GLuint framebuffer = %d)", framebuffer);
4379
4380 es2::Context *context = es2::getContext();
4381
4382 if(context && framebuffer)
4383 {
4384 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4385
4386 if(framebufferObject)
4387 {
4388 return GL_TRUE;
4389 }
4390 }
4391
4392 return GL_FALSE;
4393}
4394
4395GLboolean IsProgram(GLuint program)
4396{
4397 TRACE("(GLuint program = %d)", program);
4398
4399 es2::Context *context = es2::getContext();
4400
4401 if(context && program)
4402 {
4403 es2::Program *programObject = context->getProgram(program);
4404
4405 if(programObject)
4406 {
4407 return GL_TRUE;
4408 }
4409 }
4410
4411 return GL_FALSE;
4412}
4413
4414GLboolean IsQueryEXT(GLuint name)
4415{
4416 TRACE("(GLuint name = %d)", name);
4417
4418 if(name == 0)
4419 {
4420 return GL_FALSE;
4421 }
4422
4423 es2::Context *context = es2::getContext();
4424
4425 if(context)
4426 {
4427 es2::Query *queryObject = context->getQuery(name);
4428
4429 if(queryObject)
4430 {
4431 return GL_TRUE;
4432 }
4433 }
4434
4435 return GL_FALSE;
4436}
4437
4438GLboolean IsRenderbuffer(GLuint renderbuffer)
4439{
4440 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4441
4442 es2::Context *context = es2::getContext();
4443
4444 if(context && renderbuffer)
4445 {
4446 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4447
4448 if(renderbufferObject)
4449 {
4450 return GL_TRUE;
4451 }
4452 }
4453
4454 return GL_FALSE;
4455}
4456
4457GLboolean IsShader(GLuint shader)
4458{
4459 TRACE("(GLuint shader = %d)", shader);
4460
4461 es2::Context *context = es2::getContext();
4462
4463 if(context && shader)
4464 {
4465 es2::Shader *shaderObject = context->getShader(shader);
4466
4467 if(shaderObject)
4468 {
4469 return GL_TRUE;
4470 }
4471 }
4472
4473 return GL_FALSE;
4474}
4475
4476GLboolean IsTexture(GLuint texture)
4477{
4478 TRACE("(GLuint texture = %d)", texture);
4479
4480 es2::Context *context = es2::getContext();
4481
4482 if(context && texture)
4483 {
4484 es2::Texture *textureObject = context->getTexture(texture);
4485
4486 if(textureObject)
4487 {
4488 return GL_TRUE;
4489 }
4490 }
4491
4492 return GL_FALSE;
4493}
4494
4495void LineWidth(GLfloat width)
4496{
4497 TRACE("(GLfloat width = %f)", width);
4498
4499 if(width <= 0.0f)
4500 {
4501 return error(GL_INVALID_VALUE);
4502 }
4503
4504 es2::Context *context = es2::getContext();
4505
4506 if(context)
4507 {
4508 context->setLineWidth(width);
4509 }
4510}
4511
4512void LinkProgram(GLuint program)
4513{
4514 TRACE("(GLuint program = %d)", program);
4515
4516 es2::Context *context = es2::getContext();
4517
4518 if(context)
4519 {
4520 es2::Program *programObject = context->getProgram(program);
4521
4522 if(!programObject)
4523 {
4524 if(context->getShader(program))
4525 {
4526 return error(GL_INVALID_OPERATION);
4527 }
4528 else
4529 {
4530 return error(GL_INVALID_VALUE);
4531 }
4532 }
4533
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004534 if(programObject == context->getCurrentProgram())
4535 {
4536 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4537 if(transformFeedback && transformFeedback->isActive())
4538 {
4539 return error(GL_INVALID_OPERATION);
4540 }
4541 }
4542
Nicolas Capens0bac2852016-05-07 06:09:58 -04004543 programObject->link();
4544 }
4545}
4546
4547void PixelStorei(GLenum pname, GLint param)
4548{
4549 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4550
4551 es2::Context *context = es2::getContext();
4552
4553 if(context)
4554 {
4555 GLint clientVersion = context->getClientVersion();
4556
4557 switch(pname)
4558 {
4559 case GL_UNPACK_ALIGNMENT:
4560 if(param != 1 && param != 2 && param != 4 && param != 8)
4561 {
4562 return error(GL_INVALID_VALUE);
4563 }
4564 context->setUnpackAlignment(param);
4565 break;
4566 case GL_PACK_ALIGNMENT:
4567 if(param != 1 && param != 2 && param != 4 && param != 8)
4568 {
4569 return error(GL_INVALID_VALUE);
4570 }
4571 context->setPackAlignment(param);
4572 break;
4573 case GL_PACK_ROW_LENGTH:
4574 if(clientVersion >= 3)
4575 {
4576 if(param < 0)
4577 {
4578 return error(GL_INVALID_VALUE);
4579 }
4580 context->setPackRowLength(param);
4581 break;
4582 }
4583 else return error(GL_INVALID_ENUM);
4584 case GL_PACK_SKIP_PIXELS:
4585 if(clientVersion >= 3)
4586 {
4587 if(param < 0)
4588 {
4589 return error(GL_INVALID_VALUE);
4590 }
4591 context->setPackSkipPixels(param);
4592 break;
4593 }
4594 else return error(GL_INVALID_ENUM);
4595 case GL_PACK_SKIP_ROWS:
4596 if(clientVersion >= 3)
4597 {
4598 if(param < 0)
4599 {
4600 return error(GL_INVALID_VALUE);
4601 }
4602 context->setPackSkipRows(param);
4603 break;
4604 }
4605 else return error(GL_INVALID_ENUM);
4606 case GL_UNPACK_ROW_LENGTH:
4607 if(clientVersion >= 3)
4608 {
4609 if(param < 0)
4610 {
4611 return error(GL_INVALID_VALUE);
4612 }
4613 context->setUnpackRowLength(param);
4614 break;
4615 }
4616 else return error(GL_INVALID_ENUM);
4617 case GL_UNPACK_IMAGE_HEIGHT:
4618 if(clientVersion >= 3)
4619 {
4620 if(param < 0)
4621 {
4622 return error(GL_INVALID_VALUE);
4623 }
4624 context->setUnpackImageHeight(param);
4625 break;
4626 }
4627 else return error(GL_INVALID_ENUM);
4628 case GL_UNPACK_SKIP_PIXELS:
4629 if(clientVersion >= 3)
4630 {
4631 if(param < 0)
4632 {
4633 return error(GL_INVALID_VALUE);
4634 }
4635 context->setUnpackSkipPixels(param);
4636 break;
4637 }
4638 else return error(GL_INVALID_ENUM);
4639 case GL_UNPACK_SKIP_ROWS:
4640 if(clientVersion >= 3)
4641 {
4642 if(param < 0)
4643 {
4644 return error(GL_INVALID_VALUE);
4645 }
4646 context->setUnpackSkipRows(param);
4647 break;
4648 }
4649 else return error(GL_INVALID_ENUM);
4650 case GL_UNPACK_SKIP_IMAGES:
4651 if(clientVersion >= 3) {
4652 if(param < 0)
4653 {
4654 return error(GL_INVALID_VALUE);
4655 }
4656 context->setUnpackSkipImages(param);
4657 break;
4658 }
4659 else return error(GL_INVALID_ENUM);
4660 default:
4661 return error(GL_INVALID_ENUM);
4662 }
4663 }
4664}
4665
4666void PolygonOffset(GLfloat factor, GLfloat units)
4667{
4668 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4669
4670 es2::Context *context = es2::getContext();
4671
4672 if(context)
4673 {
4674 context->setPolygonOffsetParams(factor, units);
4675 }
4676}
4677
4678void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4679 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4680{
4681 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4682 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4683 x, y, width, height, format, type, bufSize, data);
4684
4685 if(width < 0 || height < 0 || bufSize < 0)
4686 {
4687 return error(GL_INVALID_VALUE);
4688 }
4689
4690 es2::Context *context = es2::getContext();
4691
4692 if(context)
4693 {
4694 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4695 }
4696}
4697
4698void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4699{
4700 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4701 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4702 x, y, width, height, format, type, pixels);
4703
4704 if(width < 0 || height < 0)
4705 {
4706 return error(GL_INVALID_VALUE);
4707 }
4708
4709 es2::Context *context = es2::getContext();
4710
4711 if(context)
4712 {
4713 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4714 }
4715}
4716
4717void ReleaseShaderCompiler(void)
4718{
4719 TRACE("()");
4720
4721 es2::Shader::releaseCompiler();
4722}
4723
Nicolas Capens400667e2017-03-29 14:40:14 -04004724void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004725{
4726 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4727 target, samples, internalformat, width, height);
4728
4729 switch(target)
4730 {
4731 case GL_RENDERBUFFER:
4732 break;
4733 default:
4734 return error(GL_INVALID_ENUM);
4735 }
4736
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004737 if(width < 0 || height < 0 || samples < 0 ||
4738 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4739 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004740 {
4741 return error(GL_INVALID_VALUE);
4742 }
4743
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004744 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
4745 (sw::Surface::isNonNormalizedInteger(es2sw::ConvertRenderbufferFormat(internalformat)) && samples > 0))
4746 {
4747 return error(GL_INVALID_OPERATION);
4748 }
4749
Nicolas Capens0bac2852016-05-07 06:09:58 -04004750 es2::Context *context = es2::getContext();
4751
4752 if(context)
4753 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004754 GLuint handle = context->getRenderbufferName();
4755 if(handle == 0)
4756 {
4757 return error(GL_INVALID_OPERATION);
4758 }
4759
4760 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004761
4762 if(IsColorRenderable(internalformat, clientVersion, false))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004763 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004764 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004765 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004766 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4767 {
4768 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4769 }
4770 else if(IsDepthRenderable(internalformat, clientVersion))
4771 {
4772 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4773 }
4774 else if(IsStencilRenderable(internalformat, clientVersion))
4775 {
4776 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4777 }
4778 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004779 }
4780}
4781
Nicolas Capens400667e2017-03-29 14:40:14 -04004782void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4783{
4784 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4785}
4786
Nicolas Capens0bac2852016-05-07 06:09:58 -04004787void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4788{
Nicolas Capens400667e2017-03-29 14:40:14 -04004789 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004790}
4791
4792void SampleCoverage(GLclampf value, GLboolean invert)
4793{
4794 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4795
4796 es2::Context* context = es2::getContext();
4797
4798 if(context)
4799 {
4800 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4801 }
4802}
4803
4804void SetFenceNV(GLuint fence, GLenum condition)
4805{
4806 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4807
4808 if(condition != GL_ALL_COMPLETED_NV)
4809 {
4810 return error(GL_INVALID_ENUM);
4811 }
4812
4813 es2::Context *context = es2::getContext();
4814
4815 if(context)
4816 {
4817 es2::Fence *fenceObject = context->getFence(fence);
4818
4819 if(!fenceObject)
4820 {
4821 return error(GL_INVALID_OPERATION);
4822 }
4823
4824 fenceObject->setFence(condition);
4825 }
4826}
4827
4828void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4829{
4830 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4831
4832 if(width < 0 || height < 0)
4833 {
4834 return error(GL_INVALID_VALUE);
4835 }
4836
4837 es2::Context* context = es2::getContext();
4838
4839 if(context)
4840 {
4841 context->setScissorParams(x, y, width, height);
4842 }
4843}
4844
4845void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4846{
4847 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4848 "const GLvoid* binary = %p, GLsizei length = %d)",
4849 n, shaders, binaryformat, binary, length);
4850
4851 // No binary shader formats are supported.
4852 return error(GL_INVALID_ENUM);
4853}
4854
4855void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4856{
4857 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4858 shader, count, string, length);
4859
4860 if(count < 0)
4861 {
4862 return error(GL_INVALID_VALUE);
4863 }
4864
4865 es2::Context *context = es2::getContext();
4866
4867 if(context)
4868 {
4869 es2::Shader *shaderObject = context->getShader(shader);
4870
4871 if(!shaderObject)
4872 {
4873 if(context->getProgram(shader))
4874 {
4875 return error(GL_INVALID_OPERATION);
4876 }
4877 else
4878 {
4879 return error(GL_INVALID_VALUE);
4880 }
4881 }
4882
4883 shaderObject->setSource(count, string, length);
4884 }
4885}
4886
4887void StencilFunc(GLenum func, GLint ref, GLuint mask)
4888{
4889 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4890}
4891
4892void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4893{
4894 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4895
4896 switch(face)
4897 {
4898 case GL_FRONT:
4899 case GL_BACK:
4900 case GL_FRONT_AND_BACK:
4901 break;
4902 default:
4903 return error(GL_INVALID_ENUM);
4904 }
4905
4906 switch(func)
4907 {
4908 case GL_NEVER:
4909 case GL_ALWAYS:
4910 case GL_LESS:
4911 case GL_LEQUAL:
4912 case GL_EQUAL:
4913 case GL_GEQUAL:
4914 case GL_GREATER:
4915 case GL_NOTEQUAL:
4916 break;
4917 default:
4918 return error(GL_INVALID_ENUM);
4919 }
4920
4921 es2::Context *context = es2::getContext();
4922
4923 if(context)
4924 {
4925 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4926 {
4927 context->setStencilParams(func, ref, mask);
4928 }
4929
4930 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4931 {
4932 context->setStencilBackParams(func, ref, mask);
4933 }
4934 }
4935}
4936
4937void StencilMask(GLuint mask)
4938{
4939 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4940}
4941
4942void StencilMaskSeparate(GLenum face, GLuint mask)
4943{
4944 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4945
4946 switch(face)
4947 {
4948 case GL_FRONT:
4949 case GL_BACK:
4950 case GL_FRONT_AND_BACK:
4951 break;
4952 default:
4953 return error(GL_INVALID_ENUM);
4954 }
4955
4956 es2::Context *context = es2::getContext();
4957
4958 if(context)
4959 {
4960 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4961 {
4962 context->setStencilWritemask(mask);
4963 }
4964
4965 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4966 {
4967 context->setStencilBackWritemask(mask);
4968 }
4969 }
4970}
4971
4972void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4973{
4974 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4975}
4976
4977void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4978{
4979 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4980 face, fail, zfail, zpass);
4981
4982 switch(face)
4983 {
4984 case GL_FRONT:
4985 case GL_BACK:
4986 case GL_FRONT_AND_BACK:
4987 break;
4988 default:
4989 return error(GL_INVALID_ENUM);
4990 }
4991
4992 switch(fail)
4993 {
4994 case GL_ZERO:
4995 case GL_KEEP:
4996 case GL_REPLACE:
4997 case GL_INCR:
4998 case GL_DECR:
4999 case GL_INVERT:
5000 case GL_INCR_WRAP:
5001 case GL_DECR_WRAP:
5002 break;
5003 default:
5004 return error(GL_INVALID_ENUM);
5005 }
5006
5007 switch(zfail)
5008 {
5009 case GL_ZERO:
5010 case GL_KEEP:
5011 case GL_REPLACE:
5012 case GL_INCR:
5013 case GL_DECR:
5014 case GL_INVERT:
5015 case GL_INCR_WRAP:
5016 case GL_DECR_WRAP:
5017 break;
5018 default:
5019 return error(GL_INVALID_ENUM);
5020 }
5021
5022 switch(zpass)
5023 {
5024 case GL_ZERO:
5025 case GL_KEEP:
5026 case GL_REPLACE:
5027 case GL_INCR:
5028 case GL_DECR:
5029 case GL_INVERT:
5030 case GL_INCR_WRAP:
5031 case GL_DECR_WRAP:
5032 break;
5033 default:
5034 return error(GL_INVALID_ENUM);
5035 }
5036
5037 es2::Context *context = es2::getContext();
5038
5039 if(context)
5040 {
5041 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
5042 {
5043 context->setStencilOperations(fail, zfail, zpass);
5044 }
5045
5046 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
5047 {
5048 context->setStencilBackOperations(fail, zfail, zpass);
5049 }
5050 }
5051}
5052
5053GLboolean TestFenceNV(GLuint fence)
5054{
5055 TRACE("(GLuint fence = %d)", fence);
5056
5057 es2::Context *context = es2::getContext();
5058
5059 if(context)
5060 {
5061 es2::Fence *fenceObject = context->getFence(fence);
5062
5063 if(!fenceObject)
5064 {
5065 return error(GL_INVALID_OPERATION, GL_TRUE);
5066 }
5067
5068 return fenceObject->testFence();
5069 }
5070
5071 return GL_TRUE;
5072}
5073
5074void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005075 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005076{
5077 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005078 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
5079 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005080
5081 if(!validImageSize(level, width, height))
5082 {
5083 return error(GL_INVALID_VALUE);
5084 }
5085
5086 es2::Context *context = es2::getContext();
5087
5088 if(context)
5089 {
5090 GLint clientVersion = context->getClientVersion();
5091 if(clientVersion < 3)
5092 {
5093 if(internalformat != (GLint)format)
5094 {
5095 return error(GL_INVALID_OPERATION);
5096 }
5097 }
5098
5099 GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
5100 if(validationError != GL_NONE)
5101 {
5102 return error(validationError);
5103 }
5104
5105 if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
5106 {
5107 return;
5108 }
5109
5110 if(border != 0)
5111 {
5112 return error(GL_INVALID_VALUE);
5113 }
5114
5115 switch(target)
5116 {
5117 case GL_TEXTURE_2D:
5118 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5119 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5120 {
5121 return error(GL_INVALID_VALUE);
5122 }
5123 break;
5124 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5125 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5126 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5127 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5128 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5129 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5130 if(width != height)
5131 {
5132 return error(GL_INVALID_VALUE);
5133 }
5134
5135 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5136 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5137 {
5138 return error(GL_INVALID_VALUE);
5139 }
5140 break;
5141 default:
5142 return error(GL_INVALID_ENUM);
5143 }
5144
5145 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
5146
Alexis Hetu848aa7f2017-11-17 13:15:32 -05005147 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005148 if(validationError != GL_NONE)
5149 {
5150 return error(validationError);
5151 }
5152
Nicolas Capens0bac2852016-05-07 06:09:58 -04005153 if(target == GL_TEXTURE_2D)
5154 {
5155 es2::Texture2D *texture = context->getTexture2D();
5156
5157 if(!texture)
5158 {
5159 return error(GL_INVALID_OPERATION);
5160 }
5161
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005162 texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005163 }
5164 else
5165 {
5166 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5167
5168 if(!texture)
5169 {
5170 return error(GL_INVALID_OPERATION);
5171 }
5172
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005173 texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005174 }
5175 }
5176}
5177
5178void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5179{
5180 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5181
5182 es2::Context *context = es2::getContext();
5183
5184 if(context)
5185 {
5186 es2::Texture *texture;
5187
5188 GLint clientVersion = context->getClientVersion();
5189
5190 switch(target)
5191 {
5192 case GL_TEXTURE_2D:
5193 texture = context->getTexture2D();
5194 break;
5195 case GL_TEXTURE_2D_ARRAY:
5196 if(clientVersion < 3)
5197 {
5198 return error(GL_INVALID_ENUM);
5199 }
5200 else
5201 {
5202 texture = context->getTexture2DArray();
5203 }
5204 break;
5205 case GL_TEXTURE_3D_OES:
5206 texture = context->getTexture3D();
5207 break;
5208 case GL_TEXTURE_CUBE_MAP:
5209 texture = context->getTextureCubeMap();
5210 break;
5211 case GL_TEXTURE_EXTERNAL_OES:
5212 texture = context->getTextureExternal();
5213 break;
5214 default:
5215 return error(GL_INVALID_ENUM);
5216 }
5217
5218 switch(pname)
5219 {
5220 case GL_TEXTURE_WRAP_S:
5221 if(!texture->setWrapS((GLenum)param))
5222 {
5223 return error(GL_INVALID_ENUM);
5224 }
5225 break;
5226 case GL_TEXTURE_WRAP_T:
5227 if(!texture->setWrapT((GLenum)param))
5228 {
5229 return error(GL_INVALID_ENUM);
5230 }
5231 break;
5232 case GL_TEXTURE_WRAP_R_OES:
5233 if(!texture->setWrapR((GLenum)param))
5234 {
5235 return error(GL_INVALID_ENUM);
5236 }
5237 break;
5238 case GL_TEXTURE_MIN_FILTER:
5239 if(!texture->setMinFilter((GLenum)param))
5240 {
5241 return error(GL_INVALID_ENUM);
5242 }
5243 break;
5244 case GL_TEXTURE_MAG_FILTER:
5245 if(!texture->setMagFilter((GLenum)param))
5246 {
5247 return error(GL_INVALID_ENUM);
5248 }
5249 break;
5250 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5251 if(!texture->setMaxAnisotropy(param))
5252 {
5253 return error(GL_INVALID_VALUE);
5254 }
5255 break;
5256 case GL_TEXTURE_BASE_LEVEL:
5257 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5258 {
5259 return error(GL_INVALID_VALUE);
5260 }
5261 break;
5262 case GL_TEXTURE_COMPARE_FUNC:
5263 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5264 {
5265 return error(GL_INVALID_VALUE);
5266 }
5267 break;
5268 case GL_TEXTURE_COMPARE_MODE:
5269 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5270 {
5271 return error(GL_INVALID_VALUE);
5272 }
5273 break;
5274 case GL_TEXTURE_MAX_LEVEL:
5275 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5276 {
5277 return error(GL_INVALID_VALUE);
5278 }
5279 break;
5280 case GL_TEXTURE_MAX_LOD:
5281 if(clientVersion < 3 || !texture->setMaxLOD(param))
5282 {
5283 return error(GL_INVALID_VALUE);
5284 }
5285 break;
5286 case GL_TEXTURE_MIN_LOD:
5287 if(clientVersion < 3 || !texture->setMinLOD(param))
5288 {
5289 return error(GL_INVALID_VALUE);
5290 }
5291 break;
5292 case GL_TEXTURE_SWIZZLE_R:
5293 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5294 {
5295 return error(GL_INVALID_VALUE);
5296 }
5297 break;
5298 case GL_TEXTURE_SWIZZLE_G:
5299 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5300 {
5301 return error(GL_INVALID_VALUE);
5302 }
5303 break;
5304 case GL_TEXTURE_SWIZZLE_B:
5305 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5306 {
5307 return error(GL_INVALID_VALUE);
5308 }
5309 break;
5310 case GL_TEXTURE_SWIZZLE_A:
5311 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5312 {
5313 return error(GL_INVALID_VALUE);
5314 }
5315 break;
5316 default:
5317 return error(GL_INVALID_ENUM);
5318 }
5319 }
5320}
5321
5322void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5323{
5324 glTexParameterf(target, pname, *params);
5325}
5326
5327void TexParameteri(GLenum target, GLenum pname, GLint param)
5328{
5329 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5330
5331 es2::Context *context = es2::getContext();
5332
5333 if(context)
5334 {
5335 es2::Texture *texture;
5336
5337 GLint clientVersion = context->getClientVersion();
5338
5339 switch(target)
5340 {
5341 case GL_TEXTURE_2D:
5342 texture = context->getTexture2D();
5343 break;
5344 case GL_TEXTURE_2D_ARRAY:
5345 if(clientVersion < 3)
5346 {
5347 return error(GL_INVALID_ENUM);
5348 }
5349 else
5350 {
5351 texture = context->getTexture2DArray();
5352 }
5353 break;
5354 case GL_TEXTURE_3D_OES:
5355 texture = context->getTexture3D();
5356 break;
5357 case GL_TEXTURE_CUBE_MAP:
5358 texture = context->getTextureCubeMap();
5359 break;
5360 case GL_TEXTURE_EXTERNAL_OES:
5361 texture = context->getTextureExternal();
5362 break;
5363 default:
5364 return error(GL_INVALID_ENUM);
5365 }
5366
5367 switch(pname)
5368 {
5369 case GL_TEXTURE_WRAP_S:
5370 if(!texture->setWrapS((GLenum)param))
5371 {
5372 return error(GL_INVALID_ENUM);
5373 }
5374 break;
5375 case GL_TEXTURE_WRAP_T:
5376 if(!texture->setWrapT((GLenum)param))
5377 {
5378 return error(GL_INVALID_ENUM);
5379 }
5380 break;
5381 case GL_TEXTURE_WRAP_R_OES:
5382 if(!texture->setWrapR((GLenum)param))
5383 {
5384 return error(GL_INVALID_ENUM);
5385 }
5386 break;
5387 case GL_TEXTURE_MIN_FILTER:
5388 if(!texture->setMinFilter((GLenum)param))
5389 {
5390 return error(GL_INVALID_ENUM);
5391 }
5392 break;
5393 case GL_TEXTURE_MAG_FILTER:
5394 if(!texture->setMagFilter((GLenum)param))
5395 {
5396 return error(GL_INVALID_ENUM);
5397 }
5398 break;
5399 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5400 if(!texture->setMaxAnisotropy((GLfloat)param))
5401 {
5402 return error(GL_INVALID_VALUE);
5403 }
5404 break;
5405 case GL_TEXTURE_BASE_LEVEL:
5406 if(clientVersion < 3 || !texture->setBaseLevel(param))
5407 {
5408 return error(GL_INVALID_VALUE);
5409 }
5410 break;
5411 case GL_TEXTURE_COMPARE_FUNC:
5412 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5413 {
5414 return error(GL_INVALID_VALUE);
5415 }
5416 break;
5417 case GL_TEXTURE_COMPARE_MODE:
5418 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5419 {
5420 return error(GL_INVALID_VALUE);
5421 }
5422 break;
5423 case GL_TEXTURE_MAX_LEVEL:
5424 if(clientVersion < 3 || !texture->setMaxLevel(param))
5425 {
5426 return error(GL_INVALID_VALUE);
5427 }
5428 break;
5429 case GL_TEXTURE_MAX_LOD:
5430 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5431 {
5432 return error(GL_INVALID_VALUE);
5433 }
5434 break;
5435 case GL_TEXTURE_MIN_LOD:
5436 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5437 {
5438 return error(GL_INVALID_VALUE);
5439 }
5440 break;
5441 case GL_TEXTURE_SWIZZLE_R:
5442 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5443 {
5444 return error(GL_INVALID_VALUE);
5445 }
5446 break;
5447 case GL_TEXTURE_SWIZZLE_G:
5448 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5449 {
5450 return error(GL_INVALID_VALUE);
5451 }
5452 break;
5453 case GL_TEXTURE_SWIZZLE_B:
5454 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5455 {
5456 return error(GL_INVALID_VALUE);
5457 }
5458 break;
5459 case GL_TEXTURE_SWIZZLE_A:
5460 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5461 {
5462 return error(GL_INVALID_VALUE);
5463 }
5464 break;
5465 default:
5466 return error(GL_INVALID_ENUM);
5467 }
5468 }
5469}
5470
5471void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5472{
5473 glTexParameteri(target, pname, *params);
5474}
5475
5476void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005477 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005478{
5479 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5480 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005481 "const GLvoid* data = %p)",
5482 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005483
5484 if(!es2::IsTextureTarget(target))
5485 {
5486 return error(GL_INVALID_ENUM);
5487 }
5488
5489 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5490 {
5491 return error(GL_INVALID_VALUE);
5492 }
5493
5494 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5495 {
5496 return error(GL_INVALID_VALUE);
5497 }
5498
5499 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5500 {
5501 return error(GL_INVALID_VALUE);
5502 }
5503
5504 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
5505 {
5506 return;
5507 }
5508
Alexis Hetu53f48092016-06-17 14:08:06 -04005509 if(width == 0 || height == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005510 {
5511 return;
5512 }
5513
5514 es2::Context *context = es2::getContext();
5515
5516 if(context)
5517 {
5518 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
5519
Alexis Hetu848aa7f2017-11-17 13:15:32 -05005520 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005521 if(validationError != GL_NONE)
5522 {
5523 return error(validationError);
5524 }
5525
Nicolas Capens0bac2852016-05-07 06:09:58 -04005526 if(target == GL_TEXTURE_2D)
5527 {
5528 es2::Texture2D *texture = context->getTexture2D();
5529
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005530 validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005531
5532 if(validationError == GL_NONE)
5533 {
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005534 texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005535 }
5536 else
5537 {
5538 return error(validationError);
5539 }
5540 }
5541 else if(es2::IsCubemapTextureTarget(target))
5542 {
5543 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5544
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005545 validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005546
5547 if(validationError == GL_NONE)
5548 {
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005549 texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005550 }
5551 else
5552 {
5553 return error(validationError);
5554 }
5555 }
5556 else UNREACHABLE(target);
5557 }
5558}
5559
5560void Uniform1f(GLint location, GLfloat x)
5561{
5562 glUniform1fv(location, 1, &x);
5563}
5564
5565void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5566{
5567 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5568
5569 if(count < 0)
5570 {
5571 return error(GL_INVALID_VALUE);
5572 }
5573
Nicolas Capens0bac2852016-05-07 06:09:58 -04005574 es2::Context *context = es2::getContext();
5575
5576 if(context)
5577 {
5578 es2::Program *program = context->getCurrentProgram();
5579
5580 if(!program)
5581 {
5582 return error(GL_INVALID_OPERATION);
5583 }
5584
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005585 if(location == -1)
5586 {
5587 return;
5588 }
5589
Nicolas Capens0bac2852016-05-07 06:09:58 -04005590 if(!program->setUniform1fv(location, count, v))
5591 {
5592 return error(GL_INVALID_OPERATION);
5593 }
5594 }
5595}
5596
5597void Uniform1i(GLint location, GLint x)
5598{
5599 glUniform1iv(location, 1, &x);
5600}
5601
5602void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5603{
5604 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5605
5606 if(count < 0)
5607 {
5608 return error(GL_INVALID_VALUE);
5609 }
5610
Nicolas Capens0bac2852016-05-07 06:09:58 -04005611 es2::Context *context = es2::getContext();
5612
5613 if(context)
5614 {
5615 es2::Program *program = context->getCurrentProgram();
5616
5617 if(!program)
5618 {
5619 return error(GL_INVALID_OPERATION);
5620 }
5621
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005622 if(location == -1)
5623 {
5624 return;
5625 }
5626
Nicolas Capens0bac2852016-05-07 06:09:58 -04005627 if(!program->setUniform1iv(location, count, v))
5628 {
5629 return error(GL_INVALID_OPERATION);
5630 }
5631 }
5632}
5633
5634void Uniform2f(GLint location, GLfloat x, GLfloat y)
5635{
5636 GLfloat xy[2] = {x, y};
5637
5638 glUniform2fv(location, 1, (GLfloat*)&xy);
5639}
5640
5641void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5642{
5643 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5644
5645 if(count < 0)
5646 {
5647 return error(GL_INVALID_VALUE);
5648 }
5649
Nicolas Capens0bac2852016-05-07 06:09:58 -04005650 es2::Context *context = es2::getContext();
5651
5652 if(context)
5653 {
5654 es2::Program *program = context->getCurrentProgram();
5655
5656 if(!program)
5657 {
5658 return error(GL_INVALID_OPERATION);
5659 }
5660
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005661 if(location == -1)
5662 {
5663 return;
5664 }
5665
Nicolas Capens0bac2852016-05-07 06:09:58 -04005666 if(!program->setUniform2fv(location, count, v))
5667 {
5668 return error(GL_INVALID_OPERATION);
5669 }
5670 }
5671}
5672
5673void Uniform2i(GLint location, GLint x, GLint y)
5674{
5675 GLint xy[4] = {x, y};
5676
5677 glUniform2iv(location, 1, (GLint*)&xy);
5678}
5679
5680void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5681{
5682 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5683
5684 if(count < 0)
5685 {
5686 return error(GL_INVALID_VALUE);
5687 }
5688
Nicolas Capens0bac2852016-05-07 06:09:58 -04005689 es2::Context *context = es2::getContext();
5690
5691 if(context)
5692 {
5693 es2::Program *program = context->getCurrentProgram();
5694
5695 if(!program)
5696 {
5697 return error(GL_INVALID_OPERATION);
5698 }
5699
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005700 if(location == -1)
5701 {
5702 return;
5703 }
5704
Nicolas Capens0bac2852016-05-07 06:09:58 -04005705 if(!program->setUniform2iv(location, count, v))
5706 {
5707 return error(GL_INVALID_OPERATION);
5708 }
5709 }
5710}
5711
5712void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5713{
5714 GLfloat xyz[3] = {x, y, z};
5715
5716 glUniform3fv(location, 1, (GLfloat*)&xyz);
5717}
5718
5719void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5720{
5721 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5722
5723 if(count < 0)
5724 {
5725 return error(GL_INVALID_VALUE);
5726 }
5727
Nicolas Capens0bac2852016-05-07 06:09:58 -04005728 es2::Context *context = es2::getContext();
5729
5730 if(context)
5731 {
5732 es2::Program *program = context->getCurrentProgram();
5733
5734 if(!program)
5735 {
5736 return error(GL_INVALID_OPERATION);
5737 }
5738
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005739 if(location == -1)
5740 {
5741 return;
5742 }
5743
Nicolas Capens0bac2852016-05-07 06:09:58 -04005744 if(!program->setUniform3fv(location, count, v))
5745 {
5746 return error(GL_INVALID_OPERATION);
5747 }
5748 }
5749}
5750
5751void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5752{
5753 GLint xyz[3] = {x, y, z};
5754
5755 glUniform3iv(location, 1, (GLint*)&xyz);
5756}
5757
5758void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5759{
5760 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5761
5762 if(count < 0)
5763 {
5764 return error(GL_INVALID_VALUE);
5765 }
5766
Nicolas Capens0bac2852016-05-07 06:09:58 -04005767 es2::Context *context = es2::getContext();
5768
5769 if(context)
5770 {
5771 es2::Program *program = context->getCurrentProgram();
5772
5773 if(!program)
5774 {
5775 return error(GL_INVALID_OPERATION);
5776 }
5777
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005778 if(location == -1)
5779 {
5780 return;
5781 }
5782
Nicolas Capens0bac2852016-05-07 06:09:58 -04005783 if(!program->setUniform3iv(location, count, v))
5784 {
5785 return error(GL_INVALID_OPERATION);
5786 }
5787 }
5788}
5789
5790void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5791{
5792 GLfloat xyzw[4] = {x, y, z, w};
5793
5794 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5795}
5796
5797void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5798{
5799 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5800
5801 if(count < 0)
5802 {
5803 return error(GL_INVALID_VALUE);
5804 }
5805
Nicolas Capens0bac2852016-05-07 06:09:58 -04005806 es2::Context *context = es2::getContext();
5807
5808 if(context)
5809 {
5810 es2::Program *program = context->getCurrentProgram();
5811
5812 if(!program)
5813 {
5814 return error(GL_INVALID_OPERATION);
5815 }
5816
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005817 if(location == -1)
5818 {
5819 return;
5820 }
5821
Nicolas Capens0bac2852016-05-07 06:09:58 -04005822 if(!program->setUniform4fv(location, count, v))
5823 {
5824 return error(GL_INVALID_OPERATION);
5825 }
5826 }
5827}
5828
5829void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5830{
5831 GLint xyzw[4] = {x, y, z, w};
5832
5833 glUniform4iv(location, 1, (GLint*)&xyzw);
5834}
5835
5836void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5837{
5838 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5839
5840 if(count < 0)
5841 {
5842 return error(GL_INVALID_VALUE);
5843 }
5844
Nicolas Capens0bac2852016-05-07 06:09:58 -04005845 es2::Context *context = es2::getContext();
5846
5847 if(context)
5848 {
5849 es2::Program *program = context->getCurrentProgram();
5850
5851 if(!program)
5852 {
5853 return error(GL_INVALID_OPERATION);
5854 }
5855
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005856 if(location == -1)
5857 {
5858 return;
5859 }
5860
Nicolas Capens0bac2852016-05-07 06:09:58 -04005861 if(!program->setUniform4iv(location, count, v))
5862 {
5863 return error(GL_INVALID_OPERATION);
5864 }
5865 }
5866}
5867
5868void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5869{
5870 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5871 location, count, transpose, value);
5872
5873 if(count < 0)
5874 {
5875 return error(GL_INVALID_VALUE);
5876 }
5877
Nicolas Capens0bac2852016-05-07 06:09:58 -04005878 es2::Context *context = es2::getContext();
5879
5880 if(context)
5881 {
5882 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5883 {
5884 return error(GL_INVALID_VALUE);
5885 }
5886
5887 es2::Program *program = context->getCurrentProgram();
5888
5889 if(!program)
5890 {
5891 return error(GL_INVALID_OPERATION);
5892 }
5893
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005894 if(location == -1)
5895 {
5896 return;
5897 }
5898
Nicolas Capens0bac2852016-05-07 06:09:58 -04005899 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5900 {
5901 return error(GL_INVALID_OPERATION);
5902 }
5903 }
5904}
5905
5906void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5907{
5908 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5909 location, count, transpose, value);
5910
5911 if(count < 0)
5912 {
5913 return error(GL_INVALID_VALUE);
5914 }
5915
Nicolas Capens0bac2852016-05-07 06:09:58 -04005916 es2::Context *context = es2::getContext();
5917
5918 if(context)
5919 {
5920 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5921 {
5922 return error(GL_INVALID_VALUE);
5923 }
5924
5925 es2::Program *program = context->getCurrentProgram();
5926
5927 if(!program)
5928 {
5929 return error(GL_INVALID_OPERATION);
5930 }
5931
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005932 if(location == -1)
5933 {
5934 return;
5935 }
5936
Nicolas Capens0bac2852016-05-07 06:09:58 -04005937 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5938 {
5939 return error(GL_INVALID_OPERATION);
5940 }
5941 }
5942}
5943
5944void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5945{
5946 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5947 location, count, transpose, value);
5948
5949 if(count < 0)
5950 {
5951 return error(GL_INVALID_VALUE);
5952 }
5953
Nicolas Capens0bac2852016-05-07 06:09:58 -04005954 es2::Context *context = es2::getContext();
5955
5956 if(context)
5957 {
5958 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5959 {
5960 return error(GL_INVALID_VALUE);
5961 }
5962
5963 es2::Program *program = context->getCurrentProgram();
5964
5965 if(!program)
5966 {
5967 return error(GL_INVALID_OPERATION);
5968 }
5969
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005970 if(location == -1)
5971 {
5972 return;
5973 }
5974
Nicolas Capens0bac2852016-05-07 06:09:58 -04005975 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5976 {
5977 return error(GL_INVALID_OPERATION);
5978 }
5979 }
5980}
5981
5982void UseProgram(GLuint program)
5983{
5984 TRACE("(GLuint program = %d)", program);
5985
5986 es2::Context *context = es2::getContext();
5987
5988 if(context)
5989 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005990 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5991 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5992 {
5993 return error(GL_INVALID_OPERATION);
5994 }
5995
Nicolas Capens0bac2852016-05-07 06:09:58 -04005996 es2::Program *programObject = context->getProgram(program);
5997
5998 if(!programObject && program != 0)
5999 {
6000 if(context->getShader(program))
6001 {
6002 return error(GL_INVALID_OPERATION);
6003 }
6004 else
6005 {
6006 return error(GL_INVALID_VALUE);
6007 }
6008 }
6009
6010 if(program != 0 && !programObject->isLinked())
6011 {
6012 return error(GL_INVALID_OPERATION);
6013 }
6014
6015 context->useProgram(program);
6016 }
6017}
6018
6019void ValidateProgram(GLuint program)
6020{
6021 TRACE("(GLuint program = %d)", program);
6022
6023 es2::Context *context = es2::getContext();
6024
6025 if(context)
6026 {
6027 es2::Program *programObject = context->getProgram(program);
6028
6029 if(!programObject)
6030 {
6031 if(context->getShader(program))
6032 {
6033 return error(GL_INVALID_OPERATION);
6034 }
6035 else
6036 {
6037 return error(GL_INVALID_VALUE);
6038 }
6039 }
6040
Ben Vanik1fd3b282017-07-10 14:08:12 -07006041 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04006042 }
6043}
6044
6045void VertexAttrib1f(GLuint index, GLfloat x)
6046{
6047 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
6048
6049 if(index >= es2::MAX_VERTEX_ATTRIBS)
6050 {
6051 return error(GL_INVALID_VALUE);
6052 }
6053
6054 es2::Context *context = es2::getContext();
6055
6056 if(context)
6057 {
6058 GLfloat vals[4] = { x, 0, 0, 1 };
6059 context->setVertexAttrib(index, vals);
6060 }
6061}
6062
6063void VertexAttrib1fv(GLuint index, const GLfloat* values)
6064{
6065 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6066
6067 if(index >= es2::MAX_VERTEX_ATTRIBS)
6068 {
6069 return error(GL_INVALID_VALUE);
6070 }
6071
6072 es2::Context *context = es2::getContext();
6073
6074 if(context)
6075 {
6076 GLfloat vals[4] = { values[0], 0, 0, 1 };
6077 context->setVertexAttrib(index, vals);
6078 }
6079}
6080
6081void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
6082{
6083 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
6084
6085 if(index >= es2::MAX_VERTEX_ATTRIBS)
6086 {
6087 return error(GL_INVALID_VALUE);
6088 }
6089
6090 es2::Context *context = es2::getContext();
6091
6092 if(context)
6093 {
6094 GLfloat vals[4] = { x, y, 0, 1 };
6095 context->setVertexAttrib(index, vals);
6096 }
6097}
6098
6099void VertexAttrib2fv(GLuint index, const GLfloat* values)
6100{
6101 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6102
6103 if(index >= es2::MAX_VERTEX_ATTRIBS)
6104 {
6105 return error(GL_INVALID_VALUE);
6106 }
6107
6108 es2::Context *context = es2::getContext();
6109
6110 if(context)
6111 {
6112 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6113 context->setVertexAttrib(index, vals);
6114 }
6115}
6116
6117void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6118{
6119 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
6120
6121 if(index >= es2::MAX_VERTEX_ATTRIBS)
6122 {
6123 return error(GL_INVALID_VALUE);
6124 }
6125
6126 es2::Context *context = es2::getContext();
6127
6128 if(context)
6129 {
6130 GLfloat vals[4] = { x, y, z, 1 };
6131 context->setVertexAttrib(index, vals);
6132 }
6133}
6134
6135void VertexAttrib3fv(GLuint index, const GLfloat* values)
6136{
6137 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6138
6139 if(index >= es2::MAX_VERTEX_ATTRIBS)
6140 {
6141 return error(GL_INVALID_VALUE);
6142 }
6143
6144 es2::Context *context = es2::getContext();
6145
6146 if(context)
6147 {
6148 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6149 context->setVertexAttrib(index, vals);
6150 }
6151}
6152
6153void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6154{
6155 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6156
6157 if(index >= es2::MAX_VERTEX_ATTRIBS)
6158 {
6159 return error(GL_INVALID_VALUE);
6160 }
6161
6162 es2::Context *context = es2::getContext();
6163
6164 if(context)
6165 {
6166 GLfloat vals[4] = { x, y, z, w };
6167 context->setVertexAttrib(index, vals);
6168 }
6169}
6170
6171void VertexAttrib4fv(GLuint index, const GLfloat* values)
6172{
6173 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6174
6175 if(index >= es2::MAX_VERTEX_ATTRIBS)
6176 {
6177 return error(GL_INVALID_VALUE);
6178 }
6179
6180 es2::Context *context = es2::getContext();
6181
6182 if(context)
6183 {
6184 context->setVertexAttrib(index, values);
6185 }
6186}
6187
6188void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6189{
6190 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6191 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6192 index, size, type, normalized, stride, ptr);
6193
6194 if(index >= es2::MAX_VERTEX_ATTRIBS)
6195 {
6196 return error(GL_INVALID_VALUE);
6197 }
6198
6199 if(size < 1 || size > 4)
6200 {
6201 return error(GL_INVALID_VALUE);
6202 }
6203
6204 GLint clientVersion = egl::getClientVersion();
6205
6206 switch(type)
6207 {
6208 case GL_BYTE:
6209 case GL_UNSIGNED_BYTE:
6210 case GL_SHORT:
6211 case GL_UNSIGNED_SHORT:
6212 case GL_FIXED:
6213 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006214 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006215 break;
6216 case GL_INT_2_10_10_10_REV:
6217 case GL_UNSIGNED_INT_2_10_10_10_REV:
6218 if(clientVersion >= 3)
6219 {
6220 if(size != 4)
6221 {
6222 return error(GL_INVALID_OPERATION);
6223 }
6224 break;
6225 }
6226 else return error(GL_INVALID_ENUM);
6227 case GL_INT:
6228 case GL_UNSIGNED_INT:
6229 case GL_HALF_FLOAT:
6230 if(clientVersion >= 3)
6231 {
6232 break;
6233 }
6234 else return error(GL_INVALID_ENUM);
6235 default:
6236 return error(GL_INVALID_ENUM);
6237 }
6238
6239 if(stride < 0)
6240 {
6241 return error(GL_INVALID_VALUE);
6242 }
6243
6244 es2::Context *context = es2::getContext();
6245
6246 if(context)
6247 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006248 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6249 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6250 {
6251 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6252 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6253 return error(GL_INVALID_OPERATION);
6254 }
6255
Nicolas Capens0bac2852016-05-07 06:09:58 -04006256 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
6257 }
6258}
6259
6260void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6261{
6262 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6263
6264 if(width < 0 || height < 0)
6265 {
6266 return error(GL_INVALID_VALUE);
6267 }
6268
6269 es2::Context *context = es2::getContext();
6270
6271 if(context)
6272 {
6273 context->setViewportParams(x, y, width, height);
6274 }
6275}
6276
Alexis Hetub9dda642016-10-06 11:25:32 -04006277static 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 -04006278{
6279 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6280 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6281 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6282 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6283
6284 switch(filter)
6285 {
6286 case GL_NEAREST:
6287 break;
6288 default:
6289 return error(GL_INVALID_ENUM);
6290 }
6291
6292 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6293 {
6294 return error(GL_INVALID_VALUE);
6295 }
6296
6297 es2::Context *context = es2::getContext();
6298
6299 if(context)
6300 {
6301 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6302 {
6303 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6304 return error(GL_INVALID_OPERATION);
6305 }
6306
Alexis Hetub9dda642016-10-06 11:25:32 -04006307 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006308 }
6309}
6310
Alexis Hetub9dda642016-10-06 11:25:32 -04006311void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6312{
6313 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6314}
6315
Nicolas Capens0bac2852016-05-07 06:09:58 -04006316void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6317 GLbitfield mask, GLenum filter)
6318{
6319 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6320 {
6321 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6322 return error(GL_INVALID_OPERATION);
6323 }
6324
Alexis Hetub9dda642016-10-06 11:25:32 -04006325 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006326}
6327
6328void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006329 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006330{
6331 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6332 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006333 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6334 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006335
6336 switch(target)
6337 {
6338 case GL_TEXTURE_3D_OES:
6339 switch(format)
6340 {
6341 case GL_DEPTH_COMPONENT:
6342 case GL_DEPTH_STENCIL_OES:
6343 return error(GL_INVALID_OPERATION);
6344 default:
6345 break;
6346 }
6347 break;
6348 default:
6349 return error(GL_INVALID_ENUM);
6350 }
6351
6352 if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
6353 {
6354 return;
6355 }
6356
6357 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6358 {
6359 return error(GL_INVALID_VALUE);
6360 }
6361
6362 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6363 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6364 {
6365 return error(GL_INVALID_VALUE);
6366 }
6367
6368 if(border != 0)
6369 {
6370 return error(GL_INVALID_VALUE);
6371 }
6372
6373 es2::Context *context = es2::getContext();
6374
6375 if(context)
6376 {
6377 es2::Texture3D *texture = context->getTexture3D();
6378
6379 if(!texture)
6380 {
6381 return error(GL_INVALID_OPERATION);
6382 }
6383
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006384 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006385 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006386 if(validationError != GL_NONE)
6387 {
6388 return error(validationError);
6389 }
6390
6391 texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006392 }
6393}
6394
Alexis Hetu53f48092016-06-17 14:08:06 -04006395void 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 -04006396{
6397 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6398 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006399 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6400 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006401
6402 switch(target)
6403 {
6404 case GL_TEXTURE_3D_OES:
6405 break;
6406 default:
6407 return error(GL_INVALID_ENUM);
6408 }
6409
6410 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6411 {
6412 return;
6413 }
6414
6415 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6416 {
6417 return error(GL_INVALID_VALUE);
6418 }
6419
6420 if((width < 0) || (height < 0) || (depth < 0))
6421 {
6422 return error(GL_INVALID_VALUE);
6423 }
6424
6425 es2::Context *context = es2::getContext();
6426
6427 if(context)
6428 {
6429 es2::Texture3D *texture = context->getTexture3D();
6430
6431 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
6432
6433 GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006434
Nicolas Capens0bac2852016-05-07 06:09:58 -04006435 if(validationError == GL_NONE)
6436 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006437 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006438 }
6439
6440 if(validationError == GL_NONE)
6441 {
6442 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006443 }
6444 else
6445 {
6446 return error(validationError);
6447 }
6448 }
6449}
6450
6451void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6452{
6453 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6454 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6455 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6456
6457 switch(target)
6458 {
6459 case GL_TEXTURE_3D_OES:
6460 break;
6461 default:
6462 return error(GL_INVALID_ENUM);
6463 }
6464
6465 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6466 {
6467 return error(GL_INVALID_VALUE);
6468 }
6469
6470 es2::Context *context = es2::getContext();
6471
6472 if(context)
6473 {
6474 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6475
6476 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6477 {
6478 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6479 }
6480
6481 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6482
6483 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6484 {
6485 return error(GL_INVALID_OPERATION);
6486 }
6487
6488 es2::Texture3D *texture = context->getTexture3D();
6489
6490 GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
6491
6492 if(validationError != GL_NONE)
6493 {
6494 return error(validationError);
6495 }
6496
6497 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6498 }
6499}
6500
6501void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6502{
6503 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6504 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6505 target, level, internalformat, width, height, depth, border, imageSize, data);
6506
6507 switch(target)
6508 {
6509 case GL_TEXTURE_3D_OES:
6510 break;
6511 default:
6512 return error(GL_INVALID_ENUM);
6513 }
6514
6515 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6516 {
6517 return error(GL_INVALID_VALUE);
6518 }
6519
6520 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6521 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6522 {
6523 return error(GL_INVALID_VALUE);
6524 }
6525
6526 switch(internalformat)
6527 {
6528 case GL_DEPTH_COMPONENT:
6529 case GL_DEPTH_COMPONENT16:
6530 case GL_DEPTH_COMPONENT32_OES:
6531 case GL_DEPTH_STENCIL_OES:
6532 case GL_DEPTH24_STENCIL8_OES:
6533 return error(GL_INVALID_OPERATION);
6534 default:
6535 {
6536 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
6537 if(validationError != GL_NONE)
6538 {
6539 return error(validationError);
6540 }
6541 }
6542 }
6543
6544 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6545 {
6546 return error(GL_INVALID_VALUE);
6547 }
6548
6549 es2::Context *context = es2::getContext();
6550
6551 if(context)
6552 {
6553 es2::Texture3D *texture = context->getTexture3D();
6554
6555 if(!texture)
6556 {
6557 return error(GL_INVALID_OPERATION);
6558 }
6559
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006560 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006561
6562 if(validationError != GL_NONE)
6563 {
6564 return error(validationError);
6565 }
6566
Nicolas Capens0bac2852016-05-07 06:09:58 -04006567 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6568 }
6569}
6570
6571void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6572{
6573 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6574 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6575 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6576 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6577
6578 switch(target)
6579 {
6580 case GL_TEXTURE_3D_OES:
6581 break;
6582 default:
6583 return error(GL_INVALID_ENUM);
6584 }
6585
6586 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6587 {
6588 return error(GL_INVALID_VALUE);
6589 }
6590
6591 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6592 {
6593 return error(GL_INVALID_VALUE);
6594 }
6595
6596 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
6597 if(validationError != GL_NONE)
6598 {
6599 return error(validationError);
6600 }
6601
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006602 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006603 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006604 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006605 }
6606
6607 es2::Context *context = es2::getContext();
6608
6609 if(context)
6610 {
6611 es2::Texture3D *texture = context->getTexture3D();
6612
6613 if(!texture)
6614 {
6615 return error(GL_INVALID_OPERATION);
6616 }
6617
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006618 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006619
6620 if(validationError != GL_NONE)
6621 {
6622 return error(validationError);
6623 }
6624
6625 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006626 }
6627}
6628
6629void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6630{
6631 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6632 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6633
6634 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
6635 {
6636 return error(GL_INVALID_ENUM);
6637 }
6638
6639 es2::Context *context = es2::getContext();
6640
6641 if(context)
6642 {
6643 if(texture == 0)
6644 {
6645 textarget = GL_NONE;
6646 }
6647 else
6648 {
6649 es2::Texture *tex = context->getTexture(texture);
6650
6651 if(!tex)
6652 {
6653 return error(GL_INVALID_OPERATION);
6654 }
6655
6656 if(tex->isCompressed(textarget, level))
6657 {
6658 return error(GL_INVALID_OPERATION);
6659 }
6660
6661 switch(textarget)
6662 {
6663 case GL_TEXTURE_3D_OES:
6664 if(tex->getTarget() != GL_TEXTURE_3D_OES)
6665 {
6666 return error(GL_INVALID_OPERATION);
6667 }
6668 break;
6669 default:
6670 return error(GL_INVALID_ENUM);
6671 }
6672
6673 if(level != 0)
6674 {
6675 return error(GL_INVALID_VALUE);
6676 }
6677 }
6678
6679 es2::Framebuffer *framebuffer = nullptr;
6680 GLuint framebufferName = 0;
6681 if(target == GL_READ_FRAMEBUFFER_ANGLE)
6682 {
6683 framebuffer = context->getReadFramebuffer();
6684 framebufferName = context->getReadFramebufferName();
6685 }
6686 else
6687 {
6688 framebuffer = context->getDrawFramebuffer();
6689 framebufferName = context->getDrawFramebufferName();
6690 }
6691
6692 if(framebufferName == 0 || !framebuffer)
6693 {
6694 return error(GL_INVALID_OPERATION);
6695 }
6696
6697 GLint clientVersion = context->getClientVersion();
6698
6699 switch(attachment)
6700 {
6701 case GL_COLOR_ATTACHMENT1:
6702 case GL_COLOR_ATTACHMENT2:
6703 case GL_COLOR_ATTACHMENT3:
6704 case GL_COLOR_ATTACHMENT4:
6705 case GL_COLOR_ATTACHMENT5:
6706 case GL_COLOR_ATTACHMENT6:
6707 case GL_COLOR_ATTACHMENT7:
6708 case GL_COLOR_ATTACHMENT8:
6709 case GL_COLOR_ATTACHMENT9:
6710 case GL_COLOR_ATTACHMENT10:
6711 case GL_COLOR_ATTACHMENT11:
6712 case GL_COLOR_ATTACHMENT12:
6713 case GL_COLOR_ATTACHMENT13:
6714 case GL_COLOR_ATTACHMENT14:
6715 case GL_COLOR_ATTACHMENT15:
6716 case GL_COLOR_ATTACHMENT16:
6717 case GL_COLOR_ATTACHMENT17:
6718 case GL_COLOR_ATTACHMENT18:
6719 case GL_COLOR_ATTACHMENT19:
6720 case GL_COLOR_ATTACHMENT20:
6721 case GL_COLOR_ATTACHMENT21:
6722 case GL_COLOR_ATTACHMENT22:
6723 case GL_COLOR_ATTACHMENT23:
6724 case GL_COLOR_ATTACHMENT24:
6725 case GL_COLOR_ATTACHMENT25:
6726 case GL_COLOR_ATTACHMENT26:
6727 case GL_COLOR_ATTACHMENT27:
6728 case GL_COLOR_ATTACHMENT28:
6729 case GL_COLOR_ATTACHMENT29:
6730 case GL_COLOR_ATTACHMENT30:
6731 case GL_COLOR_ATTACHMENT31:
6732 if(clientVersion < 3)
6733 {
6734 return error(GL_INVALID_ENUM);
6735 }
6736 // fall through
6737 case GL_COLOR_ATTACHMENT0:
6738 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6739 {
6740 return error(GL_INVALID_ENUM);
6741 }
6742 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6743 break;
6744 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6745 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6746 default:
6747 return error(GL_INVALID_ENUM);
6748 }
6749 }
6750}
6751
6752void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6753{
6754 if(egl::getClientVersion() == 1)
6755 {
6756 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6757 }
6758
6759 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6760
6761 switch(target)
6762 {
6763 case GL_TEXTURE_2D:
6764 case GL_TEXTURE_EXTERNAL_OES:
6765 break;
6766 default:
6767 return error(GL_INVALID_ENUM);
6768 }
6769
Nicolas Capens0bac2852016-05-07 06:09:58 -04006770 es2::Context *context = es2::getContext();
6771
6772 if(context)
6773 {
Nicolas Capens58df2f62016-06-07 14:48:56 -04006774 es2::Texture2D *texture = nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006775
6776 switch(target)
6777 {
6778 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
6779 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
6780 default: UNREACHABLE(target);
6781 }
6782
6783 if(!texture)
6784 {
6785 return error(GL_INVALID_OPERATION);
6786 }
6787
Nicolas Capens58df2f62016-06-07 14:48:56 -04006788 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006789
Nicolas Capens58df2f62016-06-07 14:48:56 -04006790 if(!eglImage)
6791 {
6792 return error(GL_INVALID_OPERATION);
6793 }
6794
6795 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006796 }
6797}
6798
6799void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6800{
6801 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6802
6803 UNIMPLEMENTED();
6804}
6805
6806GLboolean IsRenderbufferOES(GLuint renderbuffer)
6807{
6808 return IsRenderbuffer(renderbuffer);
6809}
6810
6811void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6812{
6813 BindRenderbuffer(target, renderbuffer);
6814}
6815
6816void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6817{
6818 DeleteRenderbuffers(n, renderbuffers);
6819}
6820
6821void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6822{
6823 GenRenderbuffers(n, renderbuffers);
6824}
6825
6826void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6827{
6828 RenderbufferStorage(target, internalformat, width, height);
6829}
6830
6831void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6832{
6833 GetRenderbufferParameteriv(target, pname, params);
6834}
6835
6836GLboolean IsFramebufferOES(GLuint framebuffer)
6837{
6838 return IsFramebuffer(framebuffer);
6839}
6840
6841void BindFramebufferOES(GLenum target, GLuint framebuffer)
6842{
6843 BindFramebuffer(target, framebuffer);
6844}
6845
6846void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6847{
6848 DeleteFramebuffers(n, framebuffers);
6849}
6850
6851void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6852{
6853 GenFramebuffers(n, framebuffers);
6854}
6855
6856GLenum CheckFramebufferStatusOES(GLenum target)
6857{
6858 return CheckFramebufferStatus(target);
6859}
6860
6861void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6862{
6863 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6864}
6865
6866void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6867{
6868 FramebufferTexture2D(target, attachment, textarget, texture, level);
6869}
6870
6871void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6872{
6873 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6874}
6875
6876void GenerateMipmapOES(GLenum target)
6877{
6878 GenerateMipmap(target);
6879}
6880
6881void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6882{
6883 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6884
6885 if(n < 0 || n > MAX_DRAW_BUFFERS)
6886 {
6887 return error(GL_INVALID_VALUE);
6888 }
6889
6890 es2::Context *context = es2::getContext();
6891
6892 if(context)
6893 {
6894 GLuint drawFramebufferName = context->getDrawFramebufferName();
6895
6896 if((drawFramebufferName == 0) && (n != 1))
6897 {
6898 return error(GL_INVALID_OPERATION);
6899 }
6900
6901 for(unsigned int i = 0; i < (unsigned)n; i++)
6902 {
6903 switch(bufs[i])
6904 {
6905 case GL_BACK:
6906 if(drawFramebufferName != 0)
6907 {
6908 return error(GL_INVALID_OPERATION);
6909 }
6910 break;
6911 case GL_NONE:
6912 break;
6913 case GL_COLOR_ATTACHMENT0_EXT:
6914 case GL_COLOR_ATTACHMENT1_EXT:
6915 case GL_COLOR_ATTACHMENT2_EXT:
6916 case GL_COLOR_ATTACHMENT3_EXT:
6917 case GL_COLOR_ATTACHMENT4_EXT:
6918 case GL_COLOR_ATTACHMENT5_EXT:
6919 case GL_COLOR_ATTACHMENT6_EXT:
6920 case GL_COLOR_ATTACHMENT7_EXT:
6921 case GL_COLOR_ATTACHMENT8_EXT:
6922 case GL_COLOR_ATTACHMENT9_EXT:
6923 case GL_COLOR_ATTACHMENT10_EXT:
6924 case GL_COLOR_ATTACHMENT11_EXT:
6925 case GL_COLOR_ATTACHMENT12_EXT:
6926 case GL_COLOR_ATTACHMENT13_EXT:
6927 case GL_COLOR_ATTACHMENT14_EXT:
6928 case GL_COLOR_ATTACHMENT15_EXT:
6929 {
6930 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6931
6932 if(index >= MAX_COLOR_ATTACHMENTS)
6933 {
6934 return error(GL_INVALID_OPERATION);
6935 }
6936
6937 if(index != i)
6938 {
6939 return error(GL_INVALID_OPERATION);
6940 }
6941
6942 if(drawFramebufferName == 0)
6943 {
6944 return error(GL_INVALID_OPERATION);
6945 }
6946 }
6947 break;
6948 default:
6949 return error(GL_INVALID_ENUM);
6950 }
6951 }
6952
6953 context->setFramebufferDrawBuffers(n, bufs);
6954 }
6955}
6956
6957}
6958
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006959extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006960{
6961 struct Extension
6962 {
6963 const char *name;
6964 __eglMustCastToProperFunctionPointerType address;
6965 };
6966
6967 static const Extension glExtensions[] =
6968 {
6969 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6970
6971 EXTENSION(glTexImage3DOES),
6972 EXTENSION(glBlitFramebufferANGLE),
6973 EXTENSION(glBlitFramebufferNV),
6974 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6975 EXTENSION(glDeleteFencesNV),
6976 EXTENSION(glGenFencesNV),
6977 EXTENSION(glIsFenceNV),
6978 EXTENSION(glTestFenceNV),
6979 EXTENSION(glGetFenceivNV),
6980 EXTENSION(glFinishFenceNV),
6981 EXTENSION(glSetFenceNV),
6982 EXTENSION(glGetGraphicsResetStatusEXT),
6983 EXTENSION(glReadnPixelsEXT),
6984 EXTENSION(glGetnUniformfvEXT),
6985 EXTENSION(glGetnUniformivEXT),
6986 EXTENSION(glGenQueriesEXT),
6987 EXTENSION(glDeleteQueriesEXT),
6988 EXTENSION(glIsQueryEXT),
6989 EXTENSION(glBeginQueryEXT),
6990 EXTENSION(glEndQueryEXT),
6991 EXTENSION(glGetQueryivEXT),
6992 EXTENSION(glGetQueryObjectuivEXT),
6993 EXTENSION(glEGLImageTargetTexture2DOES),
6994 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
6995 EXTENSION(glDrawElementsInstancedEXT),
6996 EXTENSION(glDrawArraysInstancedEXT),
6997 EXTENSION(glVertexAttribDivisorEXT),
6998 EXTENSION(glDrawArraysInstancedANGLE),
6999 EXTENSION(glDrawElementsInstancedANGLE),
7000 EXTENSION(glVertexAttribDivisorANGLE),
7001 EXTENSION(glIsRenderbufferOES),
7002 EXTENSION(glBindRenderbufferOES),
7003 EXTENSION(glDeleteRenderbuffersOES),
7004 EXTENSION(glGenRenderbuffersOES),
7005 EXTENSION(glRenderbufferStorageOES),
7006 EXTENSION(glGetRenderbufferParameterivOES),
7007 EXTENSION(glIsFramebufferOES),
7008 EXTENSION(glBindFramebufferOES),
7009 EXTENSION(glDeleteFramebuffersOES),
7010 EXTENSION(glGenFramebuffersOES),
7011 EXTENSION(glCheckFramebufferStatusOES),
7012 EXTENSION(glFramebufferRenderbufferOES),
7013 EXTENSION(glFramebufferTexture2DOES),
7014 EXTENSION(glGetFramebufferAttachmentParameterivOES),
7015 EXTENSION(glGenerateMipmapOES),
7016 EXTENSION(glDrawBuffersEXT),
7017
7018 #undef EXTENSION
7019 };
7020
7021 for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
7022 {
7023 if(strcmp(procname, glExtensions[ext].name) == 0)
7024 {
7025 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
7026 }
7027 }
7028
7029 return nullptr;
7030}