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