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