blob: c560600dce08de48b9a3cdc0ae345f5362b0ab70 [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
4535 programObject->link();
4536 }
4537}
4538
4539void PixelStorei(GLenum pname, GLint param)
4540{
4541 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4542
4543 es2::Context *context = es2::getContext();
4544
4545 if(context)
4546 {
4547 GLint clientVersion = context->getClientVersion();
4548
4549 switch(pname)
4550 {
4551 case GL_UNPACK_ALIGNMENT:
4552 if(param != 1 && param != 2 && param != 4 && param != 8)
4553 {
4554 return error(GL_INVALID_VALUE);
4555 }
4556 context->setUnpackAlignment(param);
4557 break;
4558 case GL_PACK_ALIGNMENT:
4559 if(param != 1 && param != 2 && param != 4 && param != 8)
4560 {
4561 return error(GL_INVALID_VALUE);
4562 }
4563 context->setPackAlignment(param);
4564 break;
4565 case GL_PACK_ROW_LENGTH:
4566 if(clientVersion >= 3)
4567 {
4568 if(param < 0)
4569 {
4570 return error(GL_INVALID_VALUE);
4571 }
4572 context->setPackRowLength(param);
4573 break;
4574 }
4575 else return error(GL_INVALID_ENUM);
4576 case GL_PACK_SKIP_PIXELS:
4577 if(clientVersion >= 3)
4578 {
4579 if(param < 0)
4580 {
4581 return error(GL_INVALID_VALUE);
4582 }
4583 context->setPackSkipPixels(param);
4584 break;
4585 }
4586 else return error(GL_INVALID_ENUM);
4587 case GL_PACK_SKIP_ROWS:
4588 if(clientVersion >= 3)
4589 {
4590 if(param < 0)
4591 {
4592 return error(GL_INVALID_VALUE);
4593 }
4594 context->setPackSkipRows(param);
4595 break;
4596 }
4597 else return error(GL_INVALID_ENUM);
4598 case GL_UNPACK_ROW_LENGTH:
4599 if(clientVersion >= 3)
4600 {
4601 if(param < 0)
4602 {
4603 return error(GL_INVALID_VALUE);
4604 }
4605 context->setUnpackRowLength(param);
4606 break;
4607 }
4608 else return error(GL_INVALID_ENUM);
4609 case GL_UNPACK_IMAGE_HEIGHT:
4610 if(clientVersion >= 3)
4611 {
4612 if(param < 0)
4613 {
4614 return error(GL_INVALID_VALUE);
4615 }
4616 context->setUnpackImageHeight(param);
4617 break;
4618 }
4619 else return error(GL_INVALID_ENUM);
4620 case GL_UNPACK_SKIP_PIXELS:
4621 if(clientVersion >= 3)
4622 {
4623 if(param < 0)
4624 {
4625 return error(GL_INVALID_VALUE);
4626 }
4627 context->setUnpackSkipPixels(param);
4628 break;
4629 }
4630 else return error(GL_INVALID_ENUM);
4631 case GL_UNPACK_SKIP_ROWS:
4632 if(clientVersion >= 3)
4633 {
4634 if(param < 0)
4635 {
4636 return error(GL_INVALID_VALUE);
4637 }
4638 context->setUnpackSkipRows(param);
4639 break;
4640 }
4641 else return error(GL_INVALID_ENUM);
4642 case GL_UNPACK_SKIP_IMAGES:
4643 if(clientVersion >= 3) {
4644 if(param < 0)
4645 {
4646 return error(GL_INVALID_VALUE);
4647 }
4648 context->setUnpackSkipImages(param);
4649 break;
4650 }
4651 else return error(GL_INVALID_ENUM);
4652 default:
4653 return error(GL_INVALID_ENUM);
4654 }
4655 }
4656}
4657
4658void PolygonOffset(GLfloat factor, GLfloat units)
4659{
4660 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4661
4662 es2::Context *context = es2::getContext();
4663
4664 if(context)
4665 {
4666 context->setPolygonOffsetParams(factor, units);
4667 }
4668}
4669
4670void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4671 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4672{
4673 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4674 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4675 x, y, width, height, format, type, bufSize, data);
4676
4677 if(width < 0 || height < 0 || bufSize < 0)
4678 {
4679 return error(GL_INVALID_VALUE);
4680 }
4681
4682 es2::Context *context = es2::getContext();
4683
4684 if(context)
4685 {
4686 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4687 }
4688}
4689
4690void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4691{
4692 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4693 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4694 x, y, width, height, format, type, pixels);
4695
4696 if(width < 0 || height < 0)
4697 {
4698 return error(GL_INVALID_VALUE);
4699 }
4700
4701 es2::Context *context = es2::getContext();
4702
4703 if(context)
4704 {
4705 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4706 }
4707}
4708
4709void ReleaseShaderCompiler(void)
4710{
4711 TRACE("()");
4712
4713 es2::Shader::releaseCompiler();
4714}
4715
Nicolas Capens400667e2017-03-29 14:40:14 -04004716void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004717{
4718 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4719 target, samples, internalformat, width, height);
4720
4721 switch(target)
4722 {
4723 case GL_RENDERBUFFER:
4724 break;
4725 default:
4726 return error(GL_INVALID_ENUM);
4727 }
4728
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004729 if(width < 0 || height < 0 || samples < 0 ||
4730 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4731 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004732 {
4733 return error(GL_INVALID_VALUE);
4734 }
4735
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004736 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
4737 (sw::Surface::isNonNormalizedInteger(es2sw::ConvertRenderbufferFormat(internalformat)) && samples > 0))
4738 {
4739 return error(GL_INVALID_OPERATION);
4740 }
4741
Nicolas Capens0bac2852016-05-07 06:09:58 -04004742 es2::Context *context = es2::getContext();
4743
4744 if(context)
4745 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004746 GLuint handle = context->getRenderbufferName();
4747 if(handle == 0)
4748 {
4749 return error(GL_INVALID_OPERATION);
4750 }
4751
4752 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004753
4754 if(IsColorRenderable(internalformat, clientVersion, false))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004755 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004756 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004757 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004758 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4759 {
4760 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4761 }
4762 else if(IsDepthRenderable(internalformat, clientVersion))
4763 {
4764 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4765 }
4766 else if(IsStencilRenderable(internalformat, clientVersion))
4767 {
4768 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4769 }
4770 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004771 }
4772}
4773
Nicolas Capens400667e2017-03-29 14:40:14 -04004774void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4775{
4776 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4777}
4778
Nicolas Capens0bac2852016-05-07 06:09:58 -04004779void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4780{
Nicolas Capens400667e2017-03-29 14:40:14 -04004781 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004782}
4783
4784void SampleCoverage(GLclampf value, GLboolean invert)
4785{
4786 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4787
4788 es2::Context* context = es2::getContext();
4789
4790 if(context)
4791 {
4792 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4793 }
4794}
4795
4796void SetFenceNV(GLuint fence, GLenum condition)
4797{
4798 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4799
4800 if(condition != GL_ALL_COMPLETED_NV)
4801 {
4802 return error(GL_INVALID_ENUM);
4803 }
4804
4805 es2::Context *context = es2::getContext();
4806
4807 if(context)
4808 {
4809 es2::Fence *fenceObject = context->getFence(fence);
4810
4811 if(!fenceObject)
4812 {
4813 return error(GL_INVALID_OPERATION);
4814 }
4815
4816 fenceObject->setFence(condition);
4817 }
4818}
4819
4820void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4821{
4822 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4823
4824 if(width < 0 || height < 0)
4825 {
4826 return error(GL_INVALID_VALUE);
4827 }
4828
4829 es2::Context* context = es2::getContext();
4830
4831 if(context)
4832 {
4833 context->setScissorParams(x, y, width, height);
4834 }
4835}
4836
4837void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4838{
4839 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4840 "const GLvoid* binary = %p, GLsizei length = %d)",
4841 n, shaders, binaryformat, binary, length);
4842
4843 // No binary shader formats are supported.
4844 return error(GL_INVALID_ENUM);
4845}
4846
4847void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4848{
4849 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4850 shader, count, string, length);
4851
4852 if(count < 0)
4853 {
4854 return error(GL_INVALID_VALUE);
4855 }
4856
4857 es2::Context *context = es2::getContext();
4858
4859 if(context)
4860 {
4861 es2::Shader *shaderObject = context->getShader(shader);
4862
4863 if(!shaderObject)
4864 {
4865 if(context->getProgram(shader))
4866 {
4867 return error(GL_INVALID_OPERATION);
4868 }
4869 else
4870 {
4871 return error(GL_INVALID_VALUE);
4872 }
4873 }
4874
4875 shaderObject->setSource(count, string, length);
4876 }
4877}
4878
4879void StencilFunc(GLenum func, GLint ref, GLuint mask)
4880{
4881 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4882}
4883
4884void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4885{
4886 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4887
4888 switch(face)
4889 {
4890 case GL_FRONT:
4891 case GL_BACK:
4892 case GL_FRONT_AND_BACK:
4893 break;
4894 default:
4895 return error(GL_INVALID_ENUM);
4896 }
4897
4898 switch(func)
4899 {
4900 case GL_NEVER:
4901 case GL_ALWAYS:
4902 case GL_LESS:
4903 case GL_LEQUAL:
4904 case GL_EQUAL:
4905 case GL_GEQUAL:
4906 case GL_GREATER:
4907 case GL_NOTEQUAL:
4908 break;
4909 default:
4910 return error(GL_INVALID_ENUM);
4911 }
4912
4913 es2::Context *context = es2::getContext();
4914
4915 if(context)
4916 {
4917 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4918 {
4919 context->setStencilParams(func, ref, mask);
4920 }
4921
4922 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4923 {
4924 context->setStencilBackParams(func, ref, mask);
4925 }
4926 }
4927}
4928
4929void StencilMask(GLuint mask)
4930{
4931 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4932}
4933
4934void StencilMaskSeparate(GLenum face, GLuint mask)
4935{
4936 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4937
4938 switch(face)
4939 {
4940 case GL_FRONT:
4941 case GL_BACK:
4942 case GL_FRONT_AND_BACK:
4943 break;
4944 default:
4945 return error(GL_INVALID_ENUM);
4946 }
4947
4948 es2::Context *context = es2::getContext();
4949
4950 if(context)
4951 {
4952 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4953 {
4954 context->setStencilWritemask(mask);
4955 }
4956
4957 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4958 {
4959 context->setStencilBackWritemask(mask);
4960 }
4961 }
4962}
4963
4964void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4965{
4966 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4967}
4968
4969void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4970{
4971 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4972 face, fail, zfail, zpass);
4973
4974 switch(face)
4975 {
4976 case GL_FRONT:
4977 case GL_BACK:
4978 case GL_FRONT_AND_BACK:
4979 break;
4980 default:
4981 return error(GL_INVALID_ENUM);
4982 }
4983
4984 switch(fail)
4985 {
4986 case GL_ZERO:
4987 case GL_KEEP:
4988 case GL_REPLACE:
4989 case GL_INCR:
4990 case GL_DECR:
4991 case GL_INVERT:
4992 case GL_INCR_WRAP:
4993 case GL_DECR_WRAP:
4994 break;
4995 default:
4996 return error(GL_INVALID_ENUM);
4997 }
4998
4999 switch(zfail)
5000 {
5001 case GL_ZERO:
5002 case GL_KEEP:
5003 case GL_REPLACE:
5004 case GL_INCR:
5005 case GL_DECR:
5006 case GL_INVERT:
5007 case GL_INCR_WRAP:
5008 case GL_DECR_WRAP:
5009 break;
5010 default:
5011 return error(GL_INVALID_ENUM);
5012 }
5013
5014 switch(zpass)
5015 {
5016 case GL_ZERO:
5017 case GL_KEEP:
5018 case GL_REPLACE:
5019 case GL_INCR:
5020 case GL_DECR:
5021 case GL_INVERT:
5022 case GL_INCR_WRAP:
5023 case GL_DECR_WRAP:
5024 break;
5025 default:
5026 return error(GL_INVALID_ENUM);
5027 }
5028
5029 es2::Context *context = es2::getContext();
5030
5031 if(context)
5032 {
5033 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
5034 {
5035 context->setStencilOperations(fail, zfail, zpass);
5036 }
5037
5038 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
5039 {
5040 context->setStencilBackOperations(fail, zfail, zpass);
5041 }
5042 }
5043}
5044
5045GLboolean TestFenceNV(GLuint fence)
5046{
5047 TRACE("(GLuint fence = %d)", fence);
5048
5049 es2::Context *context = es2::getContext();
5050
5051 if(context)
5052 {
5053 es2::Fence *fenceObject = context->getFence(fence);
5054
5055 if(!fenceObject)
5056 {
5057 return error(GL_INVALID_OPERATION, GL_TRUE);
5058 }
5059
5060 return fenceObject->testFence();
5061 }
5062
5063 return GL_TRUE;
5064}
5065
5066void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005067 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005068{
5069 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005070 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
5071 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005072
5073 if(!validImageSize(level, width, height))
5074 {
5075 return error(GL_INVALID_VALUE);
5076 }
5077
5078 es2::Context *context = es2::getContext();
5079
5080 if(context)
5081 {
5082 GLint clientVersion = context->getClientVersion();
5083 if(clientVersion < 3)
5084 {
5085 if(internalformat != (GLint)format)
5086 {
5087 return error(GL_INVALID_OPERATION);
5088 }
5089 }
5090
5091 GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
5092 if(validationError != GL_NONE)
5093 {
5094 return error(validationError);
5095 }
5096
5097 if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
5098 {
5099 return;
5100 }
5101
5102 if(border != 0)
5103 {
5104 return error(GL_INVALID_VALUE);
5105 }
5106
5107 switch(target)
5108 {
5109 case GL_TEXTURE_2D:
5110 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5111 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5112 {
5113 return error(GL_INVALID_VALUE);
5114 }
5115 break;
5116 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5117 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5118 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5119 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5120 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5121 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5122 if(width != height)
5123 {
5124 return error(GL_INVALID_VALUE);
5125 }
5126
5127 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5128 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5129 {
5130 return error(GL_INVALID_VALUE);
5131 }
5132 break;
5133 default:
5134 return error(GL_INVALID_ENUM);
5135 }
5136
5137 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
5138
Alexis Hetu848aa7f2017-11-17 13:15:32 -05005139 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005140 if(validationError != GL_NONE)
5141 {
5142 return error(validationError);
5143 }
5144
Nicolas Capens0bac2852016-05-07 06:09:58 -04005145 if(target == GL_TEXTURE_2D)
5146 {
5147 es2::Texture2D *texture = context->getTexture2D();
5148
5149 if(!texture)
5150 {
5151 return error(GL_INVALID_OPERATION);
5152 }
5153
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005154 texture->setImage(context, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005155 }
5156 else
5157 {
5158 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5159
5160 if(!texture)
5161 {
5162 return error(GL_INVALID_OPERATION);
5163 }
5164
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005165 texture->setImage(context, target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005166 }
5167 }
5168}
5169
5170void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5171{
5172 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5173
5174 es2::Context *context = es2::getContext();
5175
5176 if(context)
5177 {
5178 es2::Texture *texture;
5179
5180 GLint clientVersion = context->getClientVersion();
5181
5182 switch(target)
5183 {
5184 case GL_TEXTURE_2D:
5185 texture = context->getTexture2D();
5186 break;
5187 case GL_TEXTURE_2D_ARRAY:
5188 if(clientVersion < 3)
5189 {
5190 return error(GL_INVALID_ENUM);
5191 }
5192 else
5193 {
5194 texture = context->getTexture2DArray();
5195 }
5196 break;
5197 case GL_TEXTURE_3D_OES:
5198 texture = context->getTexture3D();
5199 break;
5200 case GL_TEXTURE_CUBE_MAP:
5201 texture = context->getTextureCubeMap();
5202 break;
5203 case GL_TEXTURE_EXTERNAL_OES:
5204 texture = context->getTextureExternal();
5205 break;
5206 default:
5207 return error(GL_INVALID_ENUM);
5208 }
5209
5210 switch(pname)
5211 {
5212 case GL_TEXTURE_WRAP_S:
5213 if(!texture->setWrapS((GLenum)param))
5214 {
5215 return error(GL_INVALID_ENUM);
5216 }
5217 break;
5218 case GL_TEXTURE_WRAP_T:
5219 if(!texture->setWrapT((GLenum)param))
5220 {
5221 return error(GL_INVALID_ENUM);
5222 }
5223 break;
5224 case GL_TEXTURE_WRAP_R_OES:
5225 if(!texture->setWrapR((GLenum)param))
5226 {
5227 return error(GL_INVALID_ENUM);
5228 }
5229 break;
5230 case GL_TEXTURE_MIN_FILTER:
5231 if(!texture->setMinFilter((GLenum)param))
5232 {
5233 return error(GL_INVALID_ENUM);
5234 }
5235 break;
5236 case GL_TEXTURE_MAG_FILTER:
5237 if(!texture->setMagFilter((GLenum)param))
5238 {
5239 return error(GL_INVALID_ENUM);
5240 }
5241 break;
5242 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5243 if(!texture->setMaxAnisotropy(param))
5244 {
5245 return error(GL_INVALID_VALUE);
5246 }
5247 break;
5248 case GL_TEXTURE_BASE_LEVEL:
5249 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5250 {
5251 return error(GL_INVALID_VALUE);
5252 }
5253 break;
5254 case GL_TEXTURE_COMPARE_FUNC:
5255 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5256 {
5257 return error(GL_INVALID_VALUE);
5258 }
5259 break;
5260 case GL_TEXTURE_COMPARE_MODE:
5261 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5262 {
5263 return error(GL_INVALID_VALUE);
5264 }
5265 break;
5266 case GL_TEXTURE_MAX_LEVEL:
5267 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5268 {
5269 return error(GL_INVALID_VALUE);
5270 }
5271 break;
5272 case GL_TEXTURE_MAX_LOD:
5273 if(clientVersion < 3 || !texture->setMaxLOD(param))
5274 {
5275 return error(GL_INVALID_VALUE);
5276 }
5277 break;
5278 case GL_TEXTURE_MIN_LOD:
5279 if(clientVersion < 3 || !texture->setMinLOD(param))
5280 {
5281 return error(GL_INVALID_VALUE);
5282 }
5283 break;
5284 case GL_TEXTURE_SWIZZLE_R:
5285 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5286 {
5287 return error(GL_INVALID_VALUE);
5288 }
5289 break;
5290 case GL_TEXTURE_SWIZZLE_G:
5291 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5292 {
5293 return error(GL_INVALID_VALUE);
5294 }
5295 break;
5296 case GL_TEXTURE_SWIZZLE_B:
5297 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5298 {
5299 return error(GL_INVALID_VALUE);
5300 }
5301 break;
5302 case GL_TEXTURE_SWIZZLE_A:
5303 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5304 {
5305 return error(GL_INVALID_VALUE);
5306 }
5307 break;
5308 default:
5309 return error(GL_INVALID_ENUM);
5310 }
5311 }
5312}
5313
5314void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5315{
5316 glTexParameterf(target, pname, *params);
5317}
5318
5319void TexParameteri(GLenum target, GLenum pname, GLint param)
5320{
5321 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5322
5323 es2::Context *context = es2::getContext();
5324
5325 if(context)
5326 {
5327 es2::Texture *texture;
5328
5329 GLint clientVersion = context->getClientVersion();
5330
5331 switch(target)
5332 {
5333 case GL_TEXTURE_2D:
5334 texture = context->getTexture2D();
5335 break;
5336 case GL_TEXTURE_2D_ARRAY:
5337 if(clientVersion < 3)
5338 {
5339 return error(GL_INVALID_ENUM);
5340 }
5341 else
5342 {
5343 texture = context->getTexture2DArray();
5344 }
5345 break;
5346 case GL_TEXTURE_3D_OES:
5347 texture = context->getTexture3D();
5348 break;
5349 case GL_TEXTURE_CUBE_MAP:
5350 texture = context->getTextureCubeMap();
5351 break;
5352 case GL_TEXTURE_EXTERNAL_OES:
5353 texture = context->getTextureExternal();
5354 break;
5355 default:
5356 return error(GL_INVALID_ENUM);
5357 }
5358
5359 switch(pname)
5360 {
5361 case GL_TEXTURE_WRAP_S:
5362 if(!texture->setWrapS((GLenum)param))
5363 {
5364 return error(GL_INVALID_ENUM);
5365 }
5366 break;
5367 case GL_TEXTURE_WRAP_T:
5368 if(!texture->setWrapT((GLenum)param))
5369 {
5370 return error(GL_INVALID_ENUM);
5371 }
5372 break;
5373 case GL_TEXTURE_WRAP_R_OES:
5374 if(!texture->setWrapR((GLenum)param))
5375 {
5376 return error(GL_INVALID_ENUM);
5377 }
5378 break;
5379 case GL_TEXTURE_MIN_FILTER:
5380 if(!texture->setMinFilter((GLenum)param))
5381 {
5382 return error(GL_INVALID_ENUM);
5383 }
5384 break;
5385 case GL_TEXTURE_MAG_FILTER:
5386 if(!texture->setMagFilter((GLenum)param))
5387 {
5388 return error(GL_INVALID_ENUM);
5389 }
5390 break;
5391 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5392 if(!texture->setMaxAnisotropy((GLfloat)param))
5393 {
5394 return error(GL_INVALID_VALUE);
5395 }
5396 break;
5397 case GL_TEXTURE_BASE_LEVEL:
5398 if(clientVersion < 3 || !texture->setBaseLevel(param))
5399 {
5400 return error(GL_INVALID_VALUE);
5401 }
5402 break;
5403 case GL_TEXTURE_COMPARE_FUNC:
5404 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5405 {
5406 return error(GL_INVALID_VALUE);
5407 }
5408 break;
5409 case GL_TEXTURE_COMPARE_MODE:
5410 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5411 {
5412 return error(GL_INVALID_VALUE);
5413 }
5414 break;
5415 case GL_TEXTURE_MAX_LEVEL:
5416 if(clientVersion < 3 || !texture->setMaxLevel(param))
5417 {
5418 return error(GL_INVALID_VALUE);
5419 }
5420 break;
5421 case GL_TEXTURE_MAX_LOD:
5422 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5423 {
5424 return error(GL_INVALID_VALUE);
5425 }
5426 break;
5427 case GL_TEXTURE_MIN_LOD:
5428 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5429 {
5430 return error(GL_INVALID_VALUE);
5431 }
5432 break;
5433 case GL_TEXTURE_SWIZZLE_R:
5434 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5435 {
5436 return error(GL_INVALID_VALUE);
5437 }
5438 break;
5439 case GL_TEXTURE_SWIZZLE_G:
5440 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5441 {
5442 return error(GL_INVALID_VALUE);
5443 }
5444 break;
5445 case GL_TEXTURE_SWIZZLE_B:
5446 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5447 {
5448 return error(GL_INVALID_VALUE);
5449 }
5450 break;
5451 case GL_TEXTURE_SWIZZLE_A:
5452 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5453 {
5454 return error(GL_INVALID_VALUE);
5455 }
5456 break;
5457 default:
5458 return error(GL_INVALID_ENUM);
5459 }
5460 }
5461}
5462
5463void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5464{
5465 glTexParameteri(target, pname, *params);
5466}
5467
5468void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005469 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005470{
5471 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5472 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005473 "const GLvoid* data = %p)",
5474 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005475
5476 if(!es2::IsTextureTarget(target))
5477 {
5478 return error(GL_INVALID_ENUM);
5479 }
5480
5481 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5482 {
5483 return error(GL_INVALID_VALUE);
5484 }
5485
5486 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5487 {
5488 return error(GL_INVALID_VALUE);
5489 }
5490
5491 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5492 {
5493 return error(GL_INVALID_VALUE);
5494 }
5495
5496 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
5497 {
5498 return;
5499 }
5500
Alexis Hetu53f48092016-06-17 14:08:06 -04005501 if(width == 0 || height == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005502 {
5503 return;
5504 }
5505
5506 es2::Context *context = es2::getContext();
5507
5508 if(context)
5509 {
5510 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
5511
Alexis Hetu848aa7f2017-11-17 13:15:32 -05005512 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005513 if(validationError != GL_NONE)
5514 {
5515 return error(validationError);
5516 }
5517
Nicolas Capens0bac2852016-05-07 06:09:58 -04005518 if(target == GL_TEXTURE_2D)
5519 {
5520 es2::Texture2D *texture = context->getTexture2D();
5521
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005522 validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005523
5524 if(validationError == GL_NONE)
5525 {
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005526 texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005527 }
5528 else
5529 {
5530 return error(validationError);
5531 }
5532 }
5533 else if(es2::IsCubemapTextureTarget(target))
5534 {
5535 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5536
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005537 validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005538
5539 if(validationError == GL_NONE)
5540 {
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005541 texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005542 }
5543 else
5544 {
5545 return error(validationError);
5546 }
5547 }
5548 else UNREACHABLE(target);
5549 }
5550}
5551
5552void Uniform1f(GLint location, GLfloat x)
5553{
5554 glUniform1fv(location, 1, &x);
5555}
5556
5557void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5558{
5559 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5560
5561 if(count < 0)
5562 {
5563 return error(GL_INVALID_VALUE);
5564 }
5565
5566 if(location == -1)
5567 {
5568 return;
5569 }
5570
5571 es2::Context *context = es2::getContext();
5572
5573 if(context)
5574 {
5575 es2::Program *program = context->getCurrentProgram();
5576
5577 if(!program)
5578 {
5579 return error(GL_INVALID_OPERATION);
5580 }
5581
5582 if(!program->setUniform1fv(location, count, v))
5583 {
5584 return error(GL_INVALID_OPERATION);
5585 }
5586 }
5587}
5588
5589void Uniform1i(GLint location, GLint x)
5590{
5591 glUniform1iv(location, 1, &x);
5592}
5593
5594void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5595{
5596 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5597
5598 if(count < 0)
5599 {
5600 return error(GL_INVALID_VALUE);
5601 }
5602
5603 if(location == -1)
5604 {
5605 return;
5606 }
5607
5608 es2::Context *context = es2::getContext();
5609
5610 if(context)
5611 {
5612 es2::Program *program = context->getCurrentProgram();
5613
5614 if(!program)
5615 {
5616 return error(GL_INVALID_OPERATION);
5617 }
5618
5619 if(!program->setUniform1iv(location, count, v))
5620 {
5621 return error(GL_INVALID_OPERATION);
5622 }
5623 }
5624}
5625
5626void Uniform2f(GLint location, GLfloat x, GLfloat y)
5627{
5628 GLfloat xy[2] = {x, y};
5629
5630 glUniform2fv(location, 1, (GLfloat*)&xy);
5631}
5632
5633void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5634{
5635 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5636
5637 if(count < 0)
5638 {
5639 return error(GL_INVALID_VALUE);
5640 }
5641
5642 if(location == -1)
5643 {
5644 return;
5645 }
5646
5647 es2::Context *context = es2::getContext();
5648
5649 if(context)
5650 {
5651 es2::Program *program = context->getCurrentProgram();
5652
5653 if(!program)
5654 {
5655 return error(GL_INVALID_OPERATION);
5656 }
5657
5658 if(!program->setUniform2fv(location, count, v))
5659 {
5660 return error(GL_INVALID_OPERATION);
5661 }
5662 }
5663}
5664
5665void Uniform2i(GLint location, GLint x, GLint y)
5666{
5667 GLint xy[4] = {x, y};
5668
5669 glUniform2iv(location, 1, (GLint*)&xy);
5670}
5671
5672void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5673{
5674 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5675
5676 if(count < 0)
5677 {
5678 return error(GL_INVALID_VALUE);
5679 }
5680
5681 if(location == -1)
5682 {
5683 return;
5684 }
5685
5686 es2::Context *context = es2::getContext();
5687
5688 if(context)
5689 {
5690 es2::Program *program = context->getCurrentProgram();
5691
5692 if(!program)
5693 {
5694 return error(GL_INVALID_OPERATION);
5695 }
5696
5697 if(!program->setUniform2iv(location, count, v))
5698 {
5699 return error(GL_INVALID_OPERATION);
5700 }
5701 }
5702}
5703
5704void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5705{
5706 GLfloat xyz[3] = {x, y, z};
5707
5708 glUniform3fv(location, 1, (GLfloat*)&xyz);
5709}
5710
5711void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5712{
5713 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5714
5715 if(count < 0)
5716 {
5717 return error(GL_INVALID_VALUE);
5718 }
5719
5720 if(location == -1)
5721 {
5722 return;
5723 }
5724
5725 es2::Context *context = es2::getContext();
5726
5727 if(context)
5728 {
5729 es2::Program *program = context->getCurrentProgram();
5730
5731 if(!program)
5732 {
5733 return error(GL_INVALID_OPERATION);
5734 }
5735
5736 if(!program->setUniform3fv(location, count, v))
5737 {
5738 return error(GL_INVALID_OPERATION);
5739 }
5740 }
5741}
5742
5743void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5744{
5745 GLint xyz[3] = {x, y, z};
5746
5747 glUniform3iv(location, 1, (GLint*)&xyz);
5748}
5749
5750void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5751{
5752 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5753
5754 if(count < 0)
5755 {
5756 return error(GL_INVALID_VALUE);
5757 }
5758
5759 if(location == -1)
5760 {
5761 return;
5762 }
5763
5764 es2::Context *context = es2::getContext();
5765
5766 if(context)
5767 {
5768 es2::Program *program = context->getCurrentProgram();
5769
5770 if(!program)
5771 {
5772 return error(GL_INVALID_OPERATION);
5773 }
5774
5775 if(!program->setUniform3iv(location, count, v))
5776 {
5777 return error(GL_INVALID_OPERATION);
5778 }
5779 }
5780}
5781
5782void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5783{
5784 GLfloat xyzw[4] = {x, y, z, w};
5785
5786 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5787}
5788
5789void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5790{
5791 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5792
5793 if(count < 0)
5794 {
5795 return error(GL_INVALID_VALUE);
5796 }
5797
5798 if(location == -1)
5799 {
5800 return;
5801 }
5802
5803 es2::Context *context = es2::getContext();
5804
5805 if(context)
5806 {
5807 es2::Program *program = context->getCurrentProgram();
5808
5809 if(!program)
5810 {
5811 return error(GL_INVALID_OPERATION);
5812 }
5813
5814 if(!program->setUniform4fv(location, count, v))
5815 {
5816 return error(GL_INVALID_OPERATION);
5817 }
5818 }
5819}
5820
5821void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5822{
5823 GLint xyzw[4] = {x, y, z, w};
5824
5825 glUniform4iv(location, 1, (GLint*)&xyzw);
5826}
5827
5828void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5829{
5830 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5831
5832 if(count < 0)
5833 {
5834 return error(GL_INVALID_VALUE);
5835 }
5836
5837 if(location == -1)
5838 {
5839 return;
5840 }
5841
5842 es2::Context *context = es2::getContext();
5843
5844 if(context)
5845 {
5846 es2::Program *program = context->getCurrentProgram();
5847
5848 if(!program)
5849 {
5850 return error(GL_INVALID_OPERATION);
5851 }
5852
5853 if(!program->setUniform4iv(location, count, v))
5854 {
5855 return error(GL_INVALID_OPERATION);
5856 }
5857 }
5858}
5859
5860void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5861{
5862 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5863 location, count, transpose, value);
5864
5865 if(count < 0)
5866 {
5867 return error(GL_INVALID_VALUE);
5868 }
5869
5870 if(location == -1)
5871 {
5872 return;
5873 }
5874
5875 es2::Context *context = es2::getContext();
5876
5877 if(context)
5878 {
5879 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5880 {
5881 return error(GL_INVALID_VALUE);
5882 }
5883
5884 es2::Program *program = context->getCurrentProgram();
5885
5886 if(!program)
5887 {
5888 return error(GL_INVALID_OPERATION);
5889 }
5890
5891 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5892 {
5893 return error(GL_INVALID_OPERATION);
5894 }
5895 }
5896}
5897
5898void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5899{
5900 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5901 location, count, transpose, value);
5902
5903 if(count < 0)
5904 {
5905 return error(GL_INVALID_VALUE);
5906 }
5907
5908 if(location == -1)
5909 {
5910 return;
5911 }
5912
5913 es2::Context *context = es2::getContext();
5914
5915 if(context)
5916 {
5917 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5918 {
5919 return error(GL_INVALID_VALUE);
5920 }
5921
5922 es2::Program *program = context->getCurrentProgram();
5923
5924 if(!program)
5925 {
5926 return error(GL_INVALID_OPERATION);
5927 }
5928
5929 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5930 {
5931 return error(GL_INVALID_OPERATION);
5932 }
5933 }
5934}
5935
5936void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5937{
5938 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5939 location, count, transpose, value);
5940
5941 if(count < 0)
5942 {
5943 return error(GL_INVALID_VALUE);
5944 }
5945
5946 if(location == -1)
5947 {
5948 return;
5949 }
5950
5951 es2::Context *context = es2::getContext();
5952
5953 if(context)
5954 {
5955 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5956 {
5957 return error(GL_INVALID_VALUE);
5958 }
5959
5960 es2::Program *program = context->getCurrentProgram();
5961
5962 if(!program)
5963 {
5964 return error(GL_INVALID_OPERATION);
5965 }
5966
5967 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5968 {
5969 return error(GL_INVALID_OPERATION);
5970 }
5971 }
5972}
5973
5974void UseProgram(GLuint program)
5975{
5976 TRACE("(GLuint program = %d)", program);
5977
5978 es2::Context *context = es2::getContext();
5979
5980 if(context)
5981 {
5982 es2::Program *programObject = context->getProgram(program);
5983
5984 if(!programObject && program != 0)
5985 {
5986 if(context->getShader(program))
5987 {
5988 return error(GL_INVALID_OPERATION);
5989 }
5990 else
5991 {
5992 return error(GL_INVALID_VALUE);
5993 }
5994 }
5995
5996 if(program != 0 && !programObject->isLinked())
5997 {
5998 return error(GL_INVALID_OPERATION);
5999 }
6000
6001 context->useProgram(program);
6002 }
6003}
6004
6005void ValidateProgram(GLuint program)
6006{
6007 TRACE("(GLuint program = %d)", program);
6008
6009 es2::Context *context = es2::getContext();
6010
6011 if(context)
6012 {
6013 es2::Program *programObject = context->getProgram(program);
6014
6015 if(!programObject)
6016 {
6017 if(context->getShader(program))
6018 {
6019 return error(GL_INVALID_OPERATION);
6020 }
6021 else
6022 {
6023 return error(GL_INVALID_VALUE);
6024 }
6025 }
6026
Ben Vanik1fd3b282017-07-10 14:08:12 -07006027 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04006028 }
6029}
6030
6031void VertexAttrib1f(GLuint index, GLfloat x)
6032{
6033 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
6034
6035 if(index >= es2::MAX_VERTEX_ATTRIBS)
6036 {
6037 return error(GL_INVALID_VALUE);
6038 }
6039
6040 es2::Context *context = es2::getContext();
6041
6042 if(context)
6043 {
6044 GLfloat vals[4] = { x, 0, 0, 1 };
6045 context->setVertexAttrib(index, vals);
6046 }
6047}
6048
6049void VertexAttrib1fv(GLuint index, const GLfloat* values)
6050{
6051 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6052
6053 if(index >= es2::MAX_VERTEX_ATTRIBS)
6054 {
6055 return error(GL_INVALID_VALUE);
6056 }
6057
6058 es2::Context *context = es2::getContext();
6059
6060 if(context)
6061 {
6062 GLfloat vals[4] = { values[0], 0, 0, 1 };
6063 context->setVertexAttrib(index, vals);
6064 }
6065}
6066
6067void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
6068{
6069 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
6070
6071 if(index >= es2::MAX_VERTEX_ATTRIBS)
6072 {
6073 return error(GL_INVALID_VALUE);
6074 }
6075
6076 es2::Context *context = es2::getContext();
6077
6078 if(context)
6079 {
6080 GLfloat vals[4] = { x, y, 0, 1 };
6081 context->setVertexAttrib(index, vals);
6082 }
6083}
6084
6085void VertexAttrib2fv(GLuint index, const GLfloat* values)
6086{
6087 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6088
6089 if(index >= es2::MAX_VERTEX_ATTRIBS)
6090 {
6091 return error(GL_INVALID_VALUE);
6092 }
6093
6094 es2::Context *context = es2::getContext();
6095
6096 if(context)
6097 {
6098 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6099 context->setVertexAttrib(index, vals);
6100 }
6101}
6102
6103void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6104{
6105 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
6106
6107 if(index >= es2::MAX_VERTEX_ATTRIBS)
6108 {
6109 return error(GL_INVALID_VALUE);
6110 }
6111
6112 es2::Context *context = es2::getContext();
6113
6114 if(context)
6115 {
6116 GLfloat vals[4] = { x, y, z, 1 };
6117 context->setVertexAttrib(index, vals);
6118 }
6119}
6120
6121void VertexAttrib3fv(GLuint index, const GLfloat* values)
6122{
6123 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6124
6125 if(index >= es2::MAX_VERTEX_ATTRIBS)
6126 {
6127 return error(GL_INVALID_VALUE);
6128 }
6129
6130 es2::Context *context = es2::getContext();
6131
6132 if(context)
6133 {
6134 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6135 context->setVertexAttrib(index, vals);
6136 }
6137}
6138
6139void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6140{
6141 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6142
6143 if(index >= es2::MAX_VERTEX_ATTRIBS)
6144 {
6145 return error(GL_INVALID_VALUE);
6146 }
6147
6148 es2::Context *context = es2::getContext();
6149
6150 if(context)
6151 {
6152 GLfloat vals[4] = { x, y, z, w };
6153 context->setVertexAttrib(index, vals);
6154 }
6155}
6156
6157void VertexAttrib4fv(GLuint index, const GLfloat* values)
6158{
6159 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6160
6161 if(index >= es2::MAX_VERTEX_ATTRIBS)
6162 {
6163 return error(GL_INVALID_VALUE);
6164 }
6165
6166 es2::Context *context = es2::getContext();
6167
6168 if(context)
6169 {
6170 context->setVertexAttrib(index, values);
6171 }
6172}
6173
6174void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6175{
6176 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6177 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6178 index, size, type, normalized, stride, ptr);
6179
6180 if(index >= es2::MAX_VERTEX_ATTRIBS)
6181 {
6182 return error(GL_INVALID_VALUE);
6183 }
6184
6185 if(size < 1 || size > 4)
6186 {
6187 return error(GL_INVALID_VALUE);
6188 }
6189
6190 GLint clientVersion = egl::getClientVersion();
6191
6192 switch(type)
6193 {
6194 case GL_BYTE:
6195 case GL_UNSIGNED_BYTE:
6196 case GL_SHORT:
6197 case GL_UNSIGNED_SHORT:
6198 case GL_FIXED:
6199 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006200 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006201 break;
6202 case GL_INT_2_10_10_10_REV:
6203 case GL_UNSIGNED_INT_2_10_10_10_REV:
6204 if(clientVersion >= 3)
6205 {
6206 if(size != 4)
6207 {
6208 return error(GL_INVALID_OPERATION);
6209 }
6210 break;
6211 }
6212 else return error(GL_INVALID_ENUM);
6213 case GL_INT:
6214 case GL_UNSIGNED_INT:
6215 case GL_HALF_FLOAT:
6216 if(clientVersion >= 3)
6217 {
6218 break;
6219 }
6220 else return error(GL_INVALID_ENUM);
6221 default:
6222 return error(GL_INVALID_ENUM);
6223 }
6224
6225 if(stride < 0)
6226 {
6227 return error(GL_INVALID_VALUE);
6228 }
6229
6230 es2::Context *context = es2::getContext();
6231
6232 if(context)
6233 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006234 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6235 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6236 {
6237 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6238 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6239 return error(GL_INVALID_OPERATION);
6240 }
6241
Nicolas Capens0bac2852016-05-07 06:09:58 -04006242 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
6243 }
6244}
6245
6246void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6247{
6248 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6249
6250 if(width < 0 || height < 0)
6251 {
6252 return error(GL_INVALID_VALUE);
6253 }
6254
6255 es2::Context *context = es2::getContext();
6256
6257 if(context)
6258 {
6259 context->setViewportParams(x, y, width, height);
6260 }
6261}
6262
Alexis Hetub9dda642016-10-06 11:25:32 -04006263static 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 -04006264{
6265 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6266 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6267 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6268 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6269
6270 switch(filter)
6271 {
6272 case GL_NEAREST:
6273 break;
6274 default:
6275 return error(GL_INVALID_ENUM);
6276 }
6277
6278 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6279 {
6280 return error(GL_INVALID_VALUE);
6281 }
6282
6283 es2::Context *context = es2::getContext();
6284
6285 if(context)
6286 {
6287 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6288 {
6289 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6290 return error(GL_INVALID_OPERATION);
6291 }
6292
Alexis Hetub9dda642016-10-06 11:25:32 -04006293 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006294 }
6295}
6296
Alexis Hetub9dda642016-10-06 11:25:32 -04006297void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6298{
6299 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6300}
6301
Nicolas Capens0bac2852016-05-07 06:09:58 -04006302void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6303 GLbitfield mask, GLenum filter)
6304{
6305 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6306 {
6307 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6308 return error(GL_INVALID_OPERATION);
6309 }
6310
Alexis Hetub9dda642016-10-06 11:25:32 -04006311 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006312}
6313
6314void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006315 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006316{
6317 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6318 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006319 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6320 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006321
6322 switch(target)
6323 {
6324 case GL_TEXTURE_3D_OES:
6325 switch(format)
6326 {
6327 case GL_DEPTH_COMPONENT:
6328 case GL_DEPTH_STENCIL_OES:
6329 return error(GL_INVALID_OPERATION);
6330 default:
6331 break;
6332 }
6333 break;
6334 default:
6335 return error(GL_INVALID_ENUM);
6336 }
6337
6338 if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
6339 {
6340 return;
6341 }
6342
6343 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6344 {
6345 return error(GL_INVALID_VALUE);
6346 }
6347
6348 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6349 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6350 {
6351 return error(GL_INVALID_VALUE);
6352 }
6353
6354 if(border != 0)
6355 {
6356 return error(GL_INVALID_VALUE);
6357 }
6358
6359 es2::Context *context = es2::getContext();
6360
6361 if(context)
6362 {
6363 es2::Texture3D *texture = context->getTexture3D();
6364
6365 if(!texture)
6366 {
6367 return error(GL_INVALID_OPERATION);
6368 }
6369
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006370 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006371 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006372 if(validationError != GL_NONE)
6373 {
6374 return error(validationError);
6375 }
6376
6377 texture->setImage(context, level, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006378 }
6379}
6380
Alexis Hetu53f48092016-06-17 14:08:06 -04006381void 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 -04006382{
6383 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6384 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006385 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6386 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006387
6388 switch(target)
6389 {
6390 case GL_TEXTURE_3D_OES:
6391 break;
6392 default:
6393 return error(GL_INVALID_ENUM);
6394 }
6395
6396 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6397 {
6398 return;
6399 }
6400
6401 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6402 {
6403 return error(GL_INVALID_VALUE);
6404 }
6405
6406 if((width < 0) || (height < 0) || (depth < 0))
6407 {
6408 return error(GL_INVALID_VALUE);
6409 }
6410
6411 es2::Context *context = es2::getContext();
6412
6413 if(context)
6414 {
6415 es2::Texture3D *texture = context->getTexture3D();
6416
6417 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
6418
6419 GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006420
Nicolas Capens0bac2852016-05-07 06:09:58 -04006421 if(validationError == GL_NONE)
6422 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006423 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006424 }
6425
6426 if(validationError == GL_NONE)
6427 {
6428 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006429 }
6430 else
6431 {
6432 return error(validationError);
6433 }
6434 }
6435}
6436
6437void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6438{
6439 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6440 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6441 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6442
6443 switch(target)
6444 {
6445 case GL_TEXTURE_3D_OES:
6446 break;
6447 default:
6448 return error(GL_INVALID_ENUM);
6449 }
6450
6451 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6452 {
6453 return error(GL_INVALID_VALUE);
6454 }
6455
6456 es2::Context *context = es2::getContext();
6457
6458 if(context)
6459 {
6460 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6461
6462 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6463 {
6464 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6465 }
6466
6467 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6468
6469 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6470 {
6471 return error(GL_INVALID_OPERATION);
6472 }
6473
6474 es2::Texture3D *texture = context->getTexture3D();
6475
6476 GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
6477
6478 if(validationError != GL_NONE)
6479 {
6480 return error(validationError);
6481 }
6482
6483 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6484 }
6485}
6486
6487void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6488{
6489 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6490 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6491 target, level, internalformat, width, height, depth, border, imageSize, data);
6492
6493 switch(target)
6494 {
6495 case GL_TEXTURE_3D_OES:
6496 break;
6497 default:
6498 return error(GL_INVALID_ENUM);
6499 }
6500
6501 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6502 {
6503 return error(GL_INVALID_VALUE);
6504 }
6505
6506 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6507 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6508 {
6509 return error(GL_INVALID_VALUE);
6510 }
6511
6512 switch(internalformat)
6513 {
6514 case GL_DEPTH_COMPONENT:
6515 case GL_DEPTH_COMPONENT16:
6516 case GL_DEPTH_COMPONENT32_OES:
6517 case GL_DEPTH_STENCIL_OES:
6518 case GL_DEPTH24_STENCIL8_OES:
6519 return error(GL_INVALID_OPERATION);
6520 default:
6521 {
6522 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
6523 if(validationError != GL_NONE)
6524 {
6525 return error(validationError);
6526 }
6527 }
6528 }
6529
6530 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6531 {
6532 return error(GL_INVALID_VALUE);
6533 }
6534
6535 es2::Context *context = es2::getContext();
6536
6537 if(context)
6538 {
6539 es2::Texture3D *texture = context->getTexture3D();
6540
6541 if(!texture)
6542 {
6543 return error(GL_INVALID_OPERATION);
6544 }
6545
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006546 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006547
6548 if(validationError != GL_NONE)
6549 {
6550 return error(validationError);
6551 }
6552
Nicolas Capens0bac2852016-05-07 06:09:58 -04006553 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6554 }
6555}
6556
6557void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6558{
6559 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6560 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6561 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6562 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6563
6564 switch(target)
6565 {
6566 case GL_TEXTURE_3D_OES:
6567 break;
6568 default:
6569 return error(GL_INVALID_ENUM);
6570 }
6571
6572 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6573 {
6574 return error(GL_INVALID_VALUE);
6575 }
6576
6577 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6578 {
6579 return error(GL_INVALID_VALUE);
6580 }
6581
6582 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
6583 if(validationError != GL_NONE)
6584 {
6585 return error(validationError);
6586 }
6587
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006588 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006589 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006590 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006591 }
6592
6593 es2::Context *context = es2::getContext();
6594
6595 if(context)
6596 {
6597 es2::Texture3D *texture = context->getTexture3D();
6598
6599 if(!texture)
6600 {
6601 return error(GL_INVALID_OPERATION);
6602 }
6603
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006604 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006605
6606 if(validationError != GL_NONE)
6607 {
6608 return error(validationError);
6609 }
6610
6611 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006612 }
6613}
6614
6615void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6616{
6617 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6618 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6619
6620 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
6621 {
6622 return error(GL_INVALID_ENUM);
6623 }
6624
6625 es2::Context *context = es2::getContext();
6626
6627 if(context)
6628 {
6629 if(texture == 0)
6630 {
6631 textarget = GL_NONE;
6632 }
6633 else
6634 {
6635 es2::Texture *tex = context->getTexture(texture);
6636
6637 if(!tex)
6638 {
6639 return error(GL_INVALID_OPERATION);
6640 }
6641
6642 if(tex->isCompressed(textarget, level))
6643 {
6644 return error(GL_INVALID_OPERATION);
6645 }
6646
6647 switch(textarget)
6648 {
6649 case GL_TEXTURE_3D_OES:
6650 if(tex->getTarget() != GL_TEXTURE_3D_OES)
6651 {
6652 return error(GL_INVALID_OPERATION);
6653 }
6654 break;
6655 default:
6656 return error(GL_INVALID_ENUM);
6657 }
6658
6659 if(level != 0)
6660 {
6661 return error(GL_INVALID_VALUE);
6662 }
6663 }
6664
6665 es2::Framebuffer *framebuffer = nullptr;
6666 GLuint framebufferName = 0;
6667 if(target == GL_READ_FRAMEBUFFER_ANGLE)
6668 {
6669 framebuffer = context->getReadFramebuffer();
6670 framebufferName = context->getReadFramebufferName();
6671 }
6672 else
6673 {
6674 framebuffer = context->getDrawFramebuffer();
6675 framebufferName = context->getDrawFramebufferName();
6676 }
6677
6678 if(framebufferName == 0 || !framebuffer)
6679 {
6680 return error(GL_INVALID_OPERATION);
6681 }
6682
6683 GLint clientVersion = context->getClientVersion();
6684
6685 switch(attachment)
6686 {
6687 case GL_COLOR_ATTACHMENT1:
6688 case GL_COLOR_ATTACHMENT2:
6689 case GL_COLOR_ATTACHMENT3:
6690 case GL_COLOR_ATTACHMENT4:
6691 case GL_COLOR_ATTACHMENT5:
6692 case GL_COLOR_ATTACHMENT6:
6693 case GL_COLOR_ATTACHMENT7:
6694 case GL_COLOR_ATTACHMENT8:
6695 case GL_COLOR_ATTACHMENT9:
6696 case GL_COLOR_ATTACHMENT10:
6697 case GL_COLOR_ATTACHMENT11:
6698 case GL_COLOR_ATTACHMENT12:
6699 case GL_COLOR_ATTACHMENT13:
6700 case GL_COLOR_ATTACHMENT14:
6701 case GL_COLOR_ATTACHMENT15:
6702 case GL_COLOR_ATTACHMENT16:
6703 case GL_COLOR_ATTACHMENT17:
6704 case GL_COLOR_ATTACHMENT18:
6705 case GL_COLOR_ATTACHMENT19:
6706 case GL_COLOR_ATTACHMENT20:
6707 case GL_COLOR_ATTACHMENT21:
6708 case GL_COLOR_ATTACHMENT22:
6709 case GL_COLOR_ATTACHMENT23:
6710 case GL_COLOR_ATTACHMENT24:
6711 case GL_COLOR_ATTACHMENT25:
6712 case GL_COLOR_ATTACHMENT26:
6713 case GL_COLOR_ATTACHMENT27:
6714 case GL_COLOR_ATTACHMENT28:
6715 case GL_COLOR_ATTACHMENT29:
6716 case GL_COLOR_ATTACHMENT30:
6717 case GL_COLOR_ATTACHMENT31:
6718 if(clientVersion < 3)
6719 {
6720 return error(GL_INVALID_ENUM);
6721 }
6722 // fall through
6723 case GL_COLOR_ATTACHMENT0:
6724 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6725 {
6726 return error(GL_INVALID_ENUM);
6727 }
6728 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6729 break;
6730 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6731 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6732 default:
6733 return error(GL_INVALID_ENUM);
6734 }
6735 }
6736}
6737
6738void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6739{
6740 if(egl::getClientVersion() == 1)
6741 {
6742 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6743 }
6744
6745 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6746
6747 switch(target)
6748 {
6749 case GL_TEXTURE_2D:
6750 case GL_TEXTURE_EXTERNAL_OES:
6751 break;
6752 default:
6753 return error(GL_INVALID_ENUM);
6754 }
6755
Nicolas Capens0bac2852016-05-07 06:09:58 -04006756 es2::Context *context = es2::getContext();
6757
6758 if(context)
6759 {
Nicolas Capens58df2f62016-06-07 14:48:56 -04006760 es2::Texture2D *texture = nullptr;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006761
6762 switch(target)
6763 {
6764 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
6765 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
6766 default: UNREACHABLE(target);
6767 }
6768
6769 if(!texture)
6770 {
6771 return error(GL_INVALID_OPERATION);
6772 }
6773
Nicolas Capens58df2f62016-06-07 14:48:56 -04006774 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006775
Nicolas Capens58df2f62016-06-07 14:48:56 -04006776 if(!eglImage)
6777 {
6778 return error(GL_INVALID_OPERATION);
6779 }
6780
6781 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006782 }
6783}
6784
6785void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6786{
6787 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6788
6789 UNIMPLEMENTED();
6790}
6791
6792GLboolean IsRenderbufferOES(GLuint renderbuffer)
6793{
6794 return IsRenderbuffer(renderbuffer);
6795}
6796
6797void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6798{
6799 BindRenderbuffer(target, renderbuffer);
6800}
6801
6802void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6803{
6804 DeleteRenderbuffers(n, renderbuffers);
6805}
6806
6807void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6808{
6809 GenRenderbuffers(n, renderbuffers);
6810}
6811
6812void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6813{
6814 RenderbufferStorage(target, internalformat, width, height);
6815}
6816
6817void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6818{
6819 GetRenderbufferParameteriv(target, pname, params);
6820}
6821
6822GLboolean IsFramebufferOES(GLuint framebuffer)
6823{
6824 return IsFramebuffer(framebuffer);
6825}
6826
6827void BindFramebufferOES(GLenum target, GLuint framebuffer)
6828{
6829 BindFramebuffer(target, framebuffer);
6830}
6831
6832void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6833{
6834 DeleteFramebuffers(n, framebuffers);
6835}
6836
6837void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6838{
6839 GenFramebuffers(n, framebuffers);
6840}
6841
6842GLenum CheckFramebufferStatusOES(GLenum target)
6843{
6844 return CheckFramebufferStatus(target);
6845}
6846
6847void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6848{
6849 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6850}
6851
6852void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6853{
6854 FramebufferTexture2D(target, attachment, textarget, texture, level);
6855}
6856
6857void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6858{
6859 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6860}
6861
6862void GenerateMipmapOES(GLenum target)
6863{
6864 GenerateMipmap(target);
6865}
6866
6867void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6868{
6869 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6870
6871 if(n < 0 || n > MAX_DRAW_BUFFERS)
6872 {
6873 return error(GL_INVALID_VALUE);
6874 }
6875
6876 es2::Context *context = es2::getContext();
6877
6878 if(context)
6879 {
6880 GLuint drawFramebufferName = context->getDrawFramebufferName();
6881
6882 if((drawFramebufferName == 0) && (n != 1))
6883 {
6884 return error(GL_INVALID_OPERATION);
6885 }
6886
6887 for(unsigned int i = 0; i < (unsigned)n; i++)
6888 {
6889 switch(bufs[i])
6890 {
6891 case GL_BACK:
6892 if(drawFramebufferName != 0)
6893 {
6894 return error(GL_INVALID_OPERATION);
6895 }
6896 break;
6897 case GL_NONE:
6898 break;
6899 case GL_COLOR_ATTACHMENT0_EXT:
6900 case GL_COLOR_ATTACHMENT1_EXT:
6901 case GL_COLOR_ATTACHMENT2_EXT:
6902 case GL_COLOR_ATTACHMENT3_EXT:
6903 case GL_COLOR_ATTACHMENT4_EXT:
6904 case GL_COLOR_ATTACHMENT5_EXT:
6905 case GL_COLOR_ATTACHMENT6_EXT:
6906 case GL_COLOR_ATTACHMENT7_EXT:
6907 case GL_COLOR_ATTACHMENT8_EXT:
6908 case GL_COLOR_ATTACHMENT9_EXT:
6909 case GL_COLOR_ATTACHMENT10_EXT:
6910 case GL_COLOR_ATTACHMENT11_EXT:
6911 case GL_COLOR_ATTACHMENT12_EXT:
6912 case GL_COLOR_ATTACHMENT13_EXT:
6913 case GL_COLOR_ATTACHMENT14_EXT:
6914 case GL_COLOR_ATTACHMENT15_EXT:
6915 {
6916 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6917
6918 if(index >= MAX_COLOR_ATTACHMENTS)
6919 {
6920 return error(GL_INVALID_OPERATION);
6921 }
6922
6923 if(index != i)
6924 {
6925 return error(GL_INVALID_OPERATION);
6926 }
6927
6928 if(drawFramebufferName == 0)
6929 {
6930 return error(GL_INVALID_OPERATION);
6931 }
6932 }
6933 break;
6934 default:
6935 return error(GL_INVALID_ENUM);
6936 }
6937 }
6938
6939 context->setFramebufferDrawBuffers(n, bufs);
6940 }
6941}
6942
6943}
6944
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006945extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006946{
6947 struct Extension
6948 {
6949 const char *name;
6950 __eglMustCastToProperFunctionPointerType address;
6951 };
6952
6953 static const Extension glExtensions[] =
6954 {
6955 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6956
6957 EXTENSION(glTexImage3DOES),
6958 EXTENSION(glBlitFramebufferANGLE),
6959 EXTENSION(glBlitFramebufferNV),
6960 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6961 EXTENSION(glDeleteFencesNV),
6962 EXTENSION(glGenFencesNV),
6963 EXTENSION(glIsFenceNV),
6964 EXTENSION(glTestFenceNV),
6965 EXTENSION(glGetFenceivNV),
6966 EXTENSION(glFinishFenceNV),
6967 EXTENSION(glSetFenceNV),
6968 EXTENSION(glGetGraphicsResetStatusEXT),
6969 EXTENSION(glReadnPixelsEXT),
6970 EXTENSION(glGetnUniformfvEXT),
6971 EXTENSION(glGetnUniformivEXT),
6972 EXTENSION(glGenQueriesEXT),
6973 EXTENSION(glDeleteQueriesEXT),
6974 EXTENSION(glIsQueryEXT),
6975 EXTENSION(glBeginQueryEXT),
6976 EXTENSION(glEndQueryEXT),
6977 EXTENSION(glGetQueryivEXT),
6978 EXTENSION(glGetQueryObjectuivEXT),
6979 EXTENSION(glEGLImageTargetTexture2DOES),
6980 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
6981 EXTENSION(glDrawElementsInstancedEXT),
6982 EXTENSION(glDrawArraysInstancedEXT),
6983 EXTENSION(glVertexAttribDivisorEXT),
6984 EXTENSION(glDrawArraysInstancedANGLE),
6985 EXTENSION(glDrawElementsInstancedANGLE),
6986 EXTENSION(glVertexAttribDivisorANGLE),
6987 EXTENSION(glIsRenderbufferOES),
6988 EXTENSION(glBindRenderbufferOES),
6989 EXTENSION(glDeleteRenderbuffersOES),
6990 EXTENSION(glGenRenderbuffersOES),
6991 EXTENSION(glRenderbufferStorageOES),
6992 EXTENSION(glGetRenderbufferParameterivOES),
6993 EXTENSION(glIsFramebufferOES),
6994 EXTENSION(glBindFramebufferOES),
6995 EXTENSION(glDeleteFramebuffersOES),
6996 EXTENSION(glGenFramebuffersOES),
6997 EXTENSION(glCheckFramebufferStatusOES),
6998 EXTENSION(glFramebufferRenderbufferOES),
6999 EXTENSION(glFramebufferTexture2DOES),
7000 EXTENSION(glGetFramebufferAttachmentParameterivOES),
7001 EXTENSION(glGenerateMipmapOES),
7002 EXTENSION(glDrawBuffersEXT),
7003
7004 #undef EXTENSION
7005 };
7006
7007 for(unsigned int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
7008 {
7009 if(strcmp(procname, glExtensions[ext].name) == 0)
7010 {
7011 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
7012 }
7013 }
7014
7015 return nullptr;
7016}