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