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