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