blob: 4be027381f1f706be966df8cf50cf777ce13f55f [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 {
Alexis Hetu2f113e32018-01-18 16:17:54 -05004967 if((internalformat != (GLint)format) &&
4968 !((type == GL_FLOAT) && (format == GL_RGBA) && (internalformat == GL_RGBA32F))) // CHROMIUM_color_buffer_float_rgba
Nicolas Capens0bac2852016-05-07 06:09:58 -04004969 {
4970 return error(GL_INVALID_OPERATION);
4971 }
4972 }
4973
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004974 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05004975 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004976 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004977 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004978 }
4979
4980 if(border != 0)
4981 {
4982 return error(GL_INVALID_VALUE);
4983 }
4984
4985 switch(target)
4986 {
Alexis Hetu46768622018-01-16 22:09:28 -05004987 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004988 if(level != 0)
4989 {
4990 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4991 }
4992 // Fall through
4993 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004994 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4995 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4996 {
4997 return error(GL_INVALID_VALUE);
4998 }
4999 break;
5000 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5001 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5002 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5003 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5004 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5005 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5006 if(width != height)
5007 {
5008 return error(GL_INVALID_VALUE);
5009 }
5010
5011 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5012 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5013 {
5014 return error(GL_INVALID_VALUE);
5015 }
5016 break;
5017 default:
5018 return error(GL_INVALID_ENUM);
5019 }
5020
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005021 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005022
Nicolas Capens5555af42017-12-14 13:14:03 -05005023 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005024 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005025 {
5026 return error(validationError);
5027 }
5028
Alexis Hetu46768622018-01-16 22:09:28 -05005029 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005030 {
Alexis Hetu46768622018-01-16 22:09:28 -05005031 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005032
5033 if(!texture)
5034 {
5035 return error(GL_INVALID_OPERATION);
5036 }
5037
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005038 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005039 }
5040 else
5041 {
5042 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5043
5044 if(!texture)
5045 {
5046 return error(GL_INVALID_OPERATION);
5047 }
5048
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005049 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005050 }
5051 }
5052}
5053
5054void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5055{
5056 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5057
5058 es2::Context *context = es2::getContext();
5059
5060 if(context)
5061 {
5062 es2::Texture *texture;
5063
5064 GLint clientVersion = context->getClientVersion();
5065
5066 switch(target)
5067 {
5068 case GL_TEXTURE_2D:
5069 texture = context->getTexture2D();
5070 break;
5071 case GL_TEXTURE_2D_ARRAY:
5072 if(clientVersion < 3)
5073 {
5074 return error(GL_INVALID_ENUM);
5075 }
5076 else
5077 {
5078 texture = context->getTexture2DArray();
5079 }
5080 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005081 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005082 texture = context->getTexture3D();
5083 break;
5084 case GL_TEXTURE_CUBE_MAP:
5085 texture = context->getTextureCubeMap();
5086 break;
5087 case GL_TEXTURE_EXTERNAL_OES:
5088 texture = context->getTextureExternal();
5089 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005090 case GL_TEXTURE_RECTANGLE_ARB:
5091 texture = context->getTexture2DRect();
5092 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005093 default:
5094 return error(GL_INVALID_ENUM);
5095 }
5096
5097 switch(pname)
5098 {
5099 case GL_TEXTURE_WRAP_S:
5100 if(!texture->setWrapS((GLenum)param))
5101 {
5102 return error(GL_INVALID_ENUM);
5103 }
5104 break;
5105 case GL_TEXTURE_WRAP_T:
5106 if(!texture->setWrapT((GLenum)param))
5107 {
5108 return error(GL_INVALID_ENUM);
5109 }
5110 break;
5111 case GL_TEXTURE_WRAP_R_OES:
5112 if(!texture->setWrapR((GLenum)param))
5113 {
5114 return error(GL_INVALID_ENUM);
5115 }
5116 break;
5117 case GL_TEXTURE_MIN_FILTER:
5118 if(!texture->setMinFilter((GLenum)param))
5119 {
5120 return error(GL_INVALID_ENUM);
5121 }
5122 break;
5123 case GL_TEXTURE_MAG_FILTER:
5124 if(!texture->setMagFilter((GLenum)param))
5125 {
5126 return error(GL_INVALID_ENUM);
5127 }
5128 break;
5129 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5130 if(!texture->setMaxAnisotropy(param))
5131 {
5132 return error(GL_INVALID_VALUE);
5133 }
5134 break;
5135 case GL_TEXTURE_BASE_LEVEL:
5136 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5137 {
5138 return error(GL_INVALID_VALUE);
5139 }
5140 break;
5141 case GL_TEXTURE_COMPARE_FUNC:
5142 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5143 {
5144 return error(GL_INVALID_VALUE);
5145 }
5146 break;
5147 case GL_TEXTURE_COMPARE_MODE:
5148 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5149 {
5150 return error(GL_INVALID_VALUE);
5151 }
5152 break;
5153 case GL_TEXTURE_MAX_LEVEL:
5154 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5155 {
5156 return error(GL_INVALID_VALUE);
5157 }
5158 break;
5159 case GL_TEXTURE_MAX_LOD:
5160 if(clientVersion < 3 || !texture->setMaxLOD(param))
5161 {
5162 return error(GL_INVALID_VALUE);
5163 }
5164 break;
5165 case GL_TEXTURE_MIN_LOD:
5166 if(clientVersion < 3 || !texture->setMinLOD(param))
5167 {
5168 return error(GL_INVALID_VALUE);
5169 }
5170 break;
5171 case GL_TEXTURE_SWIZZLE_R:
5172 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5173 {
5174 return error(GL_INVALID_VALUE);
5175 }
5176 break;
5177 case GL_TEXTURE_SWIZZLE_G:
5178 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5179 {
5180 return error(GL_INVALID_VALUE);
5181 }
5182 break;
5183 case GL_TEXTURE_SWIZZLE_B:
5184 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5185 {
5186 return error(GL_INVALID_VALUE);
5187 }
5188 break;
5189 case GL_TEXTURE_SWIZZLE_A:
5190 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5191 {
5192 return error(GL_INVALID_VALUE);
5193 }
5194 break;
5195 default:
5196 return error(GL_INVALID_ENUM);
5197 }
5198 }
5199}
5200
5201void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5202{
5203 glTexParameterf(target, pname, *params);
5204}
5205
5206void TexParameteri(GLenum target, GLenum pname, GLint param)
5207{
5208 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5209
5210 es2::Context *context = es2::getContext();
5211
5212 if(context)
5213 {
5214 es2::Texture *texture;
5215
5216 GLint clientVersion = context->getClientVersion();
5217
5218 switch(target)
5219 {
5220 case GL_TEXTURE_2D:
5221 texture = context->getTexture2D();
5222 break;
5223 case GL_TEXTURE_2D_ARRAY:
5224 if(clientVersion < 3)
5225 {
5226 return error(GL_INVALID_ENUM);
5227 }
5228 else
5229 {
5230 texture = context->getTexture2DArray();
5231 }
5232 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005233 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005234 texture = context->getTexture3D();
5235 break;
5236 case GL_TEXTURE_CUBE_MAP:
5237 texture = context->getTextureCubeMap();
5238 break;
5239 case GL_TEXTURE_EXTERNAL_OES:
5240 texture = context->getTextureExternal();
5241 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005242 case GL_TEXTURE_RECTANGLE_ARB:
5243 texture = context->getTexture2DRect();
5244 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005245 default:
5246 return error(GL_INVALID_ENUM);
5247 }
5248
5249 switch(pname)
5250 {
5251 case GL_TEXTURE_WRAP_S:
5252 if(!texture->setWrapS((GLenum)param))
5253 {
5254 return error(GL_INVALID_ENUM);
5255 }
5256 break;
5257 case GL_TEXTURE_WRAP_T:
5258 if(!texture->setWrapT((GLenum)param))
5259 {
5260 return error(GL_INVALID_ENUM);
5261 }
5262 break;
5263 case GL_TEXTURE_WRAP_R_OES:
5264 if(!texture->setWrapR((GLenum)param))
5265 {
5266 return error(GL_INVALID_ENUM);
5267 }
5268 break;
5269 case GL_TEXTURE_MIN_FILTER:
5270 if(!texture->setMinFilter((GLenum)param))
5271 {
5272 return error(GL_INVALID_ENUM);
5273 }
5274 break;
5275 case GL_TEXTURE_MAG_FILTER:
5276 if(!texture->setMagFilter((GLenum)param))
5277 {
5278 return error(GL_INVALID_ENUM);
5279 }
5280 break;
5281 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5282 if(!texture->setMaxAnisotropy((GLfloat)param))
5283 {
5284 return error(GL_INVALID_VALUE);
5285 }
5286 break;
5287 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05005288 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
5289 {
5290 return error(GL_INVALID_OPERATION); // Base level has to be 0
5291 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005292 if(clientVersion < 3 || !texture->setBaseLevel(param))
5293 {
5294 return error(GL_INVALID_VALUE);
5295 }
5296 break;
5297 case GL_TEXTURE_COMPARE_FUNC:
5298 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5299 {
5300 return error(GL_INVALID_VALUE);
5301 }
5302 break;
5303 case GL_TEXTURE_COMPARE_MODE:
5304 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5305 {
5306 return error(GL_INVALID_VALUE);
5307 }
5308 break;
5309 case GL_TEXTURE_MAX_LEVEL:
5310 if(clientVersion < 3 || !texture->setMaxLevel(param))
5311 {
5312 return error(GL_INVALID_VALUE);
5313 }
5314 break;
5315 case GL_TEXTURE_MAX_LOD:
5316 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5317 {
5318 return error(GL_INVALID_VALUE);
5319 }
5320 break;
5321 case GL_TEXTURE_MIN_LOD:
5322 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5323 {
5324 return error(GL_INVALID_VALUE);
5325 }
5326 break;
5327 case GL_TEXTURE_SWIZZLE_R:
5328 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5329 {
5330 return error(GL_INVALID_VALUE);
5331 }
5332 break;
5333 case GL_TEXTURE_SWIZZLE_G:
5334 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5335 {
5336 return error(GL_INVALID_VALUE);
5337 }
5338 break;
5339 case GL_TEXTURE_SWIZZLE_B:
5340 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5341 {
5342 return error(GL_INVALID_VALUE);
5343 }
5344 break;
5345 case GL_TEXTURE_SWIZZLE_A:
5346 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5347 {
5348 return error(GL_INVALID_VALUE);
5349 }
5350 break;
5351 default:
5352 return error(GL_INVALID_ENUM);
5353 }
5354 }
5355}
5356
5357void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5358{
5359 glTexParameteri(target, pname, *params);
5360}
5361
5362void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005363 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005364{
5365 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5366 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005367 "const GLvoid* data = %p)",
5368 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005369
5370 if(!es2::IsTextureTarget(target))
5371 {
5372 return error(GL_INVALID_ENUM);
5373 }
5374
5375 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5376 {
5377 return error(GL_INVALID_VALUE);
5378 }
5379
5380 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5381 {
5382 return error(GL_INVALID_VALUE);
5383 }
5384
5385 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5386 {
5387 return error(GL_INVALID_VALUE);
5388 }
5389
Nicolas Capens0bac2852016-05-07 06:09:58 -04005390 es2::Context *context = es2::getContext();
5391
5392 if(context)
5393 {
Alexis Hetu46768622018-01-16 22:09:28 -05005394 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005395 {
Alexis Hetu46768622018-01-16 22:09:28 -05005396 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005397
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005398 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005399 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005400 {
5401 return error(validationError);
5402 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005403
Nicolas Capens5555af42017-12-14 13:14:03 -05005404 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005405 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005406 {
5407 return error(validationError);
5408 }
5409
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005410 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005411 }
5412 else if(es2::IsCubemapTextureTarget(target))
5413 {
5414 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5415
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005416 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005417 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005418 {
5419 return error(validationError);
5420 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005421
Nicolas Capens5555af42017-12-14 13:14:03 -05005422 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005423 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005424 {
5425 return error(validationError);
5426 }
5427
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005428 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005429 }
5430 else UNREACHABLE(target);
5431 }
5432}
5433
5434void Uniform1f(GLint location, GLfloat x)
5435{
5436 glUniform1fv(location, 1, &x);
5437}
5438
5439void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5440{
5441 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5442
5443 if(count < 0)
5444 {
5445 return error(GL_INVALID_VALUE);
5446 }
5447
Nicolas Capens0bac2852016-05-07 06:09:58 -04005448 es2::Context *context = es2::getContext();
5449
5450 if(context)
5451 {
5452 es2::Program *program = context->getCurrentProgram();
5453
5454 if(!program)
5455 {
5456 return error(GL_INVALID_OPERATION);
5457 }
5458
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005459 if(location == -1)
5460 {
5461 return;
5462 }
5463
Nicolas Capens0bac2852016-05-07 06:09:58 -04005464 if(!program->setUniform1fv(location, count, v))
5465 {
5466 return error(GL_INVALID_OPERATION);
5467 }
5468 }
5469}
5470
5471void Uniform1i(GLint location, GLint x)
5472{
5473 glUniform1iv(location, 1, &x);
5474}
5475
5476void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5477{
5478 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5479
5480 if(count < 0)
5481 {
5482 return error(GL_INVALID_VALUE);
5483 }
5484
Nicolas Capens0bac2852016-05-07 06:09:58 -04005485 es2::Context *context = es2::getContext();
5486
5487 if(context)
5488 {
5489 es2::Program *program = context->getCurrentProgram();
5490
5491 if(!program)
5492 {
5493 return error(GL_INVALID_OPERATION);
5494 }
5495
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005496 if(location == -1)
5497 {
5498 return;
5499 }
5500
Nicolas Capens0bac2852016-05-07 06:09:58 -04005501 if(!program->setUniform1iv(location, count, v))
5502 {
5503 return error(GL_INVALID_OPERATION);
5504 }
5505 }
5506}
5507
5508void Uniform2f(GLint location, GLfloat x, GLfloat y)
5509{
5510 GLfloat xy[2] = {x, y};
5511
5512 glUniform2fv(location, 1, (GLfloat*)&xy);
5513}
5514
5515void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5516{
5517 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5518
5519 if(count < 0)
5520 {
5521 return error(GL_INVALID_VALUE);
5522 }
5523
Nicolas Capens0bac2852016-05-07 06:09:58 -04005524 es2::Context *context = es2::getContext();
5525
5526 if(context)
5527 {
5528 es2::Program *program = context->getCurrentProgram();
5529
5530 if(!program)
5531 {
5532 return error(GL_INVALID_OPERATION);
5533 }
5534
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005535 if(location == -1)
5536 {
5537 return;
5538 }
5539
Nicolas Capens0bac2852016-05-07 06:09:58 -04005540 if(!program->setUniform2fv(location, count, v))
5541 {
5542 return error(GL_INVALID_OPERATION);
5543 }
5544 }
5545}
5546
5547void Uniform2i(GLint location, GLint x, GLint y)
5548{
5549 GLint xy[4] = {x, y};
5550
5551 glUniform2iv(location, 1, (GLint*)&xy);
5552}
5553
5554void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5555{
5556 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5557
5558 if(count < 0)
5559 {
5560 return error(GL_INVALID_VALUE);
5561 }
5562
Nicolas Capens0bac2852016-05-07 06:09:58 -04005563 es2::Context *context = es2::getContext();
5564
5565 if(context)
5566 {
5567 es2::Program *program = context->getCurrentProgram();
5568
5569 if(!program)
5570 {
5571 return error(GL_INVALID_OPERATION);
5572 }
5573
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005574 if(location == -1)
5575 {
5576 return;
5577 }
5578
Nicolas Capens0bac2852016-05-07 06:09:58 -04005579 if(!program->setUniform2iv(location, count, v))
5580 {
5581 return error(GL_INVALID_OPERATION);
5582 }
5583 }
5584}
5585
5586void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5587{
5588 GLfloat xyz[3] = {x, y, z};
5589
5590 glUniform3fv(location, 1, (GLfloat*)&xyz);
5591}
5592
5593void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5594{
5595 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5596
5597 if(count < 0)
5598 {
5599 return error(GL_INVALID_VALUE);
5600 }
5601
Nicolas Capens0bac2852016-05-07 06:09:58 -04005602 es2::Context *context = es2::getContext();
5603
5604 if(context)
5605 {
5606 es2::Program *program = context->getCurrentProgram();
5607
5608 if(!program)
5609 {
5610 return error(GL_INVALID_OPERATION);
5611 }
5612
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005613 if(location == -1)
5614 {
5615 return;
5616 }
5617
Nicolas Capens0bac2852016-05-07 06:09:58 -04005618 if(!program->setUniform3fv(location, count, v))
5619 {
5620 return error(GL_INVALID_OPERATION);
5621 }
5622 }
5623}
5624
5625void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5626{
5627 GLint xyz[3] = {x, y, z};
5628
5629 glUniform3iv(location, 1, (GLint*)&xyz);
5630}
5631
5632void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5633{
5634 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5635
5636 if(count < 0)
5637 {
5638 return error(GL_INVALID_VALUE);
5639 }
5640
Nicolas Capens0bac2852016-05-07 06:09:58 -04005641 es2::Context *context = es2::getContext();
5642
5643 if(context)
5644 {
5645 es2::Program *program = context->getCurrentProgram();
5646
5647 if(!program)
5648 {
5649 return error(GL_INVALID_OPERATION);
5650 }
5651
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005652 if(location == -1)
5653 {
5654 return;
5655 }
5656
Nicolas Capens0bac2852016-05-07 06:09:58 -04005657 if(!program->setUniform3iv(location, count, v))
5658 {
5659 return error(GL_INVALID_OPERATION);
5660 }
5661 }
5662}
5663
5664void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5665{
5666 GLfloat xyzw[4] = {x, y, z, w};
5667
5668 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5669}
5670
5671void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5672{
5673 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5674
5675 if(count < 0)
5676 {
5677 return error(GL_INVALID_VALUE);
5678 }
5679
Nicolas Capens0bac2852016-05-07 06:09:58 -04005680 es2::Context *context = es2::getContext();
5681
5682 if(context)
5683 {
5684 es2::Program *program = context->getCurrentProgram();
5685
5686 if(!program)
5687 {
5688 return error(GL_INVALID_OPERATION);
5689 }
5690
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005691 if(location == -1)
5692 {
5693 return;
5694 }
5695
Nicolas Capens0bac2852016-05-07 06:09:58 -04005696 if(!program->setUniform4fv(location, count, v))
5697 {
5698 return error(GL_INVALID_OPERATION);
5699 }
5700 }
5701}
5702
5703void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5704{
5705 GLint xyzw[4] = {x, y, z, w};
5706
5707 glUniform4iv(location, 1, (GLint*)&xyzw);
5708}
5709
5710void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5711{
5712 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5713
5714 if(count < 0)
5715 {
5716 return error(GL_INVALID_VALUE);
5717 }
5718
Nicolas Capens0bac2852016-05-07 06:09:58 -04005719 es2::Context *context = es2::getContext();
5720
5721 if(context)
5722 {
5723 es2::Program *program = context->getCurrentProgram();
5724
5725 if(!program)
5726 {
5727 return error(GL_INVALID_OPERATION);
5728 }
5729
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005730 if(location == -1)
5731 {
5732 return;
5733 }
5734
Nicolas Capens0bac2852016-05-07 06:09:58 -04005735 if(!program->setUniform4iv(location, count, v))
5736 {
5737 return error(GL_INVALID_OPERATION);
5738 }
5739 }
5740}
5741
5742void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5743{
5744 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5745 location, count, transpose, value);
5746
5747 if(count < 0)
5748 {
5749 return error(GL_INVALID_VALUE);
5750 }
5751
Nicolas Capens0bac2852016-05-07 06:09:58 -04005752 es2::Context *context = es2::getContext();
5753
5754 if(context)
5755 {
5756 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5757 {
5758 return error(GL_INVALID_VALUE);
5759 }
5760
5761 es2::Program *program = context->getCurrentProgram();
5762
5763 if(!program)
5764 {
5765 return error(GL_INVALID_OPERATION);
5766 }
5767
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005768 if(location == -1)
5769 {
5770 return;
5771 }
5772
Nicolas Capens0bac2852016-05-07 06:09:58 -04005773 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5774 {
5775 return error(GL_INVALID_OPERATION);
5776 }
5777 }
5778}
5779
5780void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5781{
5782 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5783 location, count, transpose, value);
5784
5785 if(count < 0)
5786 {
5787 return error(GL_INVALID_VALUE);
5788 }
5789
Nicolas Capens0bac2852016-05-07 06:09:58 -04005790 es2::Context *context = es2::getContext();
5791
5792 if(context)
5793 {
5794 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5795 {
5796 return error(GL_INVALID_VALUE);
5797 }
5798
5799 es2::Program *program = context->getCurrentProgram();
5800
5801 if(!program)
5802 {
5803 return error(GL_INVALID_OPERATION);
5804 }
5805
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005806 if(location == -1)
5807 {
5808 return;
5809 }
5810
Nicolas Capens0bac2852016-05-07 06:09:58 -04005811 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5812 {
5813 return error(GL_INVALID_OPERATION);
5814 }
5815 }
5816}
5817
5818void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5819{
5820 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5821 location, count, transpose, value);
5822
5823 if(count < 0)
5824 {
5825 return error(GL_INVALID_VALUE);
5826 }
5827
Nicolas Capens0bac2852016-05-07 06:09:58 -04005828 es2::Context *context = es2::getContext();
5829
5830 if(context)
5831 {
5832 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5833 {
5834 return error(GL_INVALID_VALUE);
5835 }
5836
5837 es2::Program *program = context->getCurrentProgram();
5838
5839 if(!program)
5840 {
5841 return error(GL_INVALID_OPERATION);
5842 }
5843
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005844 if(location == -1)
5845 {
5846 return;
5847 }
5848
Nicolas Capens0bac2852016-05-07 06:09:58 -04005849 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5850 {
5851 return error(GL_INVALID_OPERATION);
5852 }
5853 }
5854}
5855
5856void UseProgram(GLuint program)
5857{
5858 TRACE("(GLuint program = %d)", program);
5859
5860 es2::Context *context = es2::getContext();
5861
5862 if(context)
5863 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005864 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5865 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5866 {
5867 return error(GL_INVALID_OPERATION);
5868 }
5869
Nicolas Capens0bac2852016-05-07 06:09:58 -04005870 es2::Program *programObject = context->getProgram(program);
5871
5872 if(!programObject && program != 0)
5873 {
5874 if(context->getShader(program))
5875 {
5876 return error(GL_INVALID_OPERATION);
5877 }
5878 else
5879 {
5880 return error(GL_INVALID_VALUE);
5881 }
5882 }
5883
5884 if(program != 0 && !programObject->isLinked())
5885 {
5886 return error(GL_INVALID_OPERATION);
5887 }
5888
5889 context->useProgram(program);
5890 }
5891}
5892
5893void ValidateProgram(GLuint program)
5894{
5895 TRACE("(GLuint program = %d)", program);
5896
5897 es2::Context *context = es2::getContext();
5898
5899 if(context)
5900 {
5901 es2::Program *programObject = context->getProgram(program);
5902
5903 if(!programObject)
5904 {
5905 if(context->getShader(program))
5906 {
5907 return error(GL_INVALID_OPERATION);
5908 }
5909 else
5910 {
5911 return error(GL_INVALID_VALUE);
5912 }
5913 }
5914
Ben Vanik1fd3b282017-07-10 14:08:12 -07005915 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005916 }
5917}
5918
5919void VertexAttrib1f(GLuint index, GLfloat x)
5920{
5921 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5922
5923 if(index >= es2::MAX_VERTEX_ATTRIBS)
5924 {
5925 return error(GL_INVALID_VALUE);
5926 }
5927
5928 es2::Context *context = es2::getContext();
5929
5930 if(context)
5931 {
5932 GLfloat vals[4] = { x, 0, 0, 1 };
5933 context->setVertexAttrib(index, vals);
5934 }
5935}
5936
5937void VertexAttrib1fv(GLuint index, const GLfloat* values)
5938{
5939 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5940
5941 if(index >= es2::MAX_VERTEX_ATTRIBS)
5942 {
5943 return error(GL_INVALID_VALUE);
5944 }
5945
5946 es2::Context *context = es2::getContext();
5947
5948 if(context)
5949 {
5950 GLfloat vals[4] = { values[0], 0, 0, 1 };
5951 context->setVertexAttrib(index, vals);
5952 }
5953}
5954
5955void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5956{
5957 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5958
5959 if(index >= es2::MAX_VERTEX_ATTRIBS)
5960 {
5961 return error(GL_INVALID_VALUE);
5962 }
5963
5964 es2::Context *context = es2::getContext();
5965
5966 if(context)
5967 {
5968 GLfloat vals[4] = { x, y, 0, 1 };
5969 context->setVertexAttrib(index, vals);
5970 }
5971}
5972
5973void VertexAttrib2fv(GLuint index, const GLfloat* values)
5974{
5975 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5976
5977 if(index >= es2::MAX_VERTEX_ATTRIBS)
5978 {
5979 return error(GL_INVALID_VALUE);
5980 }
5981
5982 es2::Context *context = es2::getContext();
5983
5984 if(context)
5985 {
5986 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5987 context->setVertexAttrib(index, vals);
5988 }
5989}
5990
5991void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5992{
5993 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5994
5995 if(index >= es2::MAX_VERTEX_ATTRIBS)
5996 {
5997 return error(GL_INVALID_VALUE);
5998 }
5999
6000 es2::Context *context = es2::getContext();
6001
6002 if(context)
6003 {
6004 GLfloat vals[4] = { x, y, z, 1 };
6005 context->setVertexAttrib(index, vals);
6006 }
6007}
6008
6009void VertexAttrib3fv(GLuint index, const GLfloat* values)
6010{
6011 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6012
6013 if(index >= es2::MAX_VERTEX_ATTRIBS)
6014 {
6015 return error(GL_INVALID_VALUE);
6016 }
6017
6018 es2::Context *context = es2::getContext();
6019
6020 if(context)
6021 {
6022 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6023 context->setVertexAttrib(index, vals);
6024 }
6025}
6026
6027void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6028{
6029 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6030
6031 if(index >= es2::MAX_VERTEX_ATTRIBS)
6032 {
6033 return error(GL_INVALID_VALUE);
6034 }
6035
6036 es2::Context *context = es2::getContext();
6037
6038 if(context)
6039 {
6040 GLfloat vals[4] = { x, y, z, w };
6041 context->setVertexAttrib(index, vals);
6042 }
6043}
6044
6045void VertexAttrib4fv(GLuint index, const GLfloat* values)
6046{
6047 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6048
6049 if(index >= es2::MAX_VERTEX_ATTRIBS)
6050 {
6051 return error(GL_INVALID_VALUE);
6052 }
6053
6054 es2::Context *context = es2::getContext();
6055
6056 if(context)
6057 {
6058 context->setVertexAttrib(index, values);
6059 }
6060}
6061
6062void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6063{
6064 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6065 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6066 index, size, type, normalized, stride, ptr);
6067
6068 if(index >= es2::MAX_VERTEX_ATTRIBS)
6069 {
6070 return error(GL_INVALID_VALUE);
6071 }
6072
6073 if(size < 1 || size > 4)
6074 {
6075 return error(GL_INVALID_VALUE);
6076 }
6077
6078 GLint clientVersion = egl::getClientVersion();
6079
6080 switch(type)
6081 {
6082 case GL_BYTE:
6083 case GL_UNSIGNED_BYTE:
6084 case GL_SHORT:
6085 case GL_UNSIGNED_SHORT:
6086 case GL_FIXED:
6087 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006088 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006089 break;
6090 case GL_INT_2_10_10_10_REV:
6091 case GL_UNSIGNED_INT_2_10_10_10_REV:
6092 if(clientVersion >= 3)
6093 {
6094 if(size != 4)
6095 {
6096 return error(GL_INVALID_OPERATION);
6097 }
6098 break;
6099 }
6100 else return error(GL_INVALID_ENUM);
6101 case GL_INT:
6102 case GL_UNSIGNED_INT:
6103 case GL_HALF_FLOAT:
6104 if(clientVersion >= 3)
6105 {
6106 break;
6107 }
6108 else return error(GL_INVALID_ENUM);
6109 default:
6110 return error(GL_INVALID_ENUM);
6111 }
6112
6113 if(stride < 0)
6114 {
6115 return error(GL_INVALID_VALUE);
6116 }
6117
6118 es2::Context *context = es2::getContext();
6119
6120 if(context)
6121 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006122 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6123 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6124 {
6125 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6126 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6127 return error(GL_INVALID_OPERATION);
6128 }
6129
Alexis Hetu6f284032017-12-11 15:19:36 -05006130 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006131 }
6132}
6133
6134void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6135{
6136 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6137
6138 if(width < 0 || height < 0)
6139 {
6140 return error(GL_INVALID_VALUE);
6141 }
6142
6143 es2::Context *context = es2::getContext();
6144
6145 if(context)
6146 {
6147 context->setViewportParams(x, y, width, height);
6148 }
6149}
6150
Alexis Hetub9dda642016-10-06 11:25:32 -04006151static 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 -04006152{
6153 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6154 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6155 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6156 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6157
6158 switch(filter)
6159 {
6160 case GL_NEAREST:
6161 break;
6162 default:
6163 return error(GL_INVALID_ENUM);
6164 }
6165
6166 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6167 {
6168 return error(GL_INVALID_VALUE);
6169 }
6170
6171 es2::Context *context = es2::getContext();
6172
6173 if(context)
6174 {
6175 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6176 {
6177 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6178 return error(GL_INVALID_OPERATION);
6179 }
6180
Alexis Hetub9dda642016-10-06 11:25:32 -04006181 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006182 }
6183}
6184
Alexis Hetub9dda642016-10-06 11:25:32 -04006185void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6186{
6187 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6188}
6189
Nicolas Capens0bac2852016-05-07 06:09:58 -04006190void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6191 GLbitfield mask, GLenum filter)
6192{
6193 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6194 {
6195 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6196 return error(GL_INVALID_OPERATION);
6197 }
6198
Alexis Hetub9dda642016-10-06 11:25:32 -04006199 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006200}
6201
6202void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006203 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006204{
6205 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6206 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006207 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6208 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006209
6210 switch(target)
6211 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006212 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006213 switch(format)
6214 {
6215 case GL_DEPTH_COMPONENT:
6216 case GL_DEPTH_STENCIL_OES:
6217 return error(GL_INVALID_OPERATION);
6218 default:
6219 break;
6220 }
6221 break;
6222 default:
6223 return error(GL_INVALID_ENUM);
6224 }
6225
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006226 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006227 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006228 return error(GL_INVALID_OPERATION);
6229 }
6230
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006231 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, egl::getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05006232 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006233 {
6234 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006235 }
6236
6237 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6238 {
6239 return error(GL_INVALID_VALUE);
6240 }
6241
6242 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6243 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6244 {
6245 return error(GL_INVALID_VALUE);
6246 }
6247
6248 if(border != 0)
6249 {
6250 return error(GL_INVALID_VALUE);
6251 }
6252
6253 es2::Context *context = es2::getContext();
6254
6255 if(context)
6256 {
6257 es2::Texture3D *texture = context->getTexture3D();
6258
6259 if(!texture)
6260 {
6261 return error(GL_INVALID_OPERATION);
6262 }
6263
Nicolas Capens2fc90512018-01-23 22:24:22 +00006264 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006265 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006266 {
6267 return error(validationError);
6268 }
6269
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006270 GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
6271 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006272 }
6273}
6274
Alexis Hetu53f48092016-06-17 14:08:06 -04006275void 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 -04006276{
6277 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6278 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006279 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6280 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006281
6282 switch(target)
6283 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006284 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006285 break;
6286 default:
6287 return error(GL_INVALID_ENUM);
6288 }
6289
Nicolas Capens0bac2852016-05-07 06:09:58 -04006290 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6291 {
6292 return error(GL_INVALID_VALUE);
6293 }
6294
6295 if((width < 0) || (height < 0) || (depth < 0))
6296 {
6297 return error(GL_INVALID_VALUE);
6298 }
6299
6300 es2::Context *context = es2::getContext();
6301
6302 if(context)
6303 {
6304 es2::Texture3D *texture = context->getTexture3D();
6305
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006306 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 -05006307 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006308 {
6309 return error(validationError);
6310 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006311
Nicolas Capens5555af42017-12-14 13:14:03 -05006312 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006313 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006314 {
6315 return error(validationError);
6316 }
6317
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006318 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006319 }
6320}
6321
6322void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6323{
6324 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6325 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6326 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6327
6328 switch(target)
6329 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006330 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006331 break;
6332 default:
6333 return error(GL_INVALID_ENUM);
6334 }
6335
6336 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6337 {
6338 return error(GL_INVALID_VALUE);
6339 }
6340
6341 es2::Context *context = es2::getContext();
6342
6343 if(context)
6344 {
6345 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6346
6347 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6348 {
6349 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6350 }
6351
6352 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6353
6354 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6355 {
6356 return error(GL_INVALID_OPERATION);
6357 }
6358
6359 es2::Texture3D *texture = context->getTexture3D();
6360
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006361 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 -05006362 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006363 {
6364 return error(validationError);
6365 }
6366
Nicolas Capens1529c2c2018-02-06 14:44:47 -05006367 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006368 }
6369}
6370
6371void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6372{
6373 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6374 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6375 target, level, internalformat, width, height, depth, border, imageSize, data);
6376
6377 switch(target)
6378 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006379 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006380 break;
6381 default:
6382 return error(GL_INVALID_ENUM);
6383 }
6384
6385 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6386 {
6387 return error(GL_INVALID_VALUE);
6388 }
6389
6390 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6391 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6392 {
6393 return error(GL_INVALID_VALUE);
6394 }
6395
Nicolas Capens03589982018-02-01 17:28:32 -05006396 if(!IsCompressed(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006397 {
Nicolas Capens03589982018-02-01 17:28:32 -05006398 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006399 }
6400
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006401 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006402 {
6403 return error(GL_INVALID_VALUE);
6404 }
6405
6406 es2::Context *context = es2::getContext();
6407
6408 if(context)
6409 {
6410 es2::Texture3D *texture = context->getTexture3D();
6411
6412 if(!texture)
6413 {
6414 return error(GL_INVALID_OPERATION);
6415 }
6416
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006417 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006418
Nicolas Capense65f5642018-02-26 17:47:06 -05006419 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006420 {
6421 return error(validationError);
6422 }
6423
Nicolas Capens0bac2852016-05-07 06:09:58 -04006424 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6425 }
6426}
6427
6428void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6429{
6430 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6431 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6432 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6433 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6434
6435 switch(target)
6436 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006437 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006438 break;
6439 default:
6440 return error(GL_INVALID_ENUM);
6441 }
6442
6443 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6444 {
6445 return error(GL_INVALID_VALUE);
6446 }
6447
6448 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6449 {
6450 return error(GL_INVALID_VALUE);
6451 }
6452
Nicolas Capens03589982018-02-01 17:28:32 -05006453 if(!IsCompressed(format, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006454 {
Nicolas Capens03589982018-02-01 17:28:32 -05006455 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006456 }
6457
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006458 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006459 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006460 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006461 }
6462
6463 es2::Context *context = es2::getContext();
6464
6465 if(context)
6466 {
6467 es2::Texture3D *texture = context->getTexture3D();
6468
6469 if(!texture)
6470 {
6471 return error(GL_INVALID_OPERATION);
6472 }
6473
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006474 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05006475 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006476 {
6477 return error(validationError);
6478 }
6479
6480 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006481 }
6482}
6483
6484void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6485{
6486 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6487 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6488
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006489 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006490 {
6491 return error(GL_INVALID_ENUM);
6492 }
6493
6494 es2::Context *context = es2::getContext();
6495
6496 if(context)
6497 {
6498 if(texture == 0)
6499 {
6500 textarget = GL_NONE;
6501 }
6502 else
6503 {
6504 es2::Texture *tex = context->getTexture(texture);
6505
6506 if(!tex)
6507 {
6508 return error(GL_INVALID_OPERATION);
6509 }
6510
6511 if(tex->isCompressed(textarget, level))
6512 {
6513 return error(GL_INVALID_OPERATION);
6514 }
6515
6516 switch(textarget)
6517 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006518 case GL_TEXTURE_3D:
6519 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006520 {
6521 return error(GL_INVALID_OPERATION);
6522 }
6523 break;
6524 default:
6525 return error(GL_INVALID_ENUM);
6526 }
6527
6528 if(level != 0)
6529 {
6530 return error(GL_INVALID_VALUE);
6531 }
6532 }
6533
6534 es2::Framebuffer *framebuffer = nullptr;
6535 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006536 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006537 {
6538 framebuffer = context->getReadFramebuffer();
6539 framebufferName = context->getReadFramebufferName();
6540 }
6541 else
6542 {
6543 framebuffer = context->getDrawFramebuffer();
6544 framebufferName = context->getDrawFramebufferName();
6545 }
6546
6547 if(framebufferName == 0 || !framebuffer)
6548 {
6549 return error(GL_INVALID_OPERATION);
6550 }
6551
6552 GLint clientVersion = context->getClientVersion();
6553
6554 switch(attachment)
6555 {
6556 case GL_COLOR_ATTACHMENT1:
6557 case GL_COLOR_ATTACHMENT2:
6558 case GL_COLOR_ATTACHMENT3:
6559 case GL_COLOR_ATTACHMENT4:
6560 case GL_COLOR_ATTACHMENT5:
6561 case GL_COLOR_ATTACHMENT6:
6562 case GL_COLOR_ATTACHMENT7:
6563 case GL_COLOR_ATTACHMENT8:
6564 case GL_COLOR_ATTACHMENT9:
6565 case GL_COLOR_ATTACHMENT10:
6566 case GL_COLOR_ATTACHMENT11:
6567 case GL_COLOR_ATTACHMENT12:
6568 case GL_COLOR_ATTACHMENT13:
6569 case GL_COLOR_ATTACHMENT14:
6570 case GL_COLOR_ATTACHMENT15:
6571 case GL_COLOR_ATTACHMENT16:
6572 case GL_COLOR_ATTACHMENT17:
6573 case GL_COLOR_ATTACHMENT18:
6574 case GL_COLOR_ATTACHMENT19:
6575 case GL_COLOR_ATTACHMENT20:
6576 case GL_COLOR_ATTACHMENT21:
6577 case GL_COLOR_ATTACHMENT22:
6578 case GL_COLOR_ATTACHMENT23:
6579 case GL_COLOR_ATTACHMENT24:
6580 case GL_COLOR_ATTACHMENT25:
6581 case GL_COLOR_ATTACHMENT26:
6582 case GL_COLOR_ATTACHMENT27:
6583 case GL_COLOR_ATTACHMENT28:
6584 case GL_COLOR_ATTACHMENT29:
6585 case GL_COLOR_ATTACHMENT30:
6586 case GL_COLOR_ATTACHMENT31:
6587 if(clientVersion < 3)
6588 {
6589 return error(GL_INVALID_ENUM);
6590 }
6591 // fall through
6592 case GL_COLOR_ATTACHMENT0:
6593 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6594 {
6595 return error(GL_INVALID_ENUM);
6596 }
6597 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6598 break;
6599 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6600 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6601 default:
6602 return error(GL_INVALID_ENUM);
6603 }
6604 }
6605}
6606
6607void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6608{
6609 if(egl::getClientVersion() == 1)
6610 {
6611 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6612 }
6613
6614 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6615
6616 switch(target)
6617 {
6618 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006619 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006620 case GL_TEXTURE_EXTERNAL_OES:
6621 break;
6622 default:
6623 return error(GL_INVALID_ENUM);
6624 }
6625
Nicolas Capens0bac2852016-05-07 06:09:58 -04006626 es2::Context *context = es2::getContext();
6627
6628 if(context)
6629 {
Alexis Hetu46768622018-01-16 22:09:28 -05006630 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006631
6632 if(!texture)
6633 {
6634 return error(GL_INVALID_OPERATION);
6635 }
6636
Nicolas Capens58df2f62016-06-07 14:48:56 -04006637 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006638
Nicolas Capens58df2f62016-06-07 14:48:56 -04006639 if(!eglImage)
6640 {
6641 return error(GL_INVALID_OPERATION);
6642 }
6643
6644 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006645 }
6646}
6647
6648void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6649{
6650 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6651
6652 UNIMPLEMENTED();
6653}
6654
6655GLboolean IsRenderbufferOES(GLuint renderbuffer)
6656{
6657 return IsRenderbuffer(renderbuffer);
6658}
6659
6660void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6661{
6662 BindRenderbuffer(target, renderbuffer);
6663}
6664
6665void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6666{
6667 DeleteRenderbuffers(n, renderbuffers);
6668}
6669
6670void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6671{
6672 GenRenderbuffers(n, renderbuffers);
6673}
6674
6675void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6676{
6677 RenderbufferStorage(target, internalformat, width, height);
6678}
6679
6680void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6681{
6682 GetRenderbufferParameteriv(target, pname, params);
6683}
6684
6685GLboolean IsFramebufferOES(GLuint framebuffer)
6686{
6687 return IsFramebuffer(framebuffer);
6688}
6689
6690void BindFramebufferOES(GLenum target, GLuint framebuffer)
6691{
6692 BindFramebuffer(target, framebuffer);
6693}
6694
6695void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6696{
6697 DeleteFramebuffers(n, framebuffers);
6698}
6699
6700void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6701{
6702 GenFramebuffers(n, framebuffers);
6703}
6704
6705GLenum CheckFramebufferStatusOES(GLenum target)
6706{
6707 return CheckFramebufferStatus(target);
6708}
6709
6710void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6711{
6712 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6713}
6714
6715void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6716{
6717 FramebufferTexture2D(target, attachment, textarget, texture, level);
6718}
6719
6720void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6721{
6722 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6723}
6724
6725void GenerateMipmapOES(GLenum target)
6726{
6727 GenerateMipmap(target);
6728}
6729
6730void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6731{
6732 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6733
6734 if(n < 0 || n > MAX_DRAW_BUFFERS)
6735 {
6736 return error(GL_INVALID_VALUE);
6737 }
6738
6739 es2::Context *context = es2::getContext();
6740
6741 if(context)
6742 {
6743 GLuint drawFramebufferName = context->getDrawFramebufferName();
6744
6745 if((drawFramebufferName == 0) && (n != 1))
6746 {
6747 return error(GL_INVALID_OPERATION);
6748 }
6749
6750 for(unsigned int i = 0; i < (unsigned)n; i++)
6751 {
6752 switch(bufs[i])
6753 {
6754 case GL_BACK:
6755 if(drawFramebufferName != 0)
6756 {
6757 return error(GL_INVALID_OPERATION);
6758 }
6759 break;
6760 case GL_NONE:
6761 break;
6762 case GL_COLOR_ATTACHMENT0_EXT:
6763 case GL_COLOR_ATTACHMENT1_EXT:
6764 case GL_COLOR_ATTACHMENT2_EXT:
6765 case GL_COLOR_ATTACHMENT3_EXT:
6766 case GL_COLOR_ATTACHMENT4_EXT:
6767 case GL_COLOR_ATTACHMENT5_EXT:
6768 case GL_COLOR_ATTACHMENT6_EXT:
6769 case GL_COLOR_ATTACHMENT7_EXT:
6770 case GL_COLOR_ATTACHMENT8_EXT:
6771 case GL_COLOR_ATTACHMENT9_EXT:
6772 case GL_COLOR_ATTACHMENT10_EXT:
6773 case GL_COLOR_ATTACHMENT11_EXT:
6774 case GL_COLOR_ATTACHMENT12_EXT:
6775 case GL_COLOR_ATTACHMENT13_EXT:
6776 case GL_COLOR_ATTACHMENT14_EXT:
6777 case GL_COLOR_ATTACHMENT15_EXT:
6778 {
6779 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6780
6781 if(index >= MAX_COLOR_ATTACHMENTS)
6782 {
6783 return error(GL_INVALID_OPERATION);
6784 }
6785
6786 if(index != i)
6787 {
6788 return error(GL_INVALID_OPERATION);
6789 }
6790
6791 if(drawFramebufferName == 0)
6792 {
6793 return error(GL_INVALID_OPERATION);
6794 }
6795 }
6796 break;
6797 default:
6798 return error(GL_INVALID_ENUM);
6799 }
6800 }
6801
6802 context->setFramebufferDrawBuffers(n, bufs);
6803 }
6804}
6805
6806}
6807
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006808extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006809{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006810 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006811 {
6812 const char *name;
6813 __eglMustCastToProperFunctionPointerType address;
6814 };
6815
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006816 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006817 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006818 bool operator()(const Function &a, const Function &b) const
6819 {
6820 return strcmp(a.name, b.name) < 0;
6821 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006822 };
6823
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006824 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6825 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6826 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006827 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006828 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6829
6830 FUNCTION(glActiveTexture),
6831 FUNCTION(glAttachShader),
6832 FUNCTION(glBeginQuery),
6833 FUNCTION(glBeginQueryEXT),
6834 FUNCTION(glBeginTransformFeedback),
6835 FUNCTION(glBindAttribLocation),
6836 FUNCTION(glBindBuffer),
6837 FUNCTION(glBindBufferBase),
6838 FUNCTION(glBindBufferRange),
6839 FUNCTION(glBindFramebuffer),
6840 FUNCTION(glBindFramebufferOES),
6841 FUNCTION(glBindRenderbuffer),
6842 FUNCTION(glBindRenderbufferOES),
6843 FUNCTION(glBindSampler),
6844 FUNCTION(glBindTexture),
6845 FUNCTION(glBindTransformFeedback),
6846 FUNCTION(glBindVertexArray),
6847 FUNCTION(glBlendColor),
6848 FUNCTION(glBlendEquation),
6849 FUNCTION(glBlendEquationSeparate),
6850 FUNCTION(glBlendFunc),
6851 FUNCTION(glBlendFuncSeparate),
6852 FUNCTION(glBlitFramebuffer),
6853 FUNCTION(glBlitFramebufferANGLE),
6854 FUNCTION(glBufferData),
6855 FUNCTION(glBufferSubData),
6856 FUNCTION(glCheckFramebufferStatus),
6857 FUNCTION(glCheckFramebufferStatusOES),
6858 FUNCTION(glClear),
6859 FUNCTION(glClearBufferfi),
6860 FUNCTION(glClearBufferfv),
6861 FUNCTION(glClearBufferiv),
6862 FUNCTION(glClearBufferuiv),
6863 FUNCTION(glClearColor),
6864 FUNCTION(glClearDepthf),
6865 FUNCTION(glClearStencil),
6866 FUNCTION(glClientWaitSync),
6867 FUNCTION(glColorMask),
6868 FUNCTION(glCompileShader),
6869 FUNCTION(glCompressedTexImage2D),
6870 FUNCTION(glCompressedTexImage3D),
6871 FUNCTION(glCompressedTexSubImage2D),
6872 FUNCTION(glCompressedTexSubImage3D),
6873 FUNCTION(glCopyBufferSubData),
6874 FUNCTION(glCopyTexImage2D),
6875 FUNCTION(glCopyTexSubImage2D),
6876 FUNCTION(glCopyTexSubImage3D),
6877 FUNCTION(glCreateProgram),
6878 FUNCTION(glCreateShader),
6879 FUNCTION(glCullFace),
6880 FUNCTION(glDeleteBuffers),
6881 FUNCTION(glDeleteFencesNV),
6882 FUNCTION(glDeleteFramebuffers),
6883 FUNCTION(glDeleteFramebuffersOES),
6884 FUNCTION(glDeleteProgram),
6885 FUNCTION(glDeleteQueries),
6886 FUNCTION(glDeleteQueriesEXT),
6887 FUNCTION(glDeleteRenderbuffers),
6888 FUNCTION(glDeleteRenderbuffersOES),
6889 FUNCTION(glDeleteSamplers),
6890 FUNCTION(glDeleteShader),
6891 FUNCTION(glDeleteSync),
6892 FUNCTION(glDeleteTextures),
6893 FUNCTION(glDeleteTransformFeedbacks),
6894 FUNCTION(glDeleteVertexArrays),
6895 FUNCTION(glDepthFunc),
6896 FUNCTION(glDepthMask),
6897 FUNCTION(glDepthRangef),
6898 FUNCTION(glDetachShader),
6899 FUNCTION(glDisable),
6900 FUNCTION(glDisableVertexAttribArray),
6901 FUNCTION(glDrawArrays),
6902 FUNCTION(glDrawArraysInstanced),
6903 FUNCTION(glDrawBuffers),
6904 FUNCTION(glDrawBuffersEXT),
6905 FUNCTION(glDrawElements),
6906 FUNCTION(glDrawElementsInstanced),
6907 FUNCTION(glDrawRangeElements),
6908 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6909 FUNCTION(glEGLImageTargetTexture2DOES),
6910 FUNCTION(glEnable),
6911 FUNCTION(glEnableVertexAttribArray),
6912 FUNCTION(glEndQuery),
6913 FUNCTION(glEndQueryEXT),
6914 FUNCTION(glEndTransformFeedback),
6915 FUNCTION(glFenceSync),
6916 FUNCTION(glFinish),
6917 FUNCTION(glFinishFenceNV),
6918 FUNCTION(glFlush),
6919 FUNCTION(glFlushMappedBufferRange),
6920 FUNCTION(glFramebufferRenderbuffer),
6921 FUNCTION(glFramebufferRenderbufferOES),
6922 FUNCTION(glFramebufferTexture2D),
6923 FUNCTION(glFramebufferTexture2DOES),
6924 FUNCTION(glFramebufferTextureLayer),
6925 FUNCTION(glFrontFace),
6926 FUNCTION(glGenBuffers),
6927 FUNCTION(glGenFencesNV),
6928 FUNCTION(glGenFramebuffers),
6929 FUNCTION(glGenFramebuffersOES),
6930 FUNCTION(glGenQueries),
6931 FUNCTION(glGenQueriesEXT),
6932 FUNCTION(glGenRenderbuffers),
6933 FUNCTION(glGenRenderbuffersOES),
6934 FUNCTION(glGenSamplers),
6935 FUNCTION(glGenTextures),
6936 FUNCTION(glGenTransformFeedbacks),
6937 FUNCTION(glGenVertexArrays),
6938 FUNCTION(glGenerateMipmap),
6939 FUNCTION(glGenerateMipmapOES),
6940 FUNCTION(glGetActiveAttrib),
6941 FUNCTION(glGetActiveUniform),
6942 FUNCTION(glGetActiveUniformBlockName),
6943 FUNCTION(glGetActiveUniformBlockiv),
6944 FUNCTION(glGetActiveUniformsiv),
6945 FUNCTION(glGetAttachedShaders),
6946 FUNCTION(glGetAttribLocation),
6947 FUNCTION(glGetBooleanv),
6948 FUNCTION(glGetBufferParameteri64v),
6949 FUNCTION(glGetBufferParameteriv),
6950 FUNCTION(glGetBufferPointerv),
6951 FUNCTION(glGetError),
6952 FUNCTION(glGetFenceivNV),
6953 FUNCTION(glGetFloatv),
6954 FUNCTION(glGetFragDataLocation),
6955 FUNCTION(glGetFramebufferAttachmentParameteriv),
6956 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6957 FUNCTION(glGetGraphicsResetStatusEXT),
6958 FUNCTION(glGetInteger64i_v),
6959 FUNCTION(glGetInteger64v),
6960 FUNCTION(glGetIntegeri_v),
6961 FUNCTION(glGetIntegerv),
6962 FUNCTION(glGetInternalformativ),
6963 FUNCTION(glGetProgramBinary),
6964 FUNCTION(glGetProgramInfoLog),
6965 FUNCTION(glGetProgramiv),
6966 FUNCTION(glGetQueryObjectuiv),
6967 FUNCTION(glGetQueryObjectuivEXT),
6968 FUNCTION(glGetQueryiv),
6969 FUNCTION(glGetQueryivEXT),
6970 FUNCTION(glGetRenderbufferParameteriv),
6971 FUNCTION(glGetRenderbufferParameterivOES),
6972 FUNCTION(glGetSamplerParameterfv),
6973 FUNCTION(glGetSamplerParameteriv),
6974 FUNCTION(glGetShaderInfoLog),
6975 FUNCTION(glGetShaderPrecisionFormat),
6976 FUNCTION(glGetShaderSource),
6977 FUNCTION(glGetShaderiv),
6978 FUNCTION(glGetString),
6979 FUNCTION(glGetStringi),
6980 FUNCTION(glGetSynciv),
6981 FUNCTION(glGetTexParameterfv),
6982 FUNCTION(glGetTexParameteriv),
6983 FUNCTION(glGetTransformFeedbackVarying),
6984 FUNCTION(glGetUniformBlockIndex),
6985 FUNCTION(glGetUniformIndices),
6986 FUNCTION(glGetUniformLocation),
6987 FUNCTION(glGetUniformfv),
6988 FUNCTION(glGetUniformiv),
6989 FUNCTION(glGetUniformuiv),
6990 FUNCTION(glGetVertexAttribIiv),
6991 FUNCTION(glGetVertexAttribIuiv),
6992 FUNCTION(glGetVertexAttribPointerv),
6993 FUNCTION(glGetVertexAttribfv),
6994 FUNCTION(glGetVertexAttribiv),
6995 FUNCTION(glGetnUniformfvEXT),
6996 FUNCTION(glGetnUniformivEXT),
6997 FUNCTION(glHint),
6998 FUNCTION(glInvalidateFramebuffer),
6999 FUNCTION(glInvalidateSubFramebuffer),
7000 FUNCTION(glIsBuffer),
7001 FUNCTION(glIsEnabled),
7002 FUNCTION(glIsFenceNV),
7003 FUNCTION(glIsFramebuffer),
7004 FUNCTION(glIsFramebufferOES),
7005 FUNCTION(glIsProgram),
7006 FUNCTION(glIsQuery),
7007 FUNCTION(glIsQueryEXT),
7008 FUNCTION(glIsRenderbuffer),
7009 FUNCTION(glIsRenderbufferOES),
7010 FUNCTION(glIsSampler),
7011 FUNCTION(glIsShader),
7012 FUNCTION(glIsSync),
7013 FUNCTION(glIsTexture),
7014 FUNCTION(glIsTransformFeedback),
7015 FUNCTION(glIsVertexArray),
7016 FUNCTION(glLineWidth),
7017 FUNCTION(glLinkProgram),
7018 FUNCTION(glMapBufferRange),
7019 FUNCTION(glPauseTransformFeedback),
7020 FUNCTION(glPixelStorei),
7021 FUNCTION(glPolygonOffset),
7022 FUNCTION(glProgramBinary),
7023 FUNCTION(glProgramParameteri),
7024 FUNCTION(glReadBuffer),
7025 FUNCTION(glReadPixels),
7026 FUNCTION(glReadnPixelsEXT),
7027 FUNCTION(glReleaseShaderCompiler),
7028 FUNCTION(glRenderbufferStorage),
7029 FUNCTION(glRenderbufferStorageMultisample),
7030 FUNCTION(glRenderbufferStorageMultisampleANGLE),
7031 FUNCTION(glRenderbufferStorageOES),
7032 FUNCTION(glResumeTransformFeedback),
7033 FUNCTION(glSampleCoverage),
7034 FUNCTION(glSamplerParameterf),
7035 FUNCTION(glSamplerParameterfv),
7036 FUNCTION(glSamplerParameteri),
7037 FUNCTION(glSamplerParameteriv),
7038 FUNCTION(glScissor),
7039 FUNCTION(glSetFenceNV),
7040 FUNCTION(glShaderBinary),
7041 FUNCTION(glShaderSource),
7042 FUNCTION(glStencilFunc),
7043 FUNCTION(glStencilFuncSeparate),
7044 FUNCTION(glStencilMask),
7045 FUNCTION(glStencilMaskSeparate),
7046 FUNCTION(glStencilOp),
7047 FUNCTION(glStencilOpSeparate),
7048 FUNCTION(glTestFenceNV),
7049 FUNCTION(glTexImage2D),
7050 FUNCTION(glTexImage3D),
7051 FUNCTION(glTexImage3DOES),
7052 FUNCTION(glTexParameterf),
7053 FUNCTION(glTexParameterfv),
7054 FUNCTION(glTexParameteri),
7055 FUNCTION(glTexParameteriv),
7056 FUNCTION(glTexStorage2D),
7057 FUNCTION(glTexStorage3D),
7058 FUNCTION(glTexSubImage2D),
7059 FUNCTION(glTexSubImage3D),
7060 FUNCTION(glTransformFeedbackVaryings),
7061 FUNCTION(glUniform1f),
7062 FUNCTION(glUniform1fv),
7063 FUNCTION(glUniform1i),
7064 FUNCTION(glUniform1iv),
7065 FUNCTION(glUniform1ui),
7066 FUNCTION(glUniform1uiv),
7067 FUNCTION(glUniform2f),
7068 FUNCTION(glUniform2fv),
7069 FUNCTION(glUniform2i),
7070 FUNCTION(glUniform2iv),
7071 FUNCTION(glUniform2ui),
7072 FUNCTION(glUniform2uiv),
7073 FUNCTION(glUniform3f),
7074 FUNCTION(glUniform3fv),
7075 FUNCTION(glUniform3i),
7076 FUNCTION(glUniform3iv),
7077 FUNCTION(glUniform3ui),
7078 FUNCTION(glUniform3uiv),
7079 FUNCTION(glUniform4f),
7080 FUNCTION(glUniform4fv),
7081 FUNCTION(glUniform4i),
7082 FUNCTION(glUniform4iv),
7083 FUNCTION(glUniform4ui),
7084 FUNCTION(glUniform4uiv),
7085 FUNCTION(glUniformBlockBinding),
7086 FUNCTION(glUniformMatrix2fv),
7087 FUNCTION(glUniformMatrix2x3fv),
7088 FUNCTION(glUniformMatrix2x4fv),
7089 FUNCTION(glUniformMatrix3fv),
7090 FUNCTION(glUniformMatrix3x2fv),
7091 FUNCTION(glUniformMatrix3x4fv),
7092 FUNCTION(glUniformMatrix4fv),
7093 FUNCTION(glUniformMatrix4x2fv),
7094 FUNCTION(glUniformMatrix4x3fv),
7095 FUNCTION(glUnmapBuffer),
7096 FUNCTION(glUseProgram),
7097 FUNCTION(glValidateProgram),
7098 FUNCTION(glVertexAttrib1f),
7099 FUNCTION(glVertexAttrib1fv),
7100 FUNCTION(glVertexAttrib2f),
7101 FUNCTION(glVertexAttrib2fv),
7102 FUNCTION(glVertexAttrib3f),
7103 FUNCTION(glVertexAttrib3fv),
7104 FUNCTION(glVertexAttrib4f),
7105 FUNCTION(glVertexAttrib4fv),
7106 FUNCTION(glVertexAttribDivisor),
7107 FUNCTION(glVertexAttribI4i),
7108 FUNCTION(glVertexAttribI4iv),
7109 FUNCTION(glVertexAttribI4ui),
7110 FUNCTION(glVertexAttribI4uiv),
7111 FUNCTION(glVertexAttribIPointer),
7112 FUNCTION(glVertexAttribPointer),
7113 FUNCTION(glViewport),
7114 FUNCTION(glWaitSync),
7115
7116 #undef FUNCTION
7117 };
7118
7119 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
7120 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
7121
7122 Function needle;
7123 needle.name = procname;
7124
7125 if(procname && strncmp("gl", procname, 2) == 0)
7126 {
7127 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
7128 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04007129 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01007130 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04007131 }
7132 }
7133
7134 return nullptr;
7135}