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