blob: 8fb198f61c580785a4e7a85ead2540d52598af38 [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 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400928 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500929 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 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400980 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500981 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400982 // TODO: Convert to the smallest format that fits all components.
983 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
984
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500985 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
986 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400987 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
988 {
989 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
990 }
991 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
992 {
993 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
994 }
995 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
996 {
997 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
998 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500999 else
1000 {
1001 UNIMPLEMENTED();
1002
1003 return error(GL_INVALID_OPERATION);
1004 }
1005 }
1006
Nicolas Capens8f215a42018-02-02 13:25:53 -05001007 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001008 {
1009 return;
1010 }
1011
Alexis Hetu46768622018-01-16 22:09:28 -05001012 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001013 {
Alexis Hetu46768622018-01-16 22:09:28 -05001014 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001015
1016 if(!texture)
1017 {
1018 return error(GL_INVALID_OPERATION);
1019 }
1020
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001021 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001022 }
1023 else if(es2::IsCubemapTextureTarget(target))
1024 {
1025 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1026
1027 if(!texture)
1028 {
1029 return error(GL_INVALID_OPERATION);
1030 }
1031
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001032 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001033 }
1034 else UNREACHABLE(target);
1035 }
1036}
1037
1038void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1039{
1040 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1041 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1042 target, level, xoffset, yoffset, x, y, width, height);
1043
1044 if(!es2::IsTextureTarget(target))
1045 {
1046 return error(GL_INVALID_ENUM);
1047 }
1048
1049 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1050 {
1051 return error(GL_INVALID_VALUE);
1052 }
1053
1054 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1055 {
1056 return error(GL_INVALID_VALUE);
1057 }
1058
1059 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1060 {
1061 return error(GL_INVALID_VALUE);
1062 }
1063
Nicolas Capens0bac2852016-05-07 06:09:58 -04001064 es2::Context *context = es2::getContext();
1065
1066 if(context)
1067 {
1068 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1069
1070 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1071 {
1072 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1073 }
1074
1075 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1076
1077 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1078 {
1079 return error(GL_INVALID_OPERATION);
1080 }
1081
1082 es2::Texture *texture = nullptr;
1083
Alexis Hetu46768622018-01-16 22:09:28 -05001084 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001085 {
Alexis Hetu46768622018-01-16 22:09:28 -05001086 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001087 }
1088 else if(es2::IsCubemapTextureTarget(target))
1089 {
1090 texture = context->getTextureCubeMap();
1091 }
1092 else UNREACHABLE(target);
1093
Nicolas Capensd2faaa92017-12-04 11:15:51 -05001094 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 -05001095 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001096 {
1097 return error(validationError);
1098 }
1099
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001100 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001101 }
1102}
1103
1104GLuint CreateProgram(void)
1105{
1106 TRACE("()");
1107
1108 es2::Context *context = es2::getContext();
1109
1110 if(context)
1111 {
1112 return context->createProgram();
1113 }
1114
1115 return 0;
1116}
1117
1118GLuint CreateShader(GLenum type)
1119{
1120 TRACE("(GLenum type = 0x%X)", type);
1121
1122 es2::Context *context = es2::getContext();
1123
1124 if(context)
1125 {
1126 switch(type)
1127 {
1128 case GL_FRAGMENT_SHADER:
1129 case GL_VERTEX_SHADER:
1130 return context->createShader(type);
1131 default:
1132 return error(GL_INVALID_ENUM, 0);
1133 }
1134 }
1135
1136 return 0;
1137}
1138
1139void CullFace(GLenum mode)
1140{
1141 TRACE("(GLenum mode = 0x%X)", mode);
1142
1143 switch(mode)
1144 {
1145 case GL_FRONT:
1146 case GL_BACK:
1147 case GL_FRONT_AND_BACK:
1148 {
1149 es2::Context *context = es2::getContext();
1150
1151 if(context)
1152 {
1153 context->setCullMode(mode);
1154 }
1155 }
1156 break;
1157 default:
1158 return error(GL_INVALID_ENUM);
1159 }
1160}
1161
1162void DeleteBuffers(GLsizei n, const GLuint* buffers)
1163{
1164 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1165
1166 if(n < 0)
1167 {
1168 return error(GL_INVALID_VALUE);
1169 }
1170
1171 es2::Context *context = es2::getContext();
1172
1173 if(context)
1174 {
1175 for(int i = 0; i < n; i++)
1176 {
1177 context->deleteBuffer(buffers[i]);
1178 }
1179 }
1180}
1181
1182void DeleteFencesNV(GLsizei n, const GLuint* fences)
1183{
1184 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1185
1186 if(n < 0)
1187 {
1188 return error(GL_INVALID_VALUE);
1189 }
1190
1191 es2::Context *context = es2::getContext();
1192
1193 if(context)
1194 {
1195 for(int i = 0; i < n; i++)
1196 {
1197 context->deleteFence(fences[i]);
1198 }
1199 }
1200}
1201
1202void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1203{
1204 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1205
1206 if(n < 0)
1207 {
1208 return error(GL_INVALID_VALUE);
1209 }
1210
1211 es2::Context *context = es2::getContext();
1212
1213 if(context)
1214 {
1215 for(int i = 0; i < n; i++)
1216 {
1217 if(framebuffers[i] != 0)
1218 {
1219 context->deleteFramebuffer(framebuffers[i]);
1220 }
1221 }
1222 }
1223}
1224
1225void DeleteProgram(GLuint program)
1226{
1227 TRACE("(GLuint program = %d)", program);
1228
1229 if(program == 0)
1230 {
1231 return;
1232 }
1233
1234 es2::Context *context = es2::getContext();
1235
1236 if(context)
1237 {
1238 if(!context->getProgram(program))
1239 {
1240 if(context->getShader(program))
1241 {
1242 return error(GL_INVALID_OPERATION);
1243 }
1244 else
1245 {
1246 return error(GL_INVALID_VALUE);
1247 }
1248 }
1249
1250 context->deleteProgram(program);
1251 }
1252}
1253
1254void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1255{
1256 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1257
1258 if(n < 0)
1259 {
1260 return error(GL_INVALID_VALUE);
1261 }
1262
1263 es2::Context *context = es2::getContext();
1264
1265 if(context)
1266 {
1267 for(int i = 0; i < n; i++)
1268 {
1269 context->deleteQuery(ids[i]);
1270 }
1271 }
1272}
1273
1274void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1275{
1276 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1277
1278 if(n < 0)
1279 {
1280 return error(GL_INVALID_VALUE);
1281 }
1282
1283 es2::Context *context = es2::getContext();
1284
1285 if(context)
1286 {
1287 for(int i = 0; i < n; i++)
1288 {
1289 context->deleteRenderbuffer(renderbuffers[i]);
1290 }
1291 }
1292}
1293
1294void DeleteShader(GLuint shader)
1295{
1296 TRACE("(GLuint shader = %d)", shader);
1297
1298 if(shader == 0)
1299 {
1300 return;
1301 }
1302
1303 es2::Context *context = es2::getContext();
1304
1305 if(context)
1306 {
1307 if(!context->getShader(shader))
1308 {
1309 if(context->getProgram(shader))
1310 {
1311 return error(GL_INVALID_OPERATION);
1312 }
1313 else
1314 {
1315 return error(GL_INVALID_VALUE);
1316 }
1317 }
1318
1319 context->deleteShader(shader);
1320 }
1321}
1322
1323void DeleteTextures(GLsizei n, const GLuint* textures)
1324{
1325 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1326
1327 if(n < 0)
1328 {
1329 return error(GL_INVALID_VALUE);
1330 }
1331
1332 es2::Context *context = es2::getContext();
1333
1334 if(context)
1335 {
1336 for(int i = 0; i < n; i++)
1337 {
1338 if(textures[i] != 0)
1339 {
1340 context->deleteTexture(textures[i]);
1341 }
1342 }
1343 }
1344}
1345
1346void DepthFunc(GLenum func)
1347{
1348 TRACE("(GLenum func = 0x%X)", func);
1349
1350 switch(func)
1351 {
1352 case GL_NEVER:
1353 case GL_ALWAYS:
1354 case GL_LESS:
1355 case GL_LEQUAL:
1356 case GL_EQUAL:
1357 case GL_GREATER:
1358 case GL_GEQUAL:
1359 case GL_NOTEQUAL:
1360 break;
1361 default:
1362 return error(GL_INVALID_ENUM);
1363 }
1364
1365 es2::Context *context = es2::getContext();
1366
1367 if(context)
1368 {
1369 context->setDepthFunc(func);
1370 }
1371}
1372
1373void DepthMask(GLboolean flag)
1374{
1375 TRACE("(GLboolean flag = %d)", flag);
1376
1377 es2::Context *context = es2::getContext();
1378
1379 if(context)
1380 {
1381 context->setDepthMask(flag != GL_FALSE);
1382 }
1383}
1384
1385void DepthRangef(GLclampf zNear, GLclampf zFar)
1386{
1387 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1388
1389 es2::Context *context = es2::getContext();
1390
1391 if(context)
1392 {
1393 context->setDepthRange(zNear, zFar);
1394 }
1395}
1396
1397void DetachShader(GLuint program, GLuint shader)
1398{
1399 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1400
1401 es2::Context *context = es2::getContext();
1402
1403 if(context)
1404 {
1405
1406 es2::Program *programObject = context->getProgram(program);
1407 es2::Shader *shaderObject = context->getShader(shader);
1408
1409 if(!programObject)
1410 {
1411 es2::Shader *shaderByProgramHandle;
1412 shaderByProgramHandle = context->getShader(program);
1413 if(!shaderByProgramHandle)
1414 {
1415 return error(GL_INVALID_VALUE);
1416 }
1417 else
1418 {
1419 return error(GL_INVALID_OPERATION);
1420 }
1421 }
1422
1423 if(!shaderObject)
1424 {
1425 es2::Program *programByShaderHandle = context->getProgram(shader);
1426 if(!programByShaderHandle)
1427 {
1428 return error(GL_INVALID_VALUE);
1429 }
1430 else
1431 {
1432 return error(GL_INVALID_OPERATION);
1433 }
1434 }
1435
1436 if(!programObject->detachShader(shaderObject))
1437 {
1438 return error(GL_INVALID_OPERATION);
1439 }
1440 }
1441}
1442
1443void Disable(GLenum cap)
1444{
1445 TRACE("(GLenum cap = 0x%X)", cap);
1446
1447 es2::Context *context = es2::getContext();
1448
1449 if(context)
1450 {
1451 switch(cap)
1452 {
1453 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1454 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1455 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1456 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1457 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1458 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1459 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1460 case GL_BLEND: context->setBlendEnabled(false); break;
1461 case GL_DITHER: context->setDitherEnabled(false); break;
1462 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1463 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1464 default:
1465 return error(GL_INVALID_ENUM);
1466 }
1467 }
1468}
1469
1470void DisableVertexAttribArray(GLuint index)
1471{
1472 TRACE("(GLuint index = %d)", index);
1473
1474 if(index >= es2::MAX_VERTEX_ATTRIBS)
1475 {
1476 return error(GL_INVALID_VALUE);
1477 }
1478
1479 es2::Context *context = es2::getContext();
1480
1481 if(context)
1482 {
1483 context->setVertexAttribArrayEnabled(index, false);
1484 }
1485}
1486
1487void DrawArrays(GLenum mode, GLint first, GLsizei count)
1488{
1489 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1490
1491 switch(mode)
1492 {
1493 case GL_POINTS:
1494 case GL_LINES:
1495 case GL_LINE_LOOP:
1496 case GL_LINE_STRIP:
1497 case GL_TRIANGLES:
1498 case GL_TRIANGLE_FAN:
1499 case GL_TRIANGLE_STRIP:
1500 break;
1501 default:
1502 return error(GL_INVALID_ENUM);
1503 }
1504
1505 if(count < 0 || first < 0)
1506 {
1507 return error(GL_INVALID_VALUE);
1508 }
1509
1510 es2::Context *context = es2::getContext();
1511
1512 if(context)
1513 {
1514 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1515 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1516 {
1517 return error(GL_INVALID_OPERATION);
1518 }
1519
1520 context->drawArrays(mode, first, count);
1521 }
1522}
1523
1524void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1525{
1526 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1527 mode, count, type, indices);
1528
1529 switch(mode)
1530 {
1531 case GL_POINTS:
1532 case GL_LINES:
1533 case GL_LINE_LOOP:
1534 case GL_LINE_STRIP:
1535 case GL_TRIANGLES:
1536 case GL_TRIANGLE_FAN:
1537 case GL_TRIANGLE_STRIP:
1538 break;
1539 default:
1540 return error(GL_INVALID_ENUM);
1541 }
1542
1543 if(count < 0)
1544 {
1545 return error(GL_INVALID_VALUE);
1546 }
1547
1548 es2::Context *context = es2::getContext();
1549
1550 if(context)
1551 {
1552 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1553 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1554 {
1555 return error(GL_INVALID_OPERATION);
1556 }
1557
1558 switch(type)
1559 {
1560 case GL_UNSIGNED_BYTE:
1561 case GL_UNSIGNED_SHORT:
1562 case GL_UNSIGNED_INT:
1563 break;
1564 default:
1565 return error(GL_INVALID_ENUM);
1566 }
1567
1568 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1569 }
1570}
1571
1572void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1573{
1574 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1575 mode, first, count, instanceCount);
1576
1577 switch(mode)
1578 {
1579 case GL_POINTS:
1580 case GL_LINES:
1581 case GL_LINE_LOOP:
1582 case GL_LINE_STRIP:
1583 case GL_TRIANGLES:
1584 case GL_TRIANGLE_FAN:
1585 case GL_TRIANGLE_STRIP:
1586 break;
1587 default:
1588 return error(GL_INVALID_ENUM);
1589 }
1590
1591 if(count < 0 || instanceCount < 0)
1592 {
1593 return error(GL_INVALID_VALUE);
1594 }
1595
1596 es2::Context *context = es2::getContext();
1597
1598 if(context)
1599 {
1600 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1601 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1602 {
1603 return error(GL_INVALID_OPERATION);
1604 }
1605
1606 context->drawArrays(mode, first, count, instanceCount);
1607 }
1608}
1609
1610void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1611{
1612 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1613 mode, count, type, indices, instanceCount);
1614
1615 switch(mode)
1616 {
1617 case GL_POINTS:
1618 case GL_LINES:
1619 case GL_LINE_LOOP:
1620 case GL_LINE_STRIP:
1621 case GL_TRIANGLES:
1622 case GL_TRIANGLE_FAN:
1623 case GL_TRIANGLE_STRIP:
1624 break;
1625 default:
1626 return error(GL_INVALID_ENUM);
1627 }
1628
1629 switch(type)
1630 {
1631 case GL_UNSIGNED_BYTE:
1632 case GL_UNSIGNED_SHORT:
1633 case GL_UNSIGNED_INT:
1634 break;
1635 default:
1636 return error(GL_INVALID_ENUM);
1637 }
1638
1639 if(count < 0 || instanceCount < 0)
1640 {
1641 return error(GL_INVALID_VALUE);
1642 }
1643
1644 es2::Context *context = es2::getContext();
1645
1646 if(context)
1647 {
1648 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1649 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1650 {
1651 return error(GL_INVALID_OPERATION);
1652 }
1653
1654 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1655 }
1656}
1657
1658void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1659{
1660 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1661
1662 es2::Context *context = es2::getContext();
1663
1664 if(context)
1665 {
1666 if(index >= es2::MAX_VERTEX_ATTRIBS)
1667 {
1668 return error(GL_INVALID_VALUE);
1669 }
1670
1671 context->setVertexAttribDivisor(index, divisor);
1672 }
1673}
1674
1675void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1676{
1677 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1678 mode, first, count, instanceCount);
1679
1680 switch(mode)
1681 {
1682 case GL_POINTS:
1683 case GL_LINES:
1684 case GL_LINE_LOOP:
1685 case GL_LINE_STRIP:
1686 case GL_TRIANGLES:
1687 case GL_TRIANGLE_FAN:
1688 case GL_TRIANGLE_STRIP:
1689 break;
1690 default:
1691 return error(GL_INVALID_ENUM);
1692 }
1693
1694 if(count < 0 || instanceCount < 0)
1695 {
1696 return error(GL_INVALID_VALUE);
1697 }
1698
1699 es2::Context *context = es2::getContext();
1700
1701 if(context)
1702 {
1703 if(!context->hasZeroDivisor())
1704 {
1705 return error(GL_INVALID_OPERATION);
1706 }
1707
1708 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1709 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1710 {
1711 return error(GL_INVALID_OPERATION);
1712 }
1713
1714 context->drawArrays(mode, first, count, instanceCount);
1715 }
1716}
1717
1718void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1719{
1720 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1721 mode, count, type, indices, instanceCount);
1722
1723 switch(mode)
1724 {
1725 case GL_POINTS:
1726 case GL_LINES:
1727 case GL_LINE_LOOP:
1728 case GL_LINE_STRIP:
1729 case GL_TRIANGLES:
1730 case GL_TRIANGLE_FAN:
1731 case GL_TRIANGLE_STRIP:
1732 break;
1733 default:
1734 return error(GL_INVALID_ENUM);
1735 }
1736
1737 switch(type)
1738 {
1739 case GL_UNSIGNED_BYTE:
1740 case GL_UNSIGNED_SHORT:
1741 case GL_UNSIGNED_INT:
1742 break;
1743 default:
1744 return error(GL_INVALID_ENUM);
1745 }
1746
1747 if(count < 0 || instanceCount < 0)
1748 {
1749 return error(GL_INVALID_VALUE);
1750 }
1751
1752 es2::Context *context = es2::getContext();
1753
1754 if(context)
1755 {
1756 if(!context->hasZeroDivisor())
1757 {
1758 return error(GL_INVALID_OPERATION);
1759 }
1760
1761 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1762 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1763 {
1764 return error(GL_INVALID_OPERATION);
1765 }
1766
1767 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1768 }
1769}
1770
1771void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1772{
1773 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1774
1775 es2::Context *context = es2::getContext();
1776
1777 if(context)
1778 {
1779 if(index >= MAX_VERTEX_ATTRIBS)
1780 {
1781 return error(GL_INVALID_VALUE);
1782 }
1783
1784 context->setVertexAttribDivisor(index, divisor);
1785 }
1786}
1787
1788void Enable(GLenum cap)
1789{
1790 TRACE("(GLenum cap = 0x%X)", cap);
1791
1792 es2::Context *context = es2::getContext();
1793
1794 if(context)
1795 {
1796 switch(cap)
1797 {
1798 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1799 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1800 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1801 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1802 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1803 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1804 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1805 case GL_BLEND: context->setBlendEnabled(true); break;
1806 case GL_DITHER: context->setDitherEnabled(true); break;
1807 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1808 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1809 default:
1810 return error(GL_INVALID_ENUM);
1811 }
1812 }
1813}
1814
1815void EnableVertexAttribArray(GLuint index)
1816{
1817 TRACE("(GLuint index = %d)", index);
1818
1819 if(index >= es2::MAX_VERTEX_ATTRIBS)
1820 {
1821 return error(GL_INVALID_VALUE);
1822 }
1823
1824 es2::Context *context = es2::getContext();
1825
1826 if(context)
1827 {
1828 context->setVertexAttribArrayEnabled(index, true);
1829 }
1830}
1831
1832void EndQueryEXT(GLenum target)
1833{
1834 TRACE("GLenum target = 0x%X)", target);
1835
1836 switch(target)
1837 {
1838 case GL_ANY_SAMPLES_PASSED_EXT:
1839 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1840 break;
1841 default:
1842 return error(GL_INVALID_ENUM);
1843 }
1844
1845 es2::Context *context = es2::getContext();
1846
1847 if(context)
1848 {
1849 context->endQuery(target);
1850 }
1851}
1852
1853void FinishFenceNV(GLuint fence)
1854{
1855 TRACE("(GLuint fence = %d)", fence);
1856
1857 es2::Context *context = es2::getContext();
1858
1859 if(context)
1860 {
1861 es2::Fence *fenceObject = context->getFence(fence);
1862
1863 if(!fenceObject)
1864 {
1865 return error(GL_INVALID_OPERATION);
1866 }
1867
1868 fenceObject->finishFence();
1869 }
1870}
1871
1872void Finish(void)
1873{
1874 TRACE("()");
1875
1876 es2::Context *context = es2::getContext();
1877
1878 if(context)
1879 {
1880 context->finish();
1881 }
1882}
1883
1884void Flush(void)
1885{
1886 TRACE("()");
1887
1888 es2::Context *context = es2::getContext();
1889
1890 if(context)
1891 {
1892 context->flush();
1893 }
1894}
1895
1896void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1897{
1898 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1899 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1900
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001901 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001902 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1903 {
1904 return error(GL_INVALID_ENUM);
1905 }
1906
1907 es2::Context *context = es2::getContext();
1908
1909 if(context)
1910 {
1911 es2::Framebuffer *framebuffer = nullptr;
1912 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001913 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001914 {
1915 framebuffer = context->getReadFramebuffer();
1916 framebufferName = context->getReadFramebufferName();
1917 }
1918 else
1919 {
1920 framebuffer = context->getDrawFramebuffer();
1921 framebufferName = context->getDrawFramebufferName();
1922 }
1923
1924 if(!framebuffer || framebufferName == 0)
1925 {
1926 return error(GL_INVALID_OPERATION);
1927 }
1928
1929 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1930 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1931 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1932 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1933 if(renderbuffer != 0)
1934 {
1935 if(!context->getRenderbuffer(renderbuffer))
1936 {
1937 return error(GL_INVALID_OPERATION);
1938 }
1939 }
1940
1941 GLint clientVersion = context->getClientVersion();
1942
1943 switch(attachment)
1944 {
1945 case GL_COLOR_ATTACHMENT0:
1946 case GL_COLOR_ATTACHMENT1:
1947 case GL_COLOR_ATTACHMENT2:
1948 case GL_COLOR_ATTACHMENT3:
1949 case GL_COLOR_ATTACHMENT4:
1950 case GL_COLOR_ATTACHMENT5:
1951 case GL_COLOR_ATTACHMENT6:
1952 case GL_COLOR_ATTACHMENT7:
1953 case GL_COLOR_ATTACHMENT8:
1954 case GL_COLOR_ATTACHMENT9:
1955 case GL_COLOR_ATTACHMENT10:
1956 case GL_COLOR_ATTACHMENT11:
1957 case GL_COLOR_ATTACHMENT12:
1958 case GL_COLOR_ATTACHMENT13:
1959 case GL_COLOR_ATTACHMENT14:
1960 case GL_COLOR_ATTACHMENT15:
1961 case GL_COLOR_ATTACHMENT16:
1962 case GL_COLOR_ATTACHMENT17:
1963 case GL_COLOR_ATTACHMENT18:
1964 case GL_COLOR_ATTACHMENT19:
1965 case GL_COLOR_ATTACHMENT20:
1966 case GL_COLOR_ATTACHMENT21:
1967 case GL_COLOR_ATTACHMENT22:
1968 case GL_COLOR_ATTACHMENT23:
1969 case GL_COLOR_ATTACHMENT24:
1970 case GL_COLOR_ATTACHMENT25:
1971 case GL_COLOR_ATTACHMENT26:
1972 case GL_COLOR_ATTACHMENT27:
1973 case GL_COLOR_ATTACHMENT28:
1974 case GL_COLOR_ATTACHMENT29:
1975 case GL_COLOR_ATTACHMENT30:
1976 case GL_COLOR_ATTACHMENT31:
1977 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1978 {
1979 return error(GL_INVALID_ENUM);
1980 }
1981 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1982 break;
1983 case GL_DEPTH_ATTACHMENT:
1984 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1985 break;
1986 case GL_STENCIL_ATTACHMENT:
1987 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1988 break;
1989 case GL_DEPTH_STENCIL_ATTACHMENT:
1990 if(clientVersion >= 3)
1991 {
1992 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1993 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1994 break;
1995 }
1996 else return error(GL_INVALID_ENUM);
1997 default:
1998 return error(GL_INVALID_ENUM);
1999 }
2000 }
2001}
2002
2003void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
2004{
2005 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
2006 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
2007
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002008 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002009 {
2010 return error(GL_INVALID_ENUM);
2011 }
2012
2013 es2::Context *context = es2::getContext();
2014
2015 if(context)
2016 {
Nicolas Capensd5401e22017-03-16 17:32:43 -04002017 GLint clientVersion = context->getClientVersion();
2018
Nicolas Capens0bac2852016-05-07 06:09:58 -04002019 if(texture == 0)
2020 {
2021 textarget = GL_NONE;
2022 }
2023 else
2024 {
2025 es2::Texture *tex = context->getTexture(texture);
2026
2027 if(!tex)
2028 {
2029 return error(GL_INVALID_OPERATION);
2030 }
2031
2032 switch(textarget)
2033 {
2034 case GL_TEXTURE_2D:
2035 if(tex->getTarget() != GL_TEXTURE_2D)
2036 {
2037 return error(GL_INVALID_OPERATION);
2038 }
2039 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002040 case GL_TEXTURE_RECTANGLE_ARB:
2041 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
2042 {
2043 return error(GL_INVALID_OPERATION);
2044 }
2045 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002046 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2047 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2048 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2049 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2050 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2051 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2052 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2053 {
2054 return error(GL_INVALID_OPERATION);
2055 }
2056 break;
2057 default:
2058 return error(GL_INVALID_ENUM);
2059 }
2060
Alexis Hetu0988fb82018-02-02 17:23:48 -05002061 if((level != 0) && ((clientVersion < 3) || (textarget == GL_TEXTURE_RECTANGLE_ARB)))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002062 {
2063 return error(GL_INVALID_VALUE);
2064 }
2065
2066 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2067 {
2068 return error(GL_INVALID_VALUE);
2069 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002070
2071 if(tex->isCompressed(textarget, level))
2072 {
2073 return error(GL_INVALID_OPERATION);
2074 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002075 }
2076
2077 es2::Framebuffer *framebuffer = nullptr;
2078 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002079 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002080 {
2081 framebuffer = context->getReadFramebuffer();
2082 framebufferName = context->getReadFramebufferName();
2083 }
2084 else
2085 {
2086 framebuffer = context->getDrawFramebuffer();
2087 framebufferName = context->getDrawFramebufferName();
2088 }
2089
2090 if(framebufferName == 0 || !framebuffer)
2091 {
2092 return error(GL_INVALID_OPERATION);
2093 }
2094
2095 switch(attachment)
2096 {
2097 case GL_COLOR_ATTACHMENT0:
2098 case GL_COLOR_ATTACHMENT1:
2099 case GL_COLOR_ATTACHMENT2:
2100 case GL_COLOR_ATTACHMENT3:
2101 case GL_COLOR_ATTACHMENT4:
2102 case GL_COLOR_ATTACHMENT5:
2103 case GL_COLOR_ATTACHMENT6:
2104 case GL_COLOR_ATTACHMENT7:
2105 case GL_COLOR_ATTACHMENT8:
2106 case GL_COLOR_ATTACHMENT9:
2107 case GL_COLOR_ATTACHMENT10:
2108 case GL_COLOR_ATTACHMENT11:
2109 case GL_COLOR_ATTACHMENT12:
2110 case GL_COLOR_ATTACHMENT13:
2111 case GL_COLOR_ATTACHMENT14:
2112 case GL_COLOR_ATTACHMENT15:
2113 case GL_COLOR_ATTACHMENT16:
2114 case GL_COLOR_ATTACHMENT17:
2115 case GL_COLOR_ATTACHMENT18:
2116 case GL_COLOR_ATTACHMENT19:
2117 case GL_COLOR_ATTACHMENT20:
2118 case GL_COLOR_ATTACHMENT21:
2119 case GL_COLOR_ATTACHMENT22:
2120 case GL_COLOR_ATTACHMENT23:
2121 case GL_COLOR_ATTACHMENT24:
2122 case GL_COLOR_ATTACHMENT25:
2123 case GL_COLOR_ATTACHMENT26:
2124 case GL_COLOR_ATTACHMENT27:
2125 case GL_COLOR_ATTACHMENT28:
2126 case GL_COLOR_ATTACHMENT29:
2127 case GL_COLOR_ATTACHMENT30:
2128 case GL_COLOR_ATTACHMENT31:
2129 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2130 {
2131 return error(GL_INVALID_ENUM);
2132 }
2133 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2134 break;
2135 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2136 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capensd5401e22017-03-16 17:32:43 -04002137 case GL_DEPTH_STENCIL_ATTACHMENT:
2138 if(clientVersion >= 3)
2139 {
2140 framebuffer->setDepthbuffer(textarget, texture, level);
2141 framebuffer->setStencilbuffer(textarget, texture, level);
2142 break;
2143 }
2144 else return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002145 default:
2146 return error(GL_INVALID_ENUM);
2147 }
2148 }
2149}
2150
2151void FrontFace(GLenum mode)
2152{
2153 TRACE("(GLenum mode = 0x%X)", mode);
2154
2155 switch(mode)
2156 {
2157 case GL_CW:
2158 case GL_CCW:
2159 {
2160 es2::Context *context = es2::getContext();
2161
2162 if(context)
2163 {
2164 context->setFrontFace(mode);
2165 }
2166 }
2167 break;
2168 default:
2169 return error(GL_INVALID_ENUM);
2170 }
2171}
2172
2173void GenBuffers(GLsizei n, GLuint* buffers)
2174{
2175 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2176
2177 if(n < 0)
2178 {
2179 return error(GL_INVALID_VALUE);
2180 }
2181
2182 es2::Context *context = es2::getContext();
2183
2184 if(context)
2185 {
2186 for(int i = 0; i < n; i++)
2187 {
2188 buffers[i] = context->createBuffer();
2189 }
2190 }
2191}
2192
2193void GenerateMipmap(GLenum target)
2194{
2195 TRACE("(GLenum target = 0x%X)", target);
2196
2197 es2::Context *context = es2::getContext();
2198
2199 if(context)
2200 {
2201 es2::Texture *texture = nullptr;
2202
2203 GLint clientVersion = context->getClientVersion();
2204
2205 switch(target)
2206 {
2207 case GL_TEXTURE_2D:
2208 texture = context->getTexture2D();
2209 break;
2210 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002211 {
2212 TextureCubeMap *cube = context->getTextureCubeMap();
2213 texture = cube;
2214
2215 if(!cube->isCubeComplete())
2216 {
2217 return error(GL_INVALID_OPERATION);
2218 }
2219 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002220 break;
2221 case GL_TEXTURE_2D_ARRAY:
2222 if(clientVersion < 3)
2223 {
2224 return error(GL_INVALID_ENUM);
2225 }
2226 else
2227 {
2228 texture = context->getTexture2DArray();
2229 }
2230 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002231 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002232 texture = context->getTexture3D();
2233 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002234 case GL_TEXTURE_RECTANGLE_ARB:
2235 texture = context->getTexture2DRect();
2236 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002237 default:
2238 return error(GL_INVALID_ENUM);
2239 }
2240
Nicolas Capense6115342017-12-18 15:58:46 -05002241 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel()), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002242 {
2243 return error(GL_INVALID_OPERATION);
2244 }
2245
Nicolas Capens0bac2852016-05-07 06:09:58 -04002246 texture->generateMipmaps();
2247 }
2248}
2249
2250void GenFencesNV(GLsizei n, GLuint* fences)
2251{
2252 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2253
2254 if(n < 0)
2255 {
2256 return error(GL_INVALID_VALUE);
2257 }
2258
2259 es2::Context *context = es2::getContext();
2260
2261 if(context)
2262 {
2263 for(int i = 0; i < n; i++)
2264 {
2265 fences[i] = context->createFence();
2266 }
2267 }
2268}
2269
2270void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2271{
2272 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2273
2274 if(n < 0)
2275 {
2276 return error(GL_INVALID_VALUE);
2277 }
2278
2279 es2::Context *context = es2::getContext();
2280
2281 if(context)
2282 {
2283 for(int i = 0; i < n; i++)
2284 {
2285 framebuffers[i] = context->createFramebuffer();
2286 }
2287 }
2288}
2289
2290void GenQueriesEXT(GLsizei n, GLuint* ids)
2291{
2292 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2293
2294 if(n < 0)
2295 {
2296 return error(GL_INVALID_VALUE);
2297 }
2298
2299 es2::Context *context = es2::getContext();
2300
2301 if(context)
2302 {
2303 for(int i = 0; i < n; i++)
2304 {
2305 ids[i] = context->createQuery();
2306 }
2307 }
2308}
2309
2310void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2311{
2312 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2313
2314 if(n < 0)
2315 {
2316 return error(GL_INVALID_VALUE);
2317 }
2318
2319 es2::Context *context = es2::getContext();
2320
2321 if(context)
2322 {
2323 for(int i = 0; i < n; i++)
2324 {
2325 renderbuffers[i] = context->createRenderbuffer();
2326 }
2327 }
2328}
2329
2330void GenTextures(GLsizei n, GLuint* textures)
2331{
2332 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2333
2334 if(n < 0)
2335 {
2336 return error(GL_INVALID_VALUE);
2337 }
2338
2339 es2::Context *context = es2::getContext();
2340
2341 if(context)
2342 {
2343 for(int i = 0; i < n; i++)
2344 {
2345 textures[i] = context->createTexture();
2346 }
2347 }
2348}
2349
2350void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2351{
2352 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2353 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2354 program, index, bufsize, length, size, type, name);
2355
2356 if(bufsize < 0)
2357 {
2358 return error(GL_INVALID_VALUE);
2359 }
2360
2361 es2::Context *context = es2::getContext();
2362
2363 if(context)
2364 {
2365 es2::Program *programObject = context->getProgram(program);
2366
2367 if(!programObject)
2368 {
2369 if(context->getShader(program))
2370 {
2371 return error(GL_INVALID_OPERATION);
2372 }
2373 else
2374 {
2375 return error(GL_INVALID_VALUE);
2376 }
2377 }
2378
2379 if(index >= programObject->getActiveAttributeCount())
2380 {
2381 return error(GL_INVALID_VALUE);
2382 }
2383
2384 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2385 }
2386}
2387
2388void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2389{
2390 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2391 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2392 program, index, bufsize, length, size, type, name);
2393
2394 if(bufsize < 0)
2395 {
2396 return error(GL_INVALID_VALUE);
2397 }
2398
2399 es2::Context *context = es2::getContext();
2400
2401 if(context)
2402 {
2403 es2::Program *programObject = context->getProgram(program);
2404
2405 if(!programObject)
2406 {
2407 if(context->getShader(program))
2408 {
2409 return error(GL_INVALID_OPERATION);
2410 }
2411 else
2412 {
2413 return error(GL_INVALID_VALUE);
2414 }
2415 }
2416
2417 if(index >= programObject->getActiveUniformCount())
2418 {
2419 return error(GL_INVALID_VALUE);
2420 }
2421
2422 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2423 }
2424}
2425
2426void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2427{
2428 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2429 program, maxcount, count, shaders);
2430
2431 if(maxcount < 0)
2432 {
2433 return error(GL_INVALID_VALUE);
2434 }
2435
2436 es2::Context *context = es2::getContext();
2437
2438 if(context)
2439 {
2440 es2::Program *programObject = context->getProgram(program);
2441
2442 if(!programObject)
2443 {
2444 if(context->getShader(program))
2445 {
2446 return error(GL_INVALID_OPERATION);
2447 }
2448 else
2449 {
2450 return error(GL_INVALID_VALUE);
2451 }
2452 }
2453
2454 return programObject->getAttachedShaders(maxcount, count, shaders);
2455 }
2456}
2457
2458int GetAttribLocation(GLuint program, const GLchar* name)
2459{
2460 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2461
2462 es2::Context *context = es2::getContext();
2463
2464 if(context)
2465 {
2466
2467 es2::Program *programObject = context->getProgram(program);
2468
2469 if(!programObject)
2470 {
2471 if(context->getShader(program))
2472 {
2473 return error(GL_INVALID_OPERATION, -1);
2474 }
2475 else
2476 {
2477 return error(GL_INVALID_VALUE, -1);
2478 }
2479 }
2480
2481 if(!programObject->isLinked())
2482 {
2483 return error(GL_INVALID_OPERATION, -1);
2484 }
2485
2486 return programObject->getAttributeLocation(name);
2487 }
2488
2489 return -1;
2490}
2491
2492void GetBooleanv(GLenum pname, GLboolean* params)
2493{
2494 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2495
2496 es2::Context *context = es2::getContext();
2497
2498 if(context)
2499 {
2500 if(!(context->getBooleanv(pname, params)))
2501 {
2502 GLenum nativeType;
2503 unsigned int numParams = 0;
2504 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2505 return error(GL_INVALID_ENUM);
2506
2507 if(numParams == 0)
2508 return; // it is known that the pname is valid, but there are no parameters to return
2509
2510 if(nativeType == GL_FLOAT)
2511 {
2512 GLfloat *floatParams = nullptr;
2513 floatParams = new GLfloat[numParams];
2514
2515 context->getFloatv(pname, floatParams);
2516
2517 for(unsigned int i = 0; i < numParams; ++i)
2518 {
2519 if(floatParams[i] == 0.0f)
2520 params[i] = GL_FALSE;
2521 else
2522 params[i] = GL_TRUE;
2523 }
2524
2525 delete [] floatParams;
2526 }
2527 else if(nativeType == GL_INT)
2528 {
2529 GLint *intParams = nullptr;
2530 intParams = new GLint[numParams];
2531
2532 context->getIntegerv(pname, intParams);
2533
2534 for(unsigned int i = 0; i < numParams; ++i)
2535 {
2536 if(intParams[i] == 0)
2537 params[i] = GL_FALSE;
2538 else
2539 params[i] = GL_TRUE;
2540 }
2541
2542 delete [] intParams;
2543 }
2544 }
2545 }
2546}
2547
2548void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2549{
2550 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2551
2552 es2::Context *context = es2::getContext();
2553
2554 if(context)
2555 {
2556 es2::Buffer *buffer;
2557 if(!context->getBuffer(target, &buffer))
2558 {
2559 return error(GL_INVALID_ENUM);
2560 }
2561
2562 if(!buffer)
2563 {
2564 // A null buffer means that "0" is bound to the requested buffer target
2565 return error(GL_INVALID_OPERATION);
2566 }
2567
2568 GLint clientVersion = context->getClientVersion();
2569
2570 switch(pname)
2571 {
2572 case GL_BUFFER_USAGE:
2573 *params = buffer->usage();
2574 break;
2575 case GL_BUFFER_SIZE:
2576 *params = (GLint)buffer->size();
2577 break;
2578 case GL_BUFFER_ACCESS_FLAGS:
2579 if(clientVersion >= 3)
2580 {
2581 *params = buffer->access();
2582 break;
2583 }
2584 else return error(GL_INVALID_ENUM);
2585 case GL_BUFFER_MAPPED:
2586 if(clientVersion >= 3)
2587 {
2588 *params = buffer->isMapped();
2589 break;
2590 }
2591 else return error(GL_INVALID_ENUM);
2592 case GL_BUFFER_MAP_LENGTH:
2593 if(clientVersion >= 3)
2594 {
2595 *params = (GLint)buffer->length();
2596 break;
2597 }
2598 else return error(GL_INVALID_ENUM);
2599 case GL_BUFFER_MAP_OFFSET:
2600 if(clientVersion >= 3)
2601 {
2602 *params = (GLint)buffer->offset();
2603 break;
2604 }
2605 else return error(GL_INVALID_ENUM);
2606 default:
2607 return error(GL_INVALID_ENUM);
2608 }
2609 }
2610}
2611
2612GLenum GetError(void)
2613{
2614 TRACE("()");
2615
2616 es2::Context *context = es2::getContext();
2617
2618 if(context)
2619 {
2620 return context->getError();
2621 }
2622
2623 return GL_NO_ERROR;
2624}
2625
2626void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2627{
2628 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2629
2630 es2::Context *context = es2::getContext();
2631
2632 if(context)
2633 {
2634 es2::Fence *fenceObject = context->getFence(fence);
2635
2636 if(!fenceObject)
2637 {
2638 return error(GL_INVALID_OPERATION);
2639 }
2640
2641 fenceObject->getFenceiv(pname, params);
2642 }
2643}
2644
2645void GetFloatv(GLenum pname, GLfloat* params)
2646{
2647 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2648
2649 es2::Context *context = es2::getContext();
2650
2651 if(context)
2652 {
2653 if(!(context->getFloatv(pname, params)))
2654 {
2655 GLenum nativeType;
2656 unsigned int numParams = 0;
2657 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2658 return error(GL_INVALID_ENUM);
2659
2660 if(numParams == 0)
2661 return; // it is known that the pname is valid, but that there are no parameters to return.
2662
2663 if(nativeType == GL_BOOL)
2664 {
2665 GLboolean *boolParams = nullptr;
2666 boolParams = new GLboolean[numParams];
2667
2668 context->getBooleanv(pname, boolParams);
2669
2670 for(unsigned int i = 0; i < numParams; ++i)
2671 {
2672 if(boolParams[i] == GL_FALSE)
2673 params[i] = 0.0f;
2674 else
2675 params[i] = 1.0f;
2676 }
2677
2678 delete [] boolParams;
2679 }
2680 else if(nativeType == GL_INT)
2681 {
2682 GLint *intParams = nullptr;
2683 intParams = new GLint[numParams];
2684
2685 context->getIntegerv(pname, intParams);
2686
2687 for(unsigned int i = 0; i < numParams; ++i)
2688 {
2689 params[i] = (GLfloat)intParams[i];
2690 }
2691
2692 delete [] intParams;
2693 }
2694 }
2695 }
2696}
2697
2698void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2699{
2700 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2701 target, attachment, pname, params);
2702
2703 es2::Context *context = es2::getContext();
2704
2705 if(context)
2706 {
2707 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2708 {
2709 return error(GL_INVALID_ENUM);
2710 }
2711
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002712 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002713
Nicolas Capens0bac2852016-05-07 06:09:58 -04002714 if(target == GL_READ_FRAMEBUFFER)
2715 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002716 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002717 }
2718 else
2719 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002720 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002721 }
2722
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002723 GLint clientVersion = context->getClientVersion();
2724
2725 if(framebufferName == 0) // Default framebuffer.
2726 {
2727 if(clientVersion < 3)
2728 {
2729 return error(GL_INVALID_OPERATION);
2730 }
2731 }
2732
Nicolas Capens0bac2852016-05-07 06:09:58 -04002733 switch(attachment)
2734 {
2735 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002736 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002737 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002738 if(clientVersion < 3)
2739 {
2740 return error(GL_INVALID_ENUM);
2741 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002742
2743 if(framebufferName != 0)
2744 {
2745 return error(GL_INVALID_OPERATION);
2746 }
2747 break;
2748 case GL_DEPTH_ATTACHMENT:
2749 case GL_STENCIL_ATTACHMENT:
2750 if(framebufferName == 0)
2751 {
2752 return error(GL_INVALID_OPERATION);
2753 }
2754 break;
2755 case GL_DEPTH_STENCIL_ATTACHMENT:
2756 if(clientVersion < 3)
2757 {
2758 return error(GL_INVALID_ENUM);
2759 }
2760
2761 if(framebufferName == 0)
2762 {
2763 return error(GL_INVALID_OPERATION);
2764 }
2765 break;
2766 default:
2767 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2768 {
2769 if(framebufferName == 0)
2770 {
2771 return error(GL_INVALID_OPERATION);
2772 }
2773 }
2774 else return error(GL_INVALID_ENUM);
2775 }
2776
2777 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2778
2779 GLenum attachmentType;
2780 GLuint attachmentHandle;
2781 GLint attachmentLayer;
2782 Renderbuffer *renderbuffer = nullptr;
2783 switch(attachment)
2784 {
2785 case GL_BACK:
2786 attachmentType = framebuffer->getColorbufferType(0);
2787 attachmentHandle = framebuffer->getColorbufferName(0);
2788 attachmentLayer = framebuffer->getColorbufferLayer(0);
2789 renderbuffer = framebuffer->getColorbuffer(0);
2790 break;
2791 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002792 case GL_DEPTH_ATTACHMENT:
2793 attachmentType = framebuffer->getDepthbufferType();
2794 attachmentHandle = framebuffer->getDepthbufferName();
2795 attachmentLayer = framebuffer->getDepthbufferLayer();
2796 renderbuffer = framebuffer->getDepthbuffer();
2797 break;
2798 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002799 case GL_STENCIL_ATTACHMENT:
2800 attachmentType = framebuffer->getStencilbufferType();
2801 attachmentHandle = framebuffer->getStencilbufferName();
2802 attachmentLayer = framebuffer->getStencilbufferLayer();
2803 renderbuffer = framebuffer->getStencilbuffer();
2804 break;
2805 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002806 attachmentType = framebuffer->getDepthbufferType();
2807 attachmentHandle = framebuffer->getDepthbufferName();
2808 attachmentLayer = framebuffer->getDepthbufferLayer();
2809 renderbuffer = framebuffer->getDepthbuffer();
2810
2811 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002812 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002813 // Different attachments to DEPTH and STENCIL, query fails
2814 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002815 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002816 break;
2817 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002818 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2819 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2820 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2821 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2822 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2823 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002824 }
2825
2826 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002827 if(framebufferName == 0)
2828 {
2829 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2830 }
2831 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002832 {
2833 attachmentObjectType = attachmentType;
2834 }
2835 else if(es2::IsTextureTarget(attachmentType))
2836 {
2837 attachmentObjectType = GL_TEXTURE;
2838 }
2839 else UNREACHABLE(attachmentType);
2840
2841 if(attachmentObjectType != GL_NONE)
2842 {
2843 switch(pname)
2844 {
2845 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2846 *params = attachmentObjectType;
2847 break;
2848 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002849 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002850 {
2851 *params = attachmentHandle;
2852 }
2853 else
2854 {
2855 return error(GL_INVALID_ENUM);
2856 }
2857 break;
2858 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2859 if(attachmentObjectType == GL_TEXTURE)
2860 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002861 *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 -04002862 }
2863 else
2864 {
2865 return error(GL_INVALID_ENUM);
2866 }
2867 break;
2868 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2869 if(attachmentObjectType == GL_TEXTURE)
2870 {
2871 if(es2::IsCubemapTextureTarget(attachmentType))
2872 {
2873 *params = attachmentType;
2874 }
2875 else
2876 {
2877 *params = 0;
2878 }
2879 }
2880 else
2881 {
2882 return error(GL_INVALID_ENUM);
2883 }
2884 break;
2885 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2886 if(clientVersion >= 3)
2887 {
2888 *params = attachmentLayer;
2889 }
2890 else return error(GL_INVALID_ENUM);
2891 break;
2892 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2893 if(clientVersion >= 3)
2894 {
2895 *params = renderbuffer->getRedSize();
2896 }
2897 else return error(GL_INVALID_ENUM);
2898 break;
2899 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2900 if(clientVersion >= 3)
2901 {
2902 *params = renderbuffer->getGreenSize();
2903 }
2904 else return error(GL_INVALID_ENUM);
2905 break;
2906 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2907 if(clientVersion >= 3)
2908 {
2909 *params = renderbuffer->getBlueSize();
2910 }
2911 else return error(GL_INVALID_ENUM);
2912 break;
2913 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2914 if(clientVersion >= 3)
2915 {
2916 *params = renderbuffer->getAlphaSize();
2917 }
2918 else return error(GL_INVALID_ENUM);
2919 break;
2920 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2921 if(clientVersion >= 3)
2922 {
2923 *params = renderbuffer->getDepthSize();
2924 }
2925 else return error(GL_INVALID_ENUM);
2926 break;
2927 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2928 if(clientVersion >= 3)
2929 {
2930 *params = renderbuffer->getStencilSize();
2931 }
2932 else return error(GL_INVALID_ENUM);
2933 break;
2934 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002935 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2936 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002937 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002938 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002939 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002940
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002941 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002942 break;
2943 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2944 if(clientVersion >= 3)
2945 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002946 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002947 }
2948 else return error(GL_INVALID_ENUM);
2949 break;
2950 default:
2951 return error(GL_INVALID_ENUM);
2952 }
2953 }
2954 else
2955 {
2956 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2957 // is NONE, then querying any other pname will generate INVALID_ENUM.
2958
2959 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2960 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2961 // INVALID_OPERATION for all other pnames
2962
2963 switch(pname)
2964 {
2965 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2966 *params = GL_NONE;
2967 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002968 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2969 if(clientVersion < 3)
2970 {
2971 return error(GL_INVALID_ENUM);
2972 }
2973 *params = 0;
2974 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002975 default:
2976 if(clientVersion < 3)
2977 {
2978 return error(GL_INVALID_ENUM);
2979 }
2980 else
2981 {
2982 return error(GL_INVALID_OPERATION);
2983 }
2984 }
2985 }
2986 }
2987}
2988
2989GLenum GetGraphicsResetStatusEXT(void)
2990{
2991 TRACE("()");
2992
2993 return GL_NO_ERROR;
2994}
2995
2996void GetIntegerv(GLenum pname, GLint* params)
2997{
2998 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2999
3000 es2::Context *context = es2::getContext();
3001
3002 if(!context)
3003 {
3004 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
3005 #ifdef __ANDROID__
3006 ALOGI("expected_badness glGetIntegerv() called without current context.");
3007 #else
3008 ERR("glGetIntegerv() called without current context.");
3009 #endif
3010
3011 // This is not spec compliant! When there is no current GL context, functions should
3012 // have no side effects. Google Maps queries these values before creating a context,
3013 // so we need this as a bug-compatible workaround.
3014 switch(pname)
3015 {
3016 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3017 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3018 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3019 case GL_STENCIL_BITS: *params = 8; return;
3020 case GL_ALIASED_LINE_WIDTH_RANGE:
3021 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3022 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3023 return;
3024 }
3025 }
3026
3027 if(context)
3028 {
3029 if(!(context->getIntegerv(pname, params)))
3030 {
3031 GLenum nativeType;
3032 unsigned int numParams = 0;
3033 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3034 return error(GL_INVALID_ENUM);
3035
3036 if(numParams == 0)
3037 return; // it is known that pname is valid, but there are no parameters to return
3038
3039 if(nativeType == GL_BOOL)
3040 {
3041 GLboolean *boolParams = nullptr;
3042 boolParams = new GLboolean[numParams];
3043
3044 context->getBooleanv(pname, boolParams);
3045
3046 for(unsigned int i = 0; i < numParams; ++i)
3047 {
3048 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3049 }
3050
3051 delete [] boolParams;
3052 }
3053 else if(nativeType == GL_FLOAT)
3054 {
3055 GLfloat *floatParams = nullptr;
3056 floatParams = new GLfloat[numParams];
3057
3058 context->getFloatv(pname, floatParams);
3059
3060 for(unsigned int i = 0; i < numParams; ++i)
3061 {
3062 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3063 {
Alexis Hetu60e20282017-12-13 07:42:22 -05003064 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003065 }
3066 else
3067 {
3068 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3069 }
3070 }
3071
3072 delete [] floatParams;
3073 }
3074 }
3075 }
3076}
3077
3078void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3079{
3080 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3081
3082 es2::Context *context = es2::getContext();
3083
3084 if(context)
3085 {
3086 es2::Program *programObject = context->getProgram(program);
3087
3088 if(!programObject)
3089 {
3090 if(context->getShader(program))
3091 {
3092 return error(GL_INVALID_OPERATION);
3093 }
3094 else
3095 {
3096 return error(GL_INVALID_VALUE);
3097 }
3098 }
3099
3100 GLint clientVersion = egl::getClientVersion();
3101
3102 switch(pname)
3103 {
3104 case GL_DELETE_STATUS:
3105 *params = programObject->isFlaggedForDeletion();
3106 return;
3107 case GL_LINK_STATUS:
3108 *params = programObject->isLinked();
3109 return;
3110 case GL_VALIDATE_STATUS:
3111 *params = programObject->isValidated();
3112 return;
3113 case GL_INFO_LOG_LENGTH:
3114 *params = (GLint)programObject->getInfoLogLength();
3115 return;
3116 case GL_ATTACHED_SHADERS:
3117 *params = programObject->getAttachedShadersCount();
3118 return;
3119 case GL_ACTIVE_ATTRIBUTES:
3120 *params = (GLint)programObject->getActiveAttributeCount();
3121 return;
3122 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3123 *params = programObject->getActiveAttributeMaxLength();
3124 return;
3125 case GL_ACTIVE_UNIFORMS:
3126 *params = (GLint)programObject->getActiveUniformCount();
3127 return;
3128 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3129 *params = programObject->getActiveUniformMaxLength();
3130 return;
3131 case GL_ACTIVE_UNIFORM_BLOCKS:
3132 if(clientVersion >= 3)
3133 {
3134 *params = (GLint)programObject->getActiveUniformBlockCount();
3135 return;
3136 }
3137 else return error(GL_INVALID_ENUM);
3138 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3139 if(clientVersion >= 3)
3140 {
3141 *params = programObject->getActiveUniformBlockMaxLength();
3142 return;
3143 }
3144 else return error(GL_INVALID_ENUM);
3145 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3146 if(clientVersion >= 3)
3147 {
3148 *params = programObject->getTransformFeedbackBufferMode();
3149 return;
3150 }
3151 else return error(GL_INVALID_ENUM);
3152 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3153 if(clientVersion >= 3)
3154 {
3155 *params = programObject->getTransformFeedbackVaryingCount();
3156 return;
3157 }
3158 else return error(GL_INVALID_ENUM);
3159 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3160 if(clientVersion >= 3)
3161 {
3162 *params = programObject->getTransformFeedbackVaryingMaxLength();
3163 return;
3164 }
3165 else return error(GL_INVALID_ENUM);
3166 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3167 if(clientVersion >= 3)
3168 {
3169 *params = programObject->getBinaryRetrievableHint();
3170 return;
3171 }
3172 else return error(GL_INVALID_ENUM);
3173 case GL_PROGRAM_BINARY_LENGTH:
3174 if(clientVersion >= 3)
3175 {
3176 *params = programObject->getBinaryLength();
3177 return;
3178 }
3179 else return error(GL_INVALID_ENUM);
3180 default:
3181 return error(GL_INVALID_ENUM);
3182 }
3183 }
3184}
3185
3186void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3187{
3188 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3189 program, bufsize, length, infolog);
3190
3191 if(bufsize < 0)
3192 {
3193 return error(GL_INVALID_VALUE);
3194 }
3195
3196 es2::Context *context = es2::getContext();
3197
3198 if(context)
3199 {
3200 es2::Program *programObject = context->getProgram(program);
3201
3202 if(!programObject)
3203 {
3204 if(context->getShader(program))
3205 {
3206 return error(GL_INVALID_OPERATION);
3207 }
3208 else
3209 {
3210 return error(GL_INVALID_VALUE);
3211 }
3212 }
3213
3214 programObject->getInfoLog(bufsize, length, infolog);
3215 }
3216}
3217
3218void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3219{
3220 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3221
3222 switch(pname)
3223 {
3224 case GL_CURRENT_QUERY_EXT:
3225 break;
3226 default:
3227 return error(GL_INVALID_ENUM);
3228 }
3229
3230 es2::Context *context = es2::getContext();
3231
3232 if(context)
3233 {
3234 params[0] = context->getActiveQuery(target);
3235 }
3236}
3237
3238void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3239{
3240 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3241
3242 switch(pname)
3243 {
3244 case GL_QUERY_RESULT_EXT:
3245 case GL_QUERY_RESULT_AVAILABLE_EXT:
3246 break;
3247 default:
3248 return error(GL_INVALID_ENUM);
3249 }
3250
3251 es2::Context *context = es2::getContext();
3252
3253 if(context)
3254 {
3255 es2::Query *queryObject = context->getQuery(name);
3256
3257 if(!queryObject)
3258 {
3259 return error(GL_INVALID_OPERATION);
3260 }
3261
3262 if(context->getActiveQuery(queryObject->getType()) == name)
3263 {
3264 return error(GL_INVALID_OPERATION);
3265 }
3266
3267 switch(pname)
3268 {
3269 case GL_QUERY_RESULT_EXT:
3270 params[0] = queryObject->getResult();
3271 break;
3272 case GL_QUERY_RESULT_AVAILABLE_EXT:
3273 params[0] = queryObject->isResultAvailable();
3274 break;
3275 default:
3276 ASSERT(false);
3277 }
3278 }
3279}
3280
3281void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3282{
3283 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3284
3285 es2::Context *context = es2::getContext();
3286
3287 if(context)
3288 {
3289 if(target != GL_RENDERBUFFER)
3290 {
3291 return error(GL_INVALID_ENUM);
3292 }
3293
3294 if(context->getRenderbufferName() == 0)
3295 {
3296 return error(GL_INVALID_OPERATION);
3297 }
3298
3299 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3300
3301 switch(pname)
3302 {
3303 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3304 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003305 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3306 {
3307 GLint internalformat = renderbuffer->getFormat();
3308 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3309 }
3310 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003311 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3312 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3313 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3314 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3315 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3316 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003317 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003318 default:
3319 return error(GL_INVALID_ENUM);
3320 }
3321 }
3322}
3323
3324void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3325{
3326 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3327
3328 es2::Context *context = es2::getContext();
3329
3330 if(context)
3331 {
3332 es2::Shader *shaderObject = context->getShader(shader);
3333
3334 if(!shaderObject)
3335 {
3336 if(context->getProgram(shader))
3337 {
3338 return error(GL_INVALID_OPERATION);
3339 }
3340 else
3341 {
3342 return error(GL_INVALID_VALUE);
3343 }
3344 }
3345
3346 switch(pname)
3347 {
3348 case GL_SHADER_TYPE:
3349 *params = shaderObject->getType();
3350 return;
3351 case GL_DELETE_STATUS:
3352 *params = shaderObject->isFlaggedForDeletion();
3353 return;
3354 case GL_COMPILE_STATUS:
3355 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3356 return;
3357 case GL_INFO_LOG_LENGTH:
3358 *params = (GLint)shaderObject->getInfoLogLength();
3359 return;
3360 case GL_SHADER_SOURCE_LENGTH:
3361 *params = (GLint)shaderObject->getSourceLength();
3362 return;
3363 default:
3364 return error(GL_INVALID_ENUM);
3365 }
3366 }
3367}
3368
3369void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3370{
3371 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3372 shader, bufsize, length, infolog);
3373
3374 if(bufsize < 0)
3375 {
3376 return error(GL_INVALID_VALUE);
3377 }
3378
3379 es2::Context *context = es2::getContext();
3380
3381 if(context)
3382 {
3383 es2::Shader *shaderObject = context->getShader(shader);
3384
3385 if(!shaderObject)
3386 {
3387 if(context->getProgram(shader))
3388 {
3389 return error(GL_INVALID_OPERATION);
3390 }
3391 else
3392 {
3393 return error(GL_INVALID_VALUE);
3394 }
3395 }
3396
3397 shaderObject->getInfoLog(bufsize, length, infolog);
3398 }
3399}
3400
3401void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3402{
3403 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3404 shadertype, precisiontype, range, precision);
3405
3406 switch(shadertype)
3407 {
3408 case GL_VERTEX_SHADER:
3409 case GL_FRAGMENT_SHADER:
3410 break;
3411 default:
3412 return error(GL_INVALID_ENUM);
3413 }
3414
3415 switch(precisiontype)
3416 {
3417 case GL_LOW_FLOAT:
3418 case GL_MEDIUM_FLOAT:
3419 case GL_HIGH_FLOAT:
3420 // IEEE 754 single-precision
3421 range[0] = 127;
3422 range[1] = 127;
3423 *precision = 23;
3424 break;
3425 case GL_LOW_INT:
3426 case GL_MEDIUM_INT:
3427 case GL_HIGH_INT:
3428 // Full integer precision is supported
3429 range[0] = 31;
3430 range[1] = 30;
3431 *precision = 0;
3432 break;
3433 default:
3434 return error(GL_INVALID_ENUM);
3435 }
3436}
3437
3438void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3439{
3440 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3441 shader, bufsize, length, source);
3442
3443 if(bufsize < 0)
3444 {
3445 return error(GL_INVALID_VALUE);
3446 }
3447
3448 es2::Context *context = es2::getContext();
3449
3450 if(context)
3451 {
3452 es2::Shader *shaderObject = context->getShader(shader);
3453
3454 if(!shaderObject)
3455 {
3456 if(context->getProgram(shader))
3457 {
3458 return error(GL_INVALID_OPERATION);
3459 }
3460 else
3461 {
3462 return error(GL_INVALID_VALUE);
3463 }
3464 }
3465
3466 shaderObject->getSource(bufsize, length, source);
3467 }
3468}
3469
3470const GLubyte* GetString(GLenum name)
3471{
3472 TRACE("(GLenum name = 0x%X)", name);
3473
3474 switch(name)
3475 {
3476 case GL_VENDOR:
3477 return (GLubyte*)"Google Inc.";
3478 case GL_RENDERER:
3479 return (GLubyte*)"Google SwiftShader";
3480 case GL_VERSION:
Nicolas Capens894858a2018-03-22 00:55:23 -04003481 {
3482 es2::Context *context = es2::getContext();
3483 return (context && (context->getClientVersion() >= 3)) ?
3484 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3485 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3486 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003487 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens894858a2018-03-22 00:55:23 -04003488 {
3489 es2::Context *context = es2::getContext();
3490 return (context && (context->getClientVersion() >= 3)) ?
3491 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3492 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3493 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003494 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003495 {
3496 es2::Context *context = es2::getContext();
3497 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3498 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003499 default:
3500 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3501 }
3502}
3503
3504void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3505{
3506 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3507
3508 es2::Context *context = es2::getContext();
3509
3510 if(context)
3511 {
3512 es2::Texture *texture;
3513
3514 GLint clientVersion = context->getClientVersion();
3515
3516 switch(target)
3517 {
3518 case GL_TEXTURE_2D:
3519 texture = context->getTexture2D();
3520 break;
3521 case GL_TEXTURE_CUBE_MAP:
3522 texture = context->getTextureCubeMap();
3523 break;
3524 case GL_TEXTURE_EXTERNAL_OES:
3525 texture = context->getTextureExternal();
3526 break;
3527 case GL_TEXTURE_2D_ARRAY:
3528 if(clientVersion < 3)
3529 {
3530 return error(GL_INVALID_ENUM);
3531 }
3532 else
3533 {
3534 texture = context->getTexture2DArray();
3535 }
3536 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003537 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003538 texture = context->getTexture3D();
3539 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003540 case GL_TEXTURE_RECTANGLE_ARB:
3541 texture = context->getTexture2DRect();
3542 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003543 default:
3544 return error(GL_INVALID_ENUM);
3545 }
3546
3547 switch(pname)
3548 {
3549 case GL_TEXTURE_MAG_FILTER:
3550 *params = (GLfloat)texture->getMagFilter();
3551 break;
3552 case GL_TEXTURE_MIN_FILTER:
3553 *params = (GLfloat)texture->getMinFilter();
3554 break;
3555 case GL_TEXTURE_WRAP_S:
3556 *params = (GLfloat)texture->getWrapS();
3557 break;
3558 case GL_TEXTURE_WRAP_T:
3559 *params = (GLfloat)texture->getWrapT();
3560 break;
3561 case GL_TEXTURE_WRAP_R_OES:
3562 *params = (GLfloat)texture->getWrapR();
3563 break;
3564 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3565 *params = texture->getMaxAnisotropy();
3566 break;
3567 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3568 *params = (GLfloat)1;
3569 break;
3570 case GL_TEXTURE_BASE_LEVEL:
3571 if(clientVersion >= 3)
3572 {
3573 *params = (GLfloat)texture->getBaseLevel();
3574 break;
3575 }
3576 else return error(GL_INVALID_ENUM);
3577 case GL_TEXTURE_COMPARE_FUNC:
3578 if(clientVersion >= 3)
3579 {
3580 *params = (GLfloat)texture->getCompareFunc();
3581 break;
3582 }
3583 else return error(GL_INVALID_ENUM);
3584 case GL_TEXTURE_COMPARE_MODE:
3585 if(clientVersion >= 3)
3586 {
3587 *params = (GLfloat)texture->getCompareMode();
3588 break;
3589 }
3590 else return error(GL_INVALID_ENUM);
3591 case GL_TEXTURE_IMMUTABLE_FORMAT:
3592 if(clientVersion >= 3)
3593 {
3594 *params = (GLfloat)texture->getImmutableFormat();
3595 break;
3596 }
3597 else return error(GL_INVALID_ENUM);
3598 case GL_TEXTURE_IMMUTABLE_LEVELS:
3599 if(clientVersion >= 3)
3600 {
3601 *params = (GLfloat)texture->getImmutableLevels();
3602 break;
3603 }
3604 else return error(GL_INVALID_ENUM);
3605 case GL_TEXTURE_MAX_LEVEL:
3606 if(clientVersion >= 3)
3607 {
3608 *params = (GLfloat)texture->getMaxLevel();
3609 break;
3610 }
3611 else return error(GL_INVALID_ENUM);
3612 case GL_TEXTURE_MAX_LOD:
3613 if(clientVersion >= 3)
3614 {
3615 *params = texture->getMaxLOD();
3616 break;
3617 }
3618 else return error(GL_INVALID_ENUM);
3619 case GL_TEXTURE_MIN_LOD:
3620 if(clientVersion >= 3)
3621 {
3622 *params = texture->getMinLOD();
3623 break;
3624 }
3625 else return error(GL_INVALID_ENUM);
3626 case GL_TEXTURE_SWIZZLE_R:
3627 if(clientVersion >= 3)
3628 {
3629 *params = (GLfloat)texture->getSwizzleR();
3630 break;
3631 }
3632 else return error(GL_INVALID_ENUM);
3633 case GL_TEXTURE_SWIZZLE_G:
3634 if(clientVersion >= 3)
3635 {
3636 *params = (GLfloat)texture->getSwizzleG();
3637 break;
3638 }
3639 else return error(GL_INVALID_ENUM);
3640 case GL_TEXTURE_SWIZZLE_B:
3641 if(clientVersion >= 3)
3642 {
3643 *params = (GLfloat)texture->getSwizzleB();
3644 break;
3645 }
3646 else return error(GL_INVALID_ENUM);
3647 case GL_TEXTURE_SWIZZLE_A:
3648 if(clientVersion >= 3)
3649 {
3650 *params = (GLfloat)texture->getSwizzleA();
3651 break;
3652 }
3653 else return error(GL_INVALID_ENUM);
3654 default:
3655 return error(GL_INVALID_ENUM);
3656 }
3657 }
3658}
3659
3660void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3661{
3662 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3663
3664 es2::Context *context = es2::getContext();
3665
3666 if(context)
3667 {
3668 es2::Texture *texture;
3669
3670 GLint clientVersion = context->getClientVersion();
3671
3672 switch(target)
3673 {
3674 case GL_TEXTURE_2D:
3675 texture = context->getTexture2D();
3676 break;
3677 case GL_TEXTURE_CUBE_MAP:
3678 texture = context->getTextureCubeMap();
3679 break;
3680 case GL_TEXTURE_EXTERNAL_OES:
3681 texture = context->getTextureExternal();
3682 break;
3683 case GL_TEXTURE_2D_ARRAY:
3684 if(clientVersion < 3)
3685 {
3686 return error(GL_INVALID_ENUM);
3687 }
3688 else
3689 {
3690 texture = context->getTexture2DArray();
3691 }
3692 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003693 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003694 texture = context->getTexture3D();
3695 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003696 case GL_TEXTURE_RECTANGLE_ARB:
3697 texture = context->getTexture2DRect();
3698 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003699 default:
3700 return error(GL_INVALID_ENUM);
3701 }
3702
3703 switch(pname)
3704 {
3705 case GL_TEXTURE_MAG_FILTER:
3706 *params = texture->getMagFilter();
3707 break;
3708 case GL_TEXTURE_MIN_FILTER:
3709 *params = texture->getMinFilter();
3710 break;
3711 case GL_TEXTURE_WRAP_S:
3712 *params = texture->getWrapS();
3713 break;
3714 case GL_TEXTURE_WRAP_T:
3715 *params = texture->getWrapT();
3716 break;
3717 case GL_TEXTURE_WRAP_R_OES:
3718 *params = texture->getWrapR();
3719 break;
3720 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3721 *params = (GLint)texture->getMaxAnisotropy();
3722 break;
3723 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3724 *params = 1;
3725 break;
3726 case GL_TEXTURE_BASE_LEVEL:
3727 if(clientVersion >= 3)
3728 {
3729 *params = texture->getBaseLevel();
3730 break;
3731 }
3732 else return error(GL_INVALID_ENUM);
3733 case GL_TEXTURE_COMPARE_FUNC:
3734 if(clientVersion >= 3)
3735 {
3736 *params = (GLint)texture->getCompareFunc();
3737 break;
3738 }
3739 else return error(GL_INVALID_ENUM);
3740 case GL_TEXTURE_COMPARE_MODE:
3741 if(clientVersion >= 3)
3742 {
3743 *params = (GLint)texture->getCompareMode();
3744 break;
3745 }
3746 else return error(GL_INVALID_ENUM);
3747 case GL_TEXTURE_IMMUTABLE_FORMAT:
3748 if(clientVersion >= 3)
3749 {
3750 *params = (GLint)texture->getImmutableFormat();
3751 break;
3752 }
3753 else return error(GL_INVALID_ENUM);
3754 case GL_TEXTURE_IMMUTABLE_LEVELS:
3755 if(clientVersion >= 3)
3756 {
3757 *params = (GLint)texture->getImmutableLevels();
3758 break;
3759 }
3760 else return error(GL_INVALID_ENUM);
3761 case GL_TEXTURE_MAX_LEVEL:
3762 if(clientVersion >= 3)
3763 {
3764 *params = texture->getMaxLevel();
3765 break;
3766 }
3767 else return error(GL_INVALID_ENUM);
3768 case GL_TEXTURE_MAX_LOD:
3769 if(clientVersion >= 3)
3770 {
3771 *params = (GLint)roundf(texture->getMaxLOD());
3772 break;
3773 }
3774 else return error(GL_INVALID_ENUM);
3775 case GL_TEXTURE_MIN_LOD:
3776 if(clientVersion >= 3)
3777 {
3778 *params = (GLint)roundf(texture->getMinLOD());
3779 break;
3780 }
3781 else return error(GL_INVALID_ENUM);
3782 case GL_TEXTURE_SWIZZLE_R:
3783 if(clientVersion >= 3)
3784 {
3785 *params = (GLint)texture->getSwizzleR();
3786 break;
3787 }
3788 else return error(GL_INVALID_ENUM);
3789 case GL_TEXTURE_SWIZZLE_G:
3790 if(clientVersion >= 3)
3791 {
3792 *params = (GLint)texture->getSwizzleG();
3793 break;
3794 }
3795 else return error(GL_INVALID_ENUM);
3796 case GL_TEXTURE_SWIZZLE_B:
3797 if(clientVersion >= 3)
3798 {
3799 *params = (GLint)texture->getSwizzleB();
3800 break;
3801 }
3802 else return error(GL_INVALID_ENUM);
3803 case GL_TEXTURE_SWIZZLE_A:
3804 if(clientVersion >= 3)
3805 {
3806 *params = (GLint)texture->getSwizzleA();
3807 break;
3808 }
3809 else return error(GL_INVALID_ENUM);
3810 default:
3811 return error(GL_INVALID_ENUM);
3812 }
3813 }
3814}
3815
3816void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3817{
3818 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3819 program, location, bufSize, params);
3820
3821 if(bufSize < 0)
3822 {
3823 return error(GL_INVALID_VALUE);
3824 }
3825
3826 es2::Context *context = es2::getContext();
3827
3828 if(context)
3829 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003830 es2::Program *programObject = context->getProgram(program);
3831
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003832 if(!programObject)
3833 {
3834 if(context->getShader(program))
3835 {
3836 return error(GL_INVALID_OPERATION);
3837 }
3838 else
3839 {
3840 return error(GL_INVALID_VALUE);
3841 }
3842 }
3843
3844 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003845 {
3846 return error(GL_INVALID_OPERATION);
3847 }
3848
3849 if(!programObject->getUniformfv(location, &bufSize, params))
3850 {
3851 return error(GL_INVALID_OPERATION);
3852 }
3853 }
3854}
3855
3856void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3857{
3858 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3859
3860 es2::Context *context = es2::getContext();
3861
3862 if(context)
3863 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003864 es2::Program *programObject = context->getProgram(program);
3865
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003866 if(!programObject)
3867 {
3868 if(context->getShader(program))
3869 {
3870 return error(GL_INVALID_OPERATION);
3871 }
3872 else
3873 {
3874 return error(GL_INVALID_VALUE);
3875 }
3876 }
3877
3878 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003879 {
3880 return error(GL_INVALID_OPERATION);
3881 }
3882
3883 if(!programObject->getUniformfv(location, nullptr, params))
3884 {
3885 return error(GL_INVALID_OPERATION);
3886 }
3887 }
3888}
3889
3890void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3891{
3892 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3893 program, location, bufSize, params);
3894
3895 if(bufSize < 0)
3896 {
3897 return error(GL_INVALID_VALUE);
3898 }
3899
3900 es2::Context *context = es2::getContext();
3901
3902 if(context)
3903 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003904 es2::Program *programObject = context->getProgram(program);
3905
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003906 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003907 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003908 if(context->getShader(program))
3909 {
3910 return error(GL_INVALID_OPERATION);
3911 }
3912 else
3913 {
3914 return error(GL_INVALID_VALUE);
3915 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003916 }
3917
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003918 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003919 {
3920 return error(GL_INVALID_OPERATION);
3921 }
3922
3923 if(!programObject->getUniformiv(location, &bufSize, params))
3924 {
3925 return error(GL_INVALID_OPERATION);
3926 }
3927 }
3928}
3929
3930void GetUniformiv(GLuint program, GLint location, GLint* params)
3931{
3932 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3933
3934 es2::Context *context = es2::getContext();
3935
3936 if(context)
3937 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003938 es2::Program *programObject = context->getProgram(program);
3939
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003940 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003941 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003942 if(context->getShader(program))
3943 {
3944 return error(GL_INVALID_OPERATION);
3945 }
3946 else
3947 {
3948 return error(GL_INVALID_VALUE);
3949 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003950 }
3951
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003952 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003953 {
3954 return error(GL_INVALID_OPERATION);
3955 }
3956
3957 if(!programObject->getUniformiv(location, nullptr, params))
3958 {
3959 return error(GL_INVALID_OPERATION);
3960 }
3961 }
3962}
3963
3964int GetUniformLocation(GLuint program, const GLchar* name)
3965{
3966 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3967
3968 es2::Context *context = es2::getContext();
3969
3970 if(strstr(name, "gl_") == name)
3971 {
3972 return -1;
3973 }
3974
3975 if(context)
3976 {
3977 es2::Program *programObject = context->getProgram(program);
3978
3979 if(!programObject)
3980 {
3981 if(context->getShader(program))
3982 {
3983 return error(GL_INVALID_OPERATION, -1);
3984 }
3985 else
3986 {
3987 return error(GL_INVALID_VALUE, -1);
3988 }
3989 }
3990
3991 if(!programObject->isLinked())
3992 {
3993 return error(GL_INVALID_OPERATION, -1);
3994 }
3995
3996 return programObject->getUniformLocation(name);
3997 }
3998
3999 return -1;
4000}
4001
4002void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
4003{
4004 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
4005
4006 es2::Context *context = es2::getContext();
4007
4008 if(context)
4009 {
4010 if(index >= es2::MAX_VERTEX_ATTRIBS)
4011 {
4012 return error(GL_INVALID_VALUE);
4013 }
4014
4015 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4016
4017 GLint clientVersion = context->getClientVersion();
4018
4019 switch(pname)
4020 {
4021 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4022 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4023 break;
4024 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4025 *params = (GLfloat)attribState.mSize;
4026 break;
4027 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4028 *params = (GLfloat)attribState.mStride;
4029 break;
4030 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4031 *params = (GLfloat)attribState.mType;
4032 break;
4033 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4034 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4035 break;
4036 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4037 *params = (GLfloat)attribState.mBoundBuffer.name();
4038 break;
4039 case GL_CURRENT_VERTEX_ATTRIB:
4040 {
4041 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4042 for(int i = 0; i < 4; ++i)
4043 {
4044 params[i] = attrib.getCurrentValueF(i);
4045 }
4046 }
4047 break;
4048 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4049 if(clientVersion >= 3)
4050 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004051 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004052 break;
4053 }
4054 else return error(GL_INVALID_ENUM);
4055 default: return error(GL_INVALID_ENUM);
4056 }
4057 }
4058}
4059
4060void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4061{
4062 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4063
4064 es2::Context *context = es2::getContext();
4065
4066 if(context)
4067 {
4068 if(index >= es2::MAX_VERTEX_ATTRIBS)
4069 {
4070 return error(GL_INVALID_VALUE);
4071 }
4072
4073 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4074
4075 GLint clientVersion = context->getClientVersion();
4076
4077 switch(pname)
4078 {
4079 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4080 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4081 break;
4082 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4083 *params = attribState.mSize;
4084 break;
4085 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4086 *params = attribState.mStride;
4087 break;
4088 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4089 *params = attribState.mType;
4090 break;
4091 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4092 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4093 break;
4094 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4095 *params = attribState.mBoundBuffer.name();
4096 break;
4097 case GL_CURRENT_VERTEX_ATTRIB:
4098 {
4099 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4100 for(int i = 0; i < 4; ++i)
4101 {
4102 float currentValue = attrib.getCurrentValueF(i);
4103 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4104 }
4105 }
4106 break;
4107 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4108 if(clientVersion >= 3)
4109 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004110 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004111 break;
4112 }
4113 else return error(GL_INVALID_ENUM);
4114 default: return error(GL_INVALID_ENUM);
4115 }
4116 }
4117}
4118
4119void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4120{
4121 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4122
4123 es2::Context *context = es2::getContext();
4124
4125 if(context)
4126 {
4127 if(index >= es2::MAX_VERTEX_ATTRIBS)
4128 {
4129 return error(GL_INVALID_VALUE);
4130 }
4131
4132 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4133 {
4134 return error(GL_INVALID_ENUM);
4135 }
4136
4137 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4138 }
4139}
4140
4141void Hint(GLenum target, GLenum mode)
4142{
4143 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4144
4145 switch(mode)
4146 {
4147 case GL_FASTEST:
4148 case GL_NICEST:
4149 case GL_DONT_CARE:
4150 break;
4151 default:
4152 return error(GL_INVALID_ENUM);
4153 }
4154
4155 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004156
4157 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004158 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004159 switch(target)
4160 {
4161 case GL_GENERATE_MIPMAP_HINT:
4162 context->setGenerateMipmapHint(mode);
4163 break;
4164 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4165 context->setFragmentShaderDerivativeHint(mode);
4166 break;
4167 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4168 context->setTextureFilteringHint(mode);
4169 break;
4170 default:
4171 return error(GL_INVALID_ENUM);
4172 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004173 }
4174}
4175
4176GLboolean IsBuffer(GLuint buffer)
4177{
4178 TRACE("(GLuint buffer = %d)", buffer);
4179
4180 es2::Context *context = es2::getContext();
4181
4182 if(context && buffer)
4183 {
4184 es2::Buffer *bufferObject = context->getBuffer(buffer);
4185
4186 if(bufferObject)
4187 {
4188 return GL_TRUE;
4189 }
4190 }
4191
4192 return GL_FALSE;
4193}
4194
4195GLboolean IsEnabled(GLenum cap)
4196{
4197 TRACE("(GLenum cap = 0x%X)", cap);
4198
4199 es2::Context *context = es2::getContext();
4200
4201 if(context)
4202 {
4203 GLint clientVersion = context->getClientVersion();
4204
4205 switch(cap)
4206 {
4207 case GL_CULL_FACE: return context->isCullFaceEnabled();
4208 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4209 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4210 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4211 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4212 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4213 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4214 case GL_BLEND: return context->isBlendEnabled();
4215 case GL_DITHER: return context->isDitherEnabled();
4216 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4217 if(clientVersion >= 3)
4218 {
4219 return context->isPrimitiveRestartFixedIndexEnabled();
4220 }
4221 else return error(GL_INVALID_ENUM, false);
4222 case GL_RASTERIZER_DISCARD:
4223 if(clientVersion >= 3)
4224 {
4225 return context->isRasterizerDiscardEnabled();
4226 }
4227 else return error(GL_INVALID_ENUM, false);
4228 default:
4229 return error(GL_INVALID_ENUM, false);
4230 }
4231 }
4232
4233 return false;
4234}
4235
4236GLboolean IsFenceNV(GLuint fence)
4237{
4238 TRACE("(GLuint fence = %d)", fence);
4239
4240 es2::Context *context = es2::getContext();
4241
4242 if(context)
4243 {
4244 es2::Fence *fenceObject = context->getFence(fence);
4245
4246 if(!fenceObject)
4247 {
4248 return GL_FALSE;
4249 }
4250
4251 return fenceObject->isFence();
4252 }
4253
4254 return GL_FALSE;
4255}
4256
4257GLboolean IsFramebuffer(GLuint framebuffer)
4258{
4259 TRACE("(GLuint framebuffer = %d)", framebuffer);
4260
4261 es2::Context *context = es2::getContext();
4262
4263 if(context && framebuffer)
4264 {
4265 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4266
4267 if(framebufferObject)
4268 {
4269 return GL_TRUE;
4270 }
4271 }
4272
4273 return GL_FALSE;
4274}
4275
4276GLboolean IsProgram(GLuint program)
4277{
4278 TRACE("(GLuint program = %d)", program);
4279
4280 es2::Context *context = es2::getContext();
4281
4282 if(context && program)
4283 {
4284 es2::Program *programObject = context->getProgram(program);
4285
4286 if(programObject)
4287 {
4288 return GL_TRUE;
4289 }
4290 }
4291
4292 return GL_FALSE;
4293}
4294
4295GLboolean IsQueryEXT(GLuint name)
4296{
4297 TRACE("(GLuint name = %d)", name);
4298
4299 if(name == 0)
4300 {
4301 return GL_FALSE;
4302 }
4303
4304 es2::Context *context = es2::getContext();
4305
4306 if(context)
4307 {
4308 es2::Query *queryObject = context->getQuery(name);
4309
4310 if(queryObject)
4311 {
4312 return GL_TRUE;
4313 }
4314 }
4315
4316 return GL_FALSE;
4317}
4318
4319GLboolean IsRenderbuffer(GLuint renderbuffer)
4320{
4321 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4322
4323 es2::Context *context = es2::getContext();
4324
4325 if(context && renderbuffer)
4326 {
4327 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4328
4329 if(renderbufferObject)
4330 {
4331 return GL_TRUE;
4332 }
4333 }
4334
4335 return GL_FALSE;
4336}
4337
4338GLboolean IsShader(GLuint shader)
4339{
4340 TRACE("(GLuint shader = %d)", shader);
4341
4342 es2::Context *context = es2::getContext();
4343
4344 if(context && shader)
4345 {
4346 es2::Shader *shaderObject = context->getShader(shader);
4347
4348 if(shaderObject)
4349 {
4350 return GL_TRUE;
4351 }
4352 }
4353
4354 return GL_FALSE;
4355}
4356
4357GLboolean IsTexture(GLuint texture)
4358{
4359 TRACE("(GLuint texture = %d)", texture);
4360
4361 es2::Context *context = es2::getContext();
4362
4363 if(context && texture)
4364 {
4365 es2::Texture *textureObject = context->getTexture(texture);
4366
4367 if(textureObject)
4368 {
4369 return GL_TRUE;
4370 }
4371 }
4372
4373 return GL_FALSE;
4374}
4375
4376void LineWidth(GLfloat width)
4377{
4378 TRACE("(GLfloat width = %f)", width);
4379
4380 if(width <= 0.0f)
4381 {
4382 return error(GL_INVALID_VALUE);
4383 }
4384
4385 es2::Context *context = es2::getContext();
4386
4387 if(context)
4388 {
4389 context->setLineWidth(width);
4390 }
4391}
4392
4393void LinkProgram(GLuint program)
4394{
4395 TRACE("(GLuint program = %d)", program);
4396
4397 es2::Context *context = es2::getContext();
4398
4399 if(context)
4400 {
4401 es2::Program *programObject = context->getProgram(program);
4402
4403 if(!programObject)
4404 {
4405 if(context->getShader(program))
4406 {
4407 return error(GL_INVALID_OPERATION);
4408 }
4409 else
4410 {
4411 return error(GL_INVALID_VALUE);
4412 }
4413 }
4414
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004415 if(programObject == context->getCurrentProgram())
4416 {
4417 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4418 if(transformFeedback && transformFeedback->isActive())
4419 {
4420 return error(GL_INVALID_OPERATION);
4421 }
4422 }
4423
Nicolas Capens0bac2852016-05-07 06:09:58 -04004424 programObject->link();
4425 }
4426}
4427
4428void PixelStorei(GLenum pname, GLint param)
4429{
4430 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4431
4432 es2::Context *context = es2::getContext();
4433
4434 if(context)
4435 {
4436 GLint clientVersion = context->getClientVersion();
4437
4438 switch(pname)
4439 {
4440 case GL_UNPACK_ALIGNMENT:
4441 if(param != 1 && param != 2 && param != 4 && param != 8)
4442 {
4443 return error(GL_INVALID_VALUE);
4444 }
4445 context->setUnpackAlignment(param);
4446 break;
4447 case GL_PACK_ALIGNMENT:
4448 if(param != 1 && param != 2 && param != 4 && param != 8)
4449 {
4450 return error(GL_INVALID_VALUE);
4451 }
4452 context->setPackAlignment(param);
4453 break;
4454 case GL_PACK_ROW_LENGTH:
4455 if(clientVersion >= 3)
4456 {
4457 if(param < 0)
4458 {
4459 return error(GL_INVALID_VALUE);
4460 }
4461 context->setPackRowLength(param);
4462 break;
4463 }
4464 else return error(GL_INVALID_ENUM);
4465 case GL_PACK_SKIP_PIXELS:
4466 if(clientVersion >= 3)
4467 {
4468 if(param < 0)
4469 {
4470 return error(GL_INVALID_VALUE);
4471 }
4472 context->setPackSkipPixels(param);
4473 break;
4474 }
4475 else return error(GL_INVALID_ENUM);
4476 case GL_PACK_SKIP_ROWS:
4477 if(clientVersion >= 3)
4478 {
4479 if(param < 0)
4480 {
4481 return error(GL_INVALID_VALUE);
4482 }
4483 context->setPackSkipRows(param);
4484 break;
4485 }
4486 else return error(GL_INVALID_ENUM);
4487 case GL_UNPACK_ROW_LENGTH:
4488 if(clientVersion >= 3)
4489 {
4490 if(param < 0)
4491 {
4492 return error(GL_INVALID_VALUE);
4493 }
4494 context->setUnpackRowLength(param);
4495 break;
4496 }
4497 else return error(GL_INVALID_ENUM);
4498 case GL_UNPACK_IMAGE_HEIGHT:
4499 if(clientVersion >= 3)
4500 {
4501 if(param < 0)
4502 {
4503 return error(GL_INVALID_VALUE);
4504 }
4505 context->setUnpackImageHeight(param);
4506 break;
4507 }
4508 else return error(GL_INVALID_ENUM);
4509 case GL_UNPACK_SKIP_PIXELS:
4510 if(clientVersion >= 3)
4511 {
4512 if(param < 0)
4513 {
4514 return error(GL_INVALID_VALUE);
4515 }
4516 context->setUnpackSkipPixels(param);
4517 break;
4518 }
4519 else return error(GL_INVALID_ENUM);
4520 case GL_UNPACK_SKIP_ROWS:
4521 if(clientVersion >= 3)
4522 {
4523 if(param < 0)
4524 {
4525 return error(GL_INVALID_VALUE);
4526 }
4527 context->setUnpackSkipRows(param);
4528 break;
4529 }
4530 else return error(GL_INVALID_ENUM);
4531 case GL_UNPACK_SKIP_IMAGES:
4532 if(clientVersion >= 3) {
4533 if(param < 0)
4534 {
4535 return error(GL_INVALID_VALUE);
4536 }
4537 context->setUnpackSkipImages(param);
4538 break;
4539 }
4540 else return error(GL_INVALID_ENUM);
4541 default:
4542 return error(GL_INVALID_ENUM);
4543 }
4544 }
4545}
4546
4547void PolygonOffset(GLfloat factor, GLfloat units)
4548{
4549 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4550
4551 es2::Context *context = es2::getContext();
4552
4553 if(context)
4554 {
4555 context->setPolygonOffsetParams(factor, units);
4556 }
4557}
4558
4559void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4560 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4561{
4562 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4563 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4564 x, y, width, height, format, type, bufSize, data);
4565
4566 if(width < 0 || height < 0 || bufSize < 0)
4567 {
4568 return error(GL_INVALID_VALUE);
4569 }
4570
4571 es2::Context *context = es2::getContext();
4572
4573 if(context)
4574 {
4575 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4576 }
4577}
4578
4579void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4580{
4581 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4582 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4583 x, y, width, height, format, type, pixels);
4584
4585 if(width < 0 || height < 0)
4586 {
4587 return error(GL_INVALID_VALUE);
4588 }
4589
4590 es2::Context *context = es2::getContext();
4591
4592 if(context)
4593 {
4594 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4595 }
4596}
4597
4598void ReleaseShaderCompiler(void)
4599{
4600 TRACE("()");
4601
4602 es2::Shader::releaseCompiler();
4603}
4604
Nicolas Capens400667e2017-03-29 14:40:14 -04004605void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004606{
4607 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4608 target, samples, internalformat, width, height);
4609
4610 switch(target)
4611 {
4612 case GL_RENDERBUFFER:
4613 break;
4614 default:
4615 return error(GL_INVALID_ENUM);
4616 }
4617
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004618 if(width < 0 || height < 0 || samples < 0 ||
4619 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4620 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004621 {
4622 return error(GL_INVALID_VALUE);
4623 }
4624
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004625 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004626 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004627 {
4628 return error(GL_INVALID_OPERATION);
4629 }
4630
Nicolas Capens0bac2852016-05-07 06:09:58 -04004631 es2::Context *context = es2::getContext();
4632
4633 if(context)
4634 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004635 GLuint handle = context->getRenderbufferName();
4636 if(handle == 0)
4637 {
4638 return error(GL_INVALID_OPERATION);
4639 }
4640
4641 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004642
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004643 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004644 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004645 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004646 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004647 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4648 {
4649 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4650 }
4651 else if(IsDepthRenderable(internalformat, clientVersion))
4652 {
4653 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4654 }
4655 else if(IsStencilRenderable(internalformat, clientVersion))
4656 {
4657 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4658 }
4659 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004660 }
4661}
4662
Nicolas Capens400667e2017-03-29 14:40:14 -04004663void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4664{
4665 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4666}
4667
Nicolas Capens0bac2852016-05-07 06:09:58 -04004668void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4669{
Nicolas Capens400667e2017-03-29 14:40:14 -04004670 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004671}
4672
4673void SampleCoverage(GLclampf value, GLboolean invert)
4674{
4675 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4676
4677 es2::Context* context = es2::getContext();
4678
4679 if(context)
4680 {
4681 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4682 }
4683}
4684
4685void SetFenceNV(GLuint fence, GLenum condition)
4686{
4687 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4688
4689 if(condition != GL_ALL_COMPLETED_NV)
4690 {
4691 return error(GL_INVALID_ENUM);
4692 }
4693
4694 es2::Context *context = es2::getContext();
4695
4696 if(context)
4697 {
4698 es2::Fence *fenceObject = context->getFence(fence);
4699
4700 if(!fenceObject)
4701 {
4702 return error(GL_INVALID_OPERATION);
4703 }
4704
4705 fenceObject->setFence(condition);
4706 }
4707}
4708
4709void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4710{
4711 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4712
4713 if(width < 0 || height < 0)
4714 {
4715 return error(GL_INVALID_VALUE);
4716 }
4717
4718 es2::Context* context = es2::getContext();
4719
4720 if(context)
4721 {
4722 context->setScissorParams(x, y, width, height);
4723 }
4724}
4725
4726void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4727{
4728 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4729 "const GLvoid* binary = %p, GLsizei length = %d)",
4730 n, shaders, binaryformat, binary, length);
4731
4732 // No binary shader formats are supported.
4733 return error(GL_INVALID_ENUM);
4734}
4735
4736void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4737{
4738 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4739 shader, count, string, length);
4740
4741 if(count < 0)
4742 {
4743 return error(GL_INVALID_VALUE);
4744 }
4745
4746 es2::Context *context = es2::getContext();
4747
4748 if(context)
4749 {
4750 es2::Shader *shaderObject = context->getShader(shader);
4751
4752 if(!shaderObject)
4753 {
4754 if(context->getProgram(shader))
4755 {
4756 return error(GL_INVALID_OPERATION);
4757 }
4758 else
4759 {
4760 return error(GL_INVALID_VALUE);
4761 }
4762 }
4763
4764 shaderObject->setSource(count, string, length);
4765 }
4766}
4767
4768void StencilFunc(GLenum func, GLint ref, GLuint mask)
4769{
4770 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4771}
4772
4773void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4774{
4775 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4776
4777 switch(face)
4778 {
4779 case GL_FRONT:
4780 case GL_BACK:
4781 case GL_FRONT_AND_BACK:
4782 break;
4783 default:
4784 return error(GL_INVALID_ENUM);
4785 }
4786
4787 switch(func)
4788 {
4789 case GL_NEVER:
4790 case GL_ALWAYS:
4791 case GL_LESS:
4792 case GL_LEQUAL:
4793 case GL_EQUAL:
4794 case GL_GEQUAL:
4795 case GL_GREATER:
4796 case GL_NOTEQUAL:
4797 break;
4798 default:
4799 return error(GL_INVALID_ENUM);
4800 }
4801
4802 es2::Context *context = es2::getContext();
4803
4804 if(context)
4805 {
4806 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4807 {
4808 context->setStencilParams(func, ref, mask);
4809 }
4810
4811 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4812 {
4813 context->setStencilBackParams(func, ref, mask);
4814 }
4815 }
4816}
4817
4818void StencilMask(GLuint mask)
4819{
4820 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4821}
4822
4823void StencilMaskSeparate(GLenum face, GLuint mask)
4824{
4825 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4826
4827 switch(face)
4828 {
4829 case GL_FRONT:
4830 case GL_BACK:
4831 case GL_FRONT_AND_BACK:
4832 break;
4833 default:
4834 return error(GL_INVALID_ENUM);
4835 }
4836
4837 es2::Context *context = es2::getContext();
4838
4839 if(context)
4840 {
4841 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4842 {
4843 context->setStencilWritemask(mask);
4844 }
4845
4846 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4847 {
4848 context->setStencilBackWritemask(mask);
4849 }
4850 }
4851}
4852
4853void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4854{
4855 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4856}
4857
4858void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4859{
4860 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4861 face, fail, zfail, zpass);
4862
4863 switch(face)
4864 {
4865 case GL_FRONT:
4866 case GL_BACK:
4867 case GL_FRONT_AND_BACK:
4868 break;
4869 default:
4870 return error(GL_INVALID_ENUM);
4871 }
4872
4873 switch(fail)
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(zfail)
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 switch(zpass)
4904 {
4905 case GL_ZERO:
4906 case GL_KEEP:
4907 case GL_REPLACE:
4908 case GL_INCR:
4909 case GL_DECR:
4910 case GL_INVERT:
4911 case GL_INCR_WRAP:
4912 case GL_DECR_WRAP:
4913 break;
4914 default:
4915 return error(GL_INVALID_ENUM);
4916 }
4917
4918 es2::Context *context = es2::getContext();
4919
4920 if(context)
4921 {
4922 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4923 {
4924 context->setStencilOperations(fail, zfail, zpass);
4925 }
4926
4927 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4928 {
4929 context->setStencilBackOperations(fail, zfail, zpass);
4930 }
4931 }
4932}
4933
4934GLboolean TestFenceNV(GLuint fence)
4935{
4936 TRACE("(GLuint fence = %d)", fence);
4937
4938 es2::Context *context = es2::getContext();
4939
4940 if(context)
4941 {
4942 es2::Fence *fenceObject = context->getFence(fence);
4943
4944 if(!fenceObject)
4945 {
4946 return error(GL_INVALID_OPERATION, GL_TRUE);
4947 }
4948
4949 return fenceObject->testFence();
4950 }
4951
4952 return GL_TRUE;
4953}
4954
4955void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004956 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004957{
4958 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004959 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4960 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004961
4962 if(!validImageSize(level, width, height))
4963 {
4964 return error(GL_INVALID_VALUE);
4965 }
4966
4967 es2::Context *context = es2::getContext();
4968
4969 if(context)
4970 {
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004971 // Core OpenGL ES 2.0 requires format and internalformat to be equal (checked below),
4972 // but GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
4973 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4974 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4975 {
4976 internalformat = GL_BGRA_EXT;
4977 }
4978
Nicolas Capens0bac2852016-05-07 06:09:58 -04004979 GLint clientVersion = context->getClientVersion();
4980 if(clientVersion < 3)
4981 {
Alexis Hetu2f113e32018-01-18 16:17:54 -05004982 if((internalformat != (GLint)format) &&
4983 !((type == GL_FLOAT) && (format == GL_RGBA) && (internalformat == GL_RGBA32F))) // CHROMIUM_color_buffer_float_rgba
Nicolas Capens0bac2852016-05-07 06:09:58 -04004984 {
4985 return error(GL_INVALID_OPERATION);
4986 }
4987 }
4988
Nicolas Capens894858a2018-03-22 00:55:23 -04004989 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, clientVersion);
Nicolas Capense65f5642018-02-26 17:47:06 -05004990 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004991 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004992 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004993 }
4994
4995 if(border != 0)
4996 {
4997 return error(GL_INVALID_VALUE);
4998 }
4999
5000 switch(target)
5001 {
Alexis Hetu46768622018-01-16 22:09:28 -05005002 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05005003 if(level != 0)
5004 {
5005 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
5006 }
Nicolas Capens894858a2018-03-22 00:55:23 -04005007 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05005008 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005009 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5010 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5011 {
5012 return error(GL_INVALID_VALUE);
5013 }
5014 break;
5015 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5016 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5017 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5018 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5019 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5020 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5021 if(width != height)
5022 {
5023 return error(GL_INVALID_VALUE);
5024 }
5025
5026 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5027 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5028 {
5029 return error(GL_INVALID_VALUE);
5030 }
5031 break;
5032 default:
5033 return error(GL_INVALID_ENUM);
5034 }
5035
Nicolas Capens5555af42017-12-14 13:14:03 -05005036 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005037 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005038 {
5039 return error(validationError);
5040 }
5041
Nicolas Capens894858a2018-03-22 00:55:23 -04005042 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
5043
Alexis Hetu46768622018-01-16 22:09:28 -05005044 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005045 {
Alexis Hetu46768622018-01-16 22:09:28 -05005046 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005047
5048 if(!texture)
5049 {
5050 return error(GL_INVALID_OPERATION);
5051 }
5052
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005053 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005054 }
5055 else
5056 {
5057 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5058
5059 if(!texture)
5060 {
5061 return error(GL_INVALID_OPERATION);
5062 }
5063
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005064 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005065 }
5066 }
5067}
5068
5069void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5070{
5071 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5072
5073 es2::Context *context = es2::getContext();
5074
5075 if(context)
5076 {
5077 es2::Texture *texture;
5078
5079 GLint clientVersion = context->getClientVersion();
5080
5081 switch(target)
5082 {
5083 case GL_TEXTURE_2D:
5084 texture = context->getTexture2D();
5085 break;
5086 case GL_TEXTURE_2D_ARRAY:
5087 if(clientVersion < 3)
5088 {
5089 return error(GL_INVALID_ENUM);
5090 }
5091 else
5092 {
5093 texture = context->getTexture2DArray();
5094 }
5095 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005096 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005097 texture = context->getTexture3D();
5098 break;
5099 case GL_TEXTURE_CUBE_MAP:
5100 texture = context->getTextureCubeMap();
5101 break;
5102 case GL_TEXTURE_EXTERNAL_OES:
5103 texture = context->getTextureExternal();
5104 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005105 case GL_TEXTURE_RECTANGLE_ARB:
5106 texture = context->getTexture2DRect();
5107 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005108 default:
5109 return error(GL_INVALID_ENUM);
5110 }
5111
5112 switch(pname)
5113 {
5114 case GL_TEXTURE_WRAP_S:
5115 if(!texture->setWrapS((GLenum)param))
5116 {
5117 return error(GL_INVALID_ENUM);
5118 }
5119 break;
5120 case GL_TEXTURE_WRAP_T:
5121 if(!texture->setWrapT((GLenum)param))
5122 {
5123 return error(GL_INVALID_ENUM);
5124 }
5125 break;
5126 case GL_TEXTURE_WRAP_R_OES:
5127 if(!texture->setWrapR((GLenum)param))
5128 {
5129 return error(GL_INVALID_ENUM);
5130 }
5131 break;
5132 case GL_TEXTURE_MIN_FILTER:
5133 if(!texture->setMinFilter((GLenum)param))
5134 {
5135 return error(GL_INVALID_ENUM);
5136 }
5137 break;
5138 case GL_TEXTURE_MAG_FILTER:
5139 if(!texture->setMagFilter((GLenum)param))
5140 {
5141 return error(GL_INVALID_ENUM);
5142 }
5143 break;
5144 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5145 if(!texture->setMaxAnisotropy(param))
5146 {
5147 return error(GL_INVALID_VALUE);
5148 }
5149 break;
5150 case GL_TEXTURE_BASE_LEVEL:
5151 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5152 {
5153 return error(GL_INVALID_VALUE);
5154 }
5155 break;
5156 case GL_TEXTURE_COMPARE_FUNC:
5157 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5158 {
5159 return error(GL_INVALID_VALUE);
5160 }
5161 break;
5162 case GL_TEXTURE_COMPARE_MODE:
5163 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5164 {
5165 return error(GL_INVALID_VALUE);
5166 }
5167 break;
5168 case GL_TEXTURE_MAX_LEVEL:
5169 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5170 {
5171 return error(GL_INVALID_VALUE);
5172 }
5173 break;
5174 case GL_TEXTURE_MAX_LOD:
5175 if(clientVersion < 3 || !texture->setMaxLOD(param))
5176 {
5177 return error(GL_INVALID_VALUE);
5178 }
5179 break;
5180 case GL_TEXTURE_MIN_LOD:
5181 if(clientVersion < 3 || !texture->setMinLOD(param))
5182 {
5183 return error(GL_INVALID_VALUE);
5184 }
5185 break;
5186 case GL_TEXTURE_SWIZZLE_R:
5187 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5188 {
5189 return error(GL_INVALID_VALUE);
5190 }
5191 break;
5192 case GL_TEXTURE_SWIZZLE_G:
5193 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5194 {
5195 return error(GL_INVALID_VALUE);
5196 }
5197 break;
5198 case GL_TEXTURE_SWIZZLE_B:
5199 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5200 {
5201 return error(GL_INVALID_VALUE);
5202 }
5203 break;
5204 case GL_TEXTURE_SWIZZLE_A:
5205 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5206 {
5207 return error(GL_INVALID_VALUE);
5208 }
5209 break;
5210 default:
5211 return error(GL_INVALID_ENUM);
5212 }
5213 }
5214}
5215
5216void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5217{
5218 glTexParameterf(target, pname, *params);
5219}
5220
5221void TexParameteri(GLenum target, GLenum pname, GLint param)
5222{
5223 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5224
5225 es2::Context *context = es2::getContext();
5226
5227 if(context)
5228 {
5229 es2::Texture *texture;
5230
5231 GLint clientVersion = context->getClientVersion();
5232
5233 switch(target)
5234 {
5235 case GL_TEXTURE_2D:
5236 texture = context->getTexture2D();
5237 break;
5238 case GL_TEXTURE_2D_ARRAY:
5239 if(clientVersion < 3)
5240 {
5241 return error(GL_INVALID_ENUM);
5242 }
5243 else
5244 {
5245 texture = context->getTexture2DArray();
5246 }
5247 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005248 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005249 texture = context->getTexture3D();
5250 break;
5251 case GL_TEXTURE_CUBE_MAP:
5252 texture = context->getTextureCubeMap();
5253 break;
5254 case GL_TEXTURE_EXTERNAL_OES:
5255 texture = context->getTextureExternal();
5256 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005257 case GL_TEXTURE_RECTANGLE_ARB:
5258 texture = context->getTexture2DRect();
5259 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005260 default:
5261 return error(GL_INVALID_ENUM);
5262 }
5263
5264 switch(pname)
5265 {
5266 case GL_TEXTURE_WRAP_S:
5267 if(!texture->setWrapS((GLenum)param))
5268 {
5269 return error(GL_INVALID_ENUM);
5270 }
5271 break;
5272 case GL_TEXTURE_WRAP_T:
5273 if(!texture->setWrapT((GLenum)param))
5274 {
5275 return error(GL_INVALID_ENUM);
5276 }
5277 break;
5278 case GL_TEXTURE_WRAP_R_OES:
5279 if(!texture->setWrapR((GLenum)param))
5280 {
5281 return error(GL_INVALID_ENUM);
5282 }
5283 break;
5284 case GL_TEXTURE_MIN_FILTER:
5285 if(!texture->setMinFilter((GLenum)param))
5286 {
5287 return error(GL_INVALID_ENUM);
5288 }
5289 break;
5290 case GL_TEXTURE_MAG_FILTER:
5291 if(!texture->setMagFilter((GLenum)param))
5292 {
5293 return error(GL_INVALID_ENUM);
5294 }
5295 break;
5296 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5297 if(!texture->setMaxAnisotropy((GLfloat)param))
5298 {
5299 return error(GL_INVALID_VALUE);
5300 }
5301 break;
5302 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05005303 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
5304 {
5305 return error(GL_INVALID_OPERATION); // Base level has to be 0
5306 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005307 if(clientVersion < 3 || !texture->setBaseLevel(param))
5308 {
5309 return error(GL_INVALID_VALUE);
5310 }
5311 break;
5312 case GL_TEXTURE_COMPARE_FUNC:
5313 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5314 {
5315 return error(GL_INVALID_VALUE);
5316 }
5317 break;
5318 case GL_TEXTURE_COMPARE_MODE:
5319 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5320 {
5321 return error(GL_INVALID_VALUE);
5322 }
5323 break;
5324 case GL_TEXTURE_MAX_LEVEL:
5325 if(clientVersion < 3 || !texture->setMaxLevel(param))
5326 {
5327 return error(GL_INVALID_VALUE);
5328 }
5329 break;
5330 case GL_TEXTURE_MAX_LOD:
5331 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5332 {
5333 return error(GL_INVALID_VALUE);
5334 }
5335 break;
5336 case GL_TEXTURE_MIN_LOD:
5337 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5338 {
5339 return error(GL_INVALID_VALUE);
5340 }
5341 break;
5342 case GL_TEXTURE_SWIZZLE_R:
5343 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5344 {
5345 return error(GL_INVALID_VALUE);
5346 }
5347 break;
5348 case GL_TEXTURE_SWIZZLE_G:
5349 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5350 {
5351 return error(GL_INVALID_VALUE);
5352 }
5353 break;
5354 case GL_TEXTURE_SWIZZLE_B:
5355 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5356 {
5357 return error(GL_INVALID_VALUE);
5358 }
5359 break;
5360 case GL_TEXTURE_SWIZZLE_A:
5361 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5362 {
5363 return error(GL_INVALID_VALUE);
5364 }
5365 break;
5366 default:
5367 return error(GL_INVALID_ENUM);
5368 }
5369 }
5370}
5371
5372void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5373{
5374 glTexParameteri(target, pname, *params);
5375}
5376
5377void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005378 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005379{
5380 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5381 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005382 "const GLvoid* data = %p)",
5383 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005384
5385 if(!es2::IsTextureTarget(target))
5386 {
5387 return error(GL_INVALID_ENUM);
5388 }
5389
5390 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5391 {
5392 return error(GL_INVALID_VALUE);
5393 }
5394
5395 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5396 {
5397 return error(GL_INVALID_VALUE);
5398 }
5399
5400 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5401 {
5402 return error(GL_INVALID_VALUE);
5403 }
5404
Nicolas Capens0bac2852016-05-07 06:09:58 -04005405 es2::Context *context = es2::getContext();
5406
5407 if(context)
5408 {
Alexis Hetu46768622018-01-16 22:09:28 -05005409 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005410 {
Alexis Hetu46768622018-01-16 22:09:28 -05005411 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005412
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005413 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005414 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005415 {
5416 return error(validationError);
5417 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005418
Nicolas Capens5555af42017-12-14 13:14:03 -05005419 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005420 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005421 {
5422 return error(validationError);
5423 }
5424
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005425 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005426 }
5427 else if(es2::IsCubemapTextureTarget(target))
5428 {
5429 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5430
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005431 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05005432 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005433 {
5434 return error(validationError);
5435 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005436
Nicolas Capens5555af42017-12-14 13:14:03 -05005437 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005438 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005439 {
5440 return error(validationError);
5441 }
5442
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005443 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005444 }
5445 else UNREACHABLE(target);
5446 }
5447}
5448
5449void Uniform1f(GLint location, GLfloat x)
5450{
5451 glUniform1fv(location, 1, &x);
5452}
5453
5454void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5455{
5456 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5457
5458 if(count < 0)
5459 {
5460 return error(GL_INVALID_VALUE);
5461 }
5462
Nicolas Capens0bac2852016-05-07 06:09:58 -04005463 es2::Context *context = es2::getContext();
5464
5465 if(context)
5466 {
5467 es2::Program *program = context->getCurrentProgram();
5468
5469 if(!program)
5470 {
5471 return error(GL_INVALID_OPERATION);
5472 }
5473
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005474 if(location == -1)
5475 {
5476 return;
5477 }
5478
Nicolas Capens0bac2852016-05-07 06:09:58 -04005479 if(!program->setUniform1fv(location, count, v))
5480 {
5481 return error(GL_INVALID_OPERATION);
5482 }
5483 }
5484}
5485
5486void Uniform1i(GLint location, GLint x)
5487{
5488 glUniform1iv(location, 1, &x);
5489}
5490
5491void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5492{
5493 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5494
5495 if(count < 0)
5496 {
5497 return error(GL_INVALID_VALUE);
5498 }
5499
Nicolas Capens0bac2852016-05-07 06:09:58 -04005500 es2::Context *context = es2::getContext();
5501
5502 if(context)
5503 {
5504 es2::Program *program = context->getCurrentProgram();
5505
5506 if(!program)
5507 {
5508 return error(GL_INVALID_OPERATION);
5509 }
5510
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005511 if(location == -1)
5512 {
5513 return;
5514 }
5515
Nicolas Capens0bac2852016-05-07 06:09:58 -04005516 if(!program->setUniform1iv(location, count, v))
5517 {
5518 return error(GL_INVALID_OPERATION);
5519 }
5520 }
5521}
5522
5523void Uniform2f(GLint location, GLfloat x, GLfloat y)
5524{
5525 GLfloat xy[2] = {x, y};
5526
5527 glUniform2fv(location, 1, (GLfloat*)&xy);
5528}
5529
5530void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5531{
5532 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5533
5534 if(count < 0)
5535 {
5536 return error(GL_INVALID_VALUE);
5537 }
5538
Nicolas Capens0bac2852016-05-07 06:09:58 -04005539 es2::Context *context = es2::getContext();
5540
5541 if(context)
5542 {
5543 es2::Program *program = context->getCurrentProgram();
5544
5545 if(!program)
5546 {
5547 return error(GL_INVALID_OPERATION);
5548 }
5549
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005550 if(location == -1)
5551 {
5552 return;
5553 }
5554
Nicolas Capens0bac2852016-05-07 06:09:58 -04005555 if(!program->setUniform2fv(location, count, v))
5556 {
5557 return error(GL_INVALID_OPERATION);
5558 }
5559 }
5560}
5561
5562void Uniform2i(GLint location, GLint x, GLint y)
5563{
5564 GLint xy[4] = {x, y};
5565
5566 glUniform2iv(location, 1, (GLint*)&xy);
5567}
5568
5569void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5570{
5571 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5572
5573 if(count < 0)
5574 {
5575 return error(GL_INVALID_VALUE);
5576 }
5577
Nicolas Capens0bac2852016-05-07 06:09:58 -04005578 es2::Context *context = es2::getContext();
5579
5580 if(context)
5581 {
5582 es2::Program *program = context->getCurrentProgram();
5583
5584 if(!program)
5585 {
5586 return error(GL_INVALID_OPERATION);
5587 }
5588
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005589 if(location == -1)
5590 {
5591 return;
5592 }
5593
Nicolas Capens0bac2852016-05-07 06:09:58 -04005594 if(!program->setUniform2iv(location, count, v))
5595 {
5596 return error(GL_INVALID_OPERATION);
5597 }
5598 }
5599}
5600
5601void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5602{
5603 GLfloat xyz[3] = {x, y, z};
5604
5605 glUniform3fv(location, 1, (GLfloat*)&xyz);
5606}
5607
5608void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5609{
5610 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5611
5612 if(count < 0)
5613 {
5614 return error(GL_INVALID_VALUE);
5615 }
5616
Nicolas Capens0bac2852016-05-07 06:09:58 -04005617 es2::Context *context = es2::getContext();
5618
5619 if(context)
5620 {
5621 es2::Program *program = context->getCurrentProgram();
5622
5623 if(!program)
5624 {
5625 return error(GL_INVALID_OPERATION);
5626 }
5627
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005628 if(location == -1)
5629 {
5630 return;
5631 }
5632
Nicolas Capens0bac2852016-05-07 06:09:58 -04005633 if(!program->setUniform3fv(location, count, v))
5634 {
5635 return error(GL_INVALID_OPERATION);
5636 }
5637 }
5638}
5639
5640void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5641{
5642 GLint xyz[3] = {x, y, z};
5643
5644 glUniform3iv(location, 1, (GLint*)&xyz);
5645}
5646
5647void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5648{
5649 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5650
5651 if(count < 0)
5652 {
5653 return error(GL_INVALID_VALUE);
5654 }
5655
Nicolas Capens0bac2852016-05-07 06:09:58 -04005656 es2::Context *context = es2::getContext();
5657
5658 if(context)
5659 {
5660 es2::Program *program = context->getCurrentProgram();
5661
5662 if(!program)
5663 {
5664 return error(GL_INVALID_OPERATION);
5665 }
5666
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005667 if(location == -1)
5668 {
5669 return;
5670 }
5671
Nicolas Capens0bac2852016-05-07 06:09:58 -04005672 if(!program->setUniform3iv(location, count, v))
5673 {
5674 return error(GL_INVALID_OPERATION);
5675 }
5676 }
5677}
5678
5679void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5680{
5681 GLfloat xyzw[4] = {x, y, z, w};
5682
5683 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5684}
5685
5686void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5687{
5688 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5689
5690 if(count < 0)
5691 {
5692 return error(GL_INVALID_VALUE);
5693 }
5694
Nicolas Capens0bac2852016-05-07 06:09:58 -04005695 es2::Context *context = es2::getContext();
5696
5697 if(context)
5698 {
5699 es2::Program *program = context->getCurrentProgram();
5700
5701 if(!program)
5702 {
5703 return error(GL_INVALID_OPERATION);
5704 }
5705
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005706 if(location == -1)
5707 {
5708 return;
5709 }
5710
Nicolas Capens0bac2852016-05-07 06:09:58 -04005711 if(!program->setUniform4fv(location, count, v))
5712 {
5713 return error(GL_INVALID_OPERATION);
5714 }
5715 }
5716}
5717
5718void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5719{
5720 GLint xyzw[4] = {x, y, z, w};
5721
5722 glUniform4iv(location, 1, (GLint*)&xyzw);
5723}
5724
5725void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5726{
5727 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5728
5729 if(count < 0)
5730 {
5731 return error(GL_INVALID_VALUE);
5732 }
5733
Nicolas Capens0bac2852016-05-07 06:09:58 -04005734 es2::Context *context = es2::getContext();
5735
5736 if(context)
5737 {
5738 es2::Program *program = context->getCurrentProgram();
5739
5740 if(!program)
5741 {
5742 return error(GL_INVALID_OPERATION);
5743 }
5744
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005745 if(location == -1)
5746 {
5747 return;
5748 }
5749
Nicolas Capens0bac2852016-05-07 06:09:58 -04005750 if(!program->setUniform4iv(location, count, v))
5751 {
5752 return error(GL_INVALID_OPERATION);
5753 }
5754 }
5755}
5756
5757void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5758{
5759 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5760 location, count, transpose, value);
5761
5762 if(count < 0)
5763 {
5764 return error(GL_INVALID_VALUE);
5765 }
5766
Nicolas Capens0bac2852016-05-07 06:09:58 -04005767 es2::Context *context = es2::getContext();
5768
5769 if(context)
5770 {
5771 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5772 {
5773 return error(GL_INVALID_VALUE);
5774 }
5775
5776 es2::Program *program = context->getCurrentProgram();
5777
5778 if(!program)
5779 {
5780 return error(GL_INVALID_OPERATION);
5781 }
5782
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005783 if(location == -1)
5784 {
5785 return;
5786 }
5787
Nicolas Capens0bac2852016-05-07 06:09:58 -04005788 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5789 {
5790 return error(GL_INVALID_OPERATION);
5791 }
5792 }
5793}
5794
5795void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5796{
5797 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5798 location, count, transpose, value);
5799
5800 if(count < 0)
5801 {
5802 return error(GL_INVALID_VALUE);
5803 }
5804
Nicolas Capens0bac2852016-05-07 06:09:58 -04005805 es2::Context *context = es2::getContext();
5806
5807 if(context)
5808 {
5809 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5810 {
5811 return error(GL_INVALID_VALUE);
5812 }
5813
5814 es2::Program *program = context->getCurrentProgram();
5815
5816 if(!program)
5817 {
5818 return error(GL_INVALID_OPERATION);
5819 }
5820
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005821 if(location == -1)
5822 {
5823 return;
5824 }
5825
Nicolas Capens0bac2852016-05-07 06:09:58 -04005826 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5827 {
5828 return error(GL_INVALID_OPERATION);
5829 }
5830 }
5831}
5832
5833void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5834{
5835 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5836 location, count, transpose, value);
5837
5838 if(count < 0)
5839 {
5840 return error(GL_INVALID_VALUE);
5841 }
5842
Nicolas Capens0bac2852016-05-07 06:09:58 -04005843 es2::Context *context = es2::getContext();
5844
5845 if(context)
5846 {
5847 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5848 {
5849 return error(GL_INVALID_VALUE);
5850 }
5851
5852 es2::Program *program = context->getCurrentProgram();
5853
5854 if(!program)
5855 {
5856 return error(GL_INVALID_OPERATION);
5857 }
5858
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005859 if(location == -1)
5860 {
5861 return;
5862 }
5863
Nicolas Capens0bac2852016-05-07 06:09:58 -04005864 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5865 {
5866 return error(GL_INVALID_OPERATION);
5867 }
5868 }
5869}
5870
5871void UseProgram(GLuint program)
5872{
5873 TRACE("(GLuint program = %d)", program);
5874
5875 es2::Context *context = es2::getContext();
5876
5877 if(context)
5878 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005879 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5880 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5881 {
5882 return error(GL_INVALID_OPERATION);
5883 }
5884
Nicolas Capens0bac2852016-05-07 06:09:58 -04005885 es2::Program *programObject = context->getProgram(program);
5886
5887 if(!programObject && program != 0)
5888 {
5889 if(context->getShader(program))
5890 {
5891 return error(GL_INVALID_OPERATION);
5892 }
5893 else
5894 {
5895 return error(GL_INVALID_VALUE);
5896 }
5897 }
5898
5899 if(program != 0 && !programObject->isLinked())
5900 {
5901 return error(GL_INVALID_OPERATION);
5902 }
5903
5904 context->useProgram(program);
5905 }
5906}
5907
5908void ValidateProgram(GLuint program)
5909{
5910 TRACE("(GLuint program = %d)", program);
5911
5912 es2::Context *context = es2::getContext();
5913
5914 if(context)
5915 {
5916 es2::Program *programObject = context->getProgram(program);
5917
5918 if(!programObject)
5919 {
5920 if(context->getShader(program))
5921 {
5922 return error(GL_INVALID_OPERATION);
5923 }
5924 else
5925 {
5926 return error(GL_INVALID_VALUE);
5927 }
5928 }
5929
Ben Vanik1fd3b282017-07-10 14:08:12 -07005930 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005931 }
5932}
5933
5934void VertexAttrib1f(GLuint index, GLfloat x)
5935{
5936 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5937
5938 if(index >= es2::MAX_VERTEX_ATTRIBS)
5939 {
5940 return error(GL_INVALID_VALUE);
5941 }
5942
5943 es2::Context *context = es2::getContext();
5944
5945 if(context)
5946 {
5947 GLfloat vals[4] = { x, 0, 0, 1 };
5948 context->setVertexAttrib(index, vals);
5949 }
5950}
5951
5952void VertexAttrib1fv(GLuint index, const GLfloat* values)
5953{
5954 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5955
5956 if(index >= es2::MAX_VERTEX_ATTRIBS)
5957 {
5958 return error(GL_INVALID_VALUE);
5959 }
5960
5961 es2::Context *context = es2::getContext();
5962
5963 if(context)
5964 {
5965 GLfloat vals[4] = { values[0], 0, 0, 1 };
5966 context->setVertexAttrib(index, vals);
5967 }
5968}
5969
5970void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5971{
5972 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5973
5974 if(index >= es2::MAX_VERTEX_ATTRIBS)
5975 {
5976 return error(GL_INVALID_VALUE);
5977 }
5978
5979 es2::Context *context = es2::getContext();
5980
5981 if(context)
5982 {
5983 GLfloat vals[4] = { x, y, 0, 1 };
5984 context->setVertexAttrib(index, vals);
5985 }
5986}
5987
5988void VertexAttrib2fv(GLuint index, const GLfloat* values)
5989{
5990 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5991
5992 if(index >= es2::MAX_VERTEX_ATTRIBS)
5993 {
5994 return error(GL_INVALID_VALUE);
5995 }
5996
5997 es2::Context *context = es2::getContext();
5998
5999 if(context)
6000 {
6001 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6002 context->setVertexAttrib(index, vals);
6003 }
6004}
6005
6006void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6007{
6008 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
6009
6010 if(index >= es2::MAX_VERTEX_ATTRIBS)
6011 {
6012 return error(GL_INVALID_VALUE);
6013 }
6014
6015 es2::Context *context = es2::getContext();
6016
6017 if(context)
6018 {
6019 GLfloat vals[4] = { x, y, z, 1 };
6020 context->setVertexAttrib(index, vals);
6021 }
6022}
6023
6024void VertexAttrib3fv(GLuint index, const GLfloat* values)
6025{
6026 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6027
6028 if(index >= es2::MAX_VERTEX_ATTRIBS)
6029 {
6030 return error(GL_INVALID_VALUE);
6031 }
6032
6033 es2::Context *context = es2::getContext();
6034
6035 if(context)
6036 {
6037 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6038 context->setVertexAttrib(index, vals);
6039 }
6040}
6041
6042void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6043{
6044 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6045
6046 if(index >= es2::MAX_VERTEX_ATTRIBS)
6047 {
6048 return error(GL_INVALID_VALUE);
6049 }
6050
6051 es2::Context *context = es2::getContext();
6052
6053 if(context)
6054 {
6055 GLfloat vals[4] = { x, y, z, w };
6056 context->setVertexAttrib(index, vals);
6057 }
6058}
6059
6060void VertexAttrib4fv(GLuint index, const GLfloat* values)
6061{
6062 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6063
6064 if(index >= es2::MAX_VERTEX_ATTRIBS)
6065 {
6066 return error(GL_INVALID_VALUE);
6067 }
6068
6069 es2::Context *context = es2::getContext();
6070
6071 if(context)
6072 {
6073 context->setVertexAttrib(index, values);
6074 }
6075}
6076
6077void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6078{
6079 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6080 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6081 index, size, type, normalized, stride, ptr);
6082
6083 if(index >= es2::MAX_VERTEX_ATTRIBS)
6084 {
6085 return error(GL_INVALID_VALUE);
6086 }
6087
6088 if(size < 1 || size > 4)
6089 {
6090 return error(GL_INVALID_VALUE);
6091 }
6092
6093 GLint clientVersion = egl::getClientVersion();
6094
6095 switch(type)
6096 {
6097 case GL_BYTE:
6098 case GL_UNSIGNED_BYTE:
6099 case GL_SHORT:
6100 case GL_UNSIGNED_SHORT:
6101 case GL_FIXED:
6102 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006103 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006104 break;
6105 case GL_INT_2_10_10_10_REV:
6106 case GL_UNSIGNED_INT_2_10_10_10_REV:
6107 if(clientVersion >= 3)
6108 {
6109 if(size != 4)
6110 {
6111 return error(GL_INVALID_OPERATION);
6112 }
6113 break;
6114 }
6115 else return error(GL_INVALID_ENUM);
6116 case GL_INT:
6117 case GL_UNSIGNED_INT:
6118 case GL_HALF_FLOAT:
6119 if(clientVersion >= 3)
6120 {
6121 break;
6122 }
6123 else return error(GL_INVALID_ENUM);
6124 default:
6125 return error(GL_INVALID_ENUM);
6126 }
6127
6128 if(stride < 0)
6129 {
6130 return error(GL_INVALID_VALUE);
6131 }
6132
6133 es2::Context *context = es2::getContext();
6134
6135 if(context)
6136 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006137 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6138 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6139 {
6140 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6141 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6142 return error(GL_INVALID_OPERATION);
6143 }
6144
Alexis Hetu6f284032017-12-11 15:19:36 -05006145 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006146 }
6147}
6148
6149void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6150{
6151 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6152
6153 if(width < 0 || height < 0)
6154 {
6155 return error(GL_INVALID_VALUE);
6156 }
6157
6158 es2::Context *context = es2::getContext();
6159
6160 if(context)
6161 {
6162 context->setViewportParams(x, y, width, height);
6163 }
6164}
6165
Alexis Hetub9dda642016-10-06 11:25:32 -04006166static 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 -04006167{
6168 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6169 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6170 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6171 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6172
6173 switch(filter)
6174 {
6175 case GL_NEAREST:
6176 break;
6177 default:
6178 return error(GL_INVALID_ENUM);
6179 }
6180
6181 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6182 {
6183 return error(GL_INVALID_VALUE);
6184 }
6185
6186 es2::Context *context = es2::getContext();
6187
6188 if(context)
6189 {
6190 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6191 {
6192 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6193 return error(GL_INVALID_OPERATION);
6194 }
6195
Alexis Hetub9dda642016-10-06 11:25:32 -04006196 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006197 }
6198}
6199
Alexis Hetub9dda642016-10-06 11:25:32 -04006200void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6201{
6202 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6203}
6204
Nicolas Capens0bac2852016-05-07 06:09:58 -04006205void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6206 GLbitfield mask, GLenum filter)
6207{
6208 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6209 {
6210 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6211 return error(GL_INVALID_OPERATION);
6212 }
6213
Alexis Hetub9dda642016-10-06 11:25:32 -04006214 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006215}
6216
6217void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006218 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006219{
6220 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6221 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006222 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6223 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006224
6225 switch(target)
6226 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006227 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006228 switch(format)
6229 {
6230 case GL_DEPTH_COMPONENT:
6231 case GL_DEPTH_STENCIL_OES:
6232 return error(GL_INVALID_OPERATION);
6233 default:
6234 break;
6235 }
6236 break;
6237 default:
6238 return error(GL_INVALID_ENUM);
6239 }
6240
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006241 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006242 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006243 return error(GL_INVALID_OPERATION);
6244 }
6245
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006246 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target, egl::getClientVersion());
Nicolas Capense65f5642018-02-26 17:47:06 -05006247 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006248 {
6249 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006250 }
6251
6252 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6253 {
6254 return error(GL_INVALID_VALUE);
6255 }
6256
6257 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6258 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6259 {
6260 return error(GL_INVALID_VALUE);
6261 }
6262
6263 if(border != 0)
6264 {
6265 return error(GL_INVALID_VALUE);
6266 }
6267
6268 es2::Context *context = es2::getContext();
6269
6270 if(context)
6271 {
6272 es2::Texture3D *texture = context->getTexture3D();
6273
6274 if(!texture)
6275 {
6276 return error(GL_INVALID_OPERATION);
6277 }
6278
Nicolas Capens2fc90512018-01-23 22:24:22 +00006279 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006280 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006281 {
6282 return error(validationError);
6283 }
6284
Nicolas Capens894858a2018-03-22 00:55:23 -04006285 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006286 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006287 }
6288}
6289
Alexis Hetu53f48092016-06-17 14:08:06 -04006290void 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 -04006291{
6292 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6293 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006294 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6295 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006296
6297 switch(target)
6298 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006299 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006300 break;
6301 default:
6302 return error(GL_INVALID_ENUM);
6303 }
6304
Nicolas Capens0bac2852016-05-07 06:09:58 -04006305 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6306 {
6307 return error(GL_INVALID_VALUE);
6308 }
6309
6310 if((width < 0) || (height < 0) || (depth < 0))
6311 {
6312 return error(GL_INVALID_VALUE);
6313 }
6314
6315 es2::Context *context = es2::getContext();
6316
6317 if(context)
6318 {
6319 es2::Texture3D *texture = context->getTexture3D();
6320
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006321 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 -05006322 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006323 {
6324 return error(validationError);
6325 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006326
Nicolas Capens5555af42017-12-14 13:14:03 -05006327 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05006328 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006329 {
6330 return error(validationError);
6331 }
6332
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006333 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006334 }
6335}
6336
6337void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6338{
6339 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6340 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6341 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6342
6343 switch(target)
6344 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006345 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006346 break;
6347 default:
6348 return error(GL_INVALID_ENUM);
6349 }
6350
6351 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6352 {
6353 return error(GL_INVALID_VALUE);
6354 }
6355
6356 es2::Context *context = es2::getContext();
6357
6358 if(context)
6359 {
6360 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6361
6362 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6363 {
6364 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6365 }
6366
6367 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6368
6369 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6370 {
6371 return error(GL_INVALID_OPERATION);
6372 }
6373
6374 es2::Texture3D *texture = context->getTexture3D();
6375
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006376 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 -05006377 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006378 {
6379 return error(validationError);
6380 }
6381
Nicolas Capens1529c2c2018-02-06 14:44:47 -05006382 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006383 }
6384}
6385
6386void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6387{
6388 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6389 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6390 target, level, internalformat, width, height, depth, border, imageSize, data);
6391
6392 switch(target)
6393 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006394 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006395 break;
6396 default:
6397 return error(GL_INVALID_ENUM);
6398 }
6399
6400 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6401 {
6402 return error(GL_INVALID_VALUE);
6403 }
6404
6405 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6406 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6407 {
6408 return error(GL_INVALID_VALUE);
6409 }
6410
Nicolas Capens03589982018-02-01 17:28:32 -05006411 if(!IsCompressed(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006412 {
Nicolas Capens03589982018-02-01 17:28:32 -05006413 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006414 }
6415
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006416 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006417 {
6418 return error(GL_INVALID_VALUE);
6419 }
6420
6421 es2::Context *context = es2::getContext();
6422
6423 if(context)
6424 {
6425 es2::Texture3D *texture = context->getTexture3D();
6426
6427 if(!texture)
6428 {
6429 return error(GL_INVALID_OPERATION);
6430 }
6431
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006432 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006433
Nicolas Capense65f5642018-02-26 17:47:06 -05006434 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006435 {
6436 return error(validationError);
6437 }
6438
Nicolas Capens0bac2852016-05-07 06:09:58 -04006439 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6440 }
6441}
6442
6443void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6444{
6445 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6446 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6447 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6448 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6449
6450 switch(target)
6451 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006452 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006453 break;
6454 default:
6455 return error(GL_INVALID_ENUM);
6456 }
6457
6458 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6459 {
6460 return error(GL_INVALID_VALUE);
6461 }
6462
6463 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6464 {
6465 return error(GL_INVALID_VALUE);
6466 }
6467
Nicolas Capens03589982018-02-01 17:28:32 -05006468 if(!IsCompressed(format, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006469 {
Nicolas Capens03589982018-02-01 17:28:32 -05006470 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006471 }
6472
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006473 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006474 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006475 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006476 }
6477
6478 es2::Context *context = es2::getContext();
6479
6480 if(context)
6481 {
6482 es2::Texture3D *texture = context->getTexture3D();
6483
6484 if(!texture)
6485 {
6486 return error(GL_INVALID_OPERATION);
6487 }
6488
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006489 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05006490 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006491 {
6492 return error(validationError);
6493 }
6494
6495 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006496 }
6497}
6498
6499void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6500{
6501 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6502 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6503
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006504 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006505 {
6506 return error(GL_INVALID_ENUM);
6507 }
6508
6509 es2::Context *context = es2::getContext();
6510
6511 if(context)
6512 {
6513 if(texture == 0)
6514 {
6515 textarget = GL_NONE;
6516 }
6517 else
6518 {
6519 es2::Texture *tex = context->getTexture(texture);
6520
6521 if(!tex)
6522 {
6523 return error(GL_INVALID_OPERATION);
6524 }
6525
6526 if(tex->isCompressed(textarget, level))
6527 {
6528 return error(GL_INVALID_OPERATION);
6529 }
6530
6531 switch(textarget)
6532 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006533 case GL_TEXTURE_3D:
6534 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006535 {
6536 return error(GL_INVALID_OPERATION);
6537 }
6538 break;
6539 default:
6540 return error(GL_INVALID_ENUM);
6541 }
6542
6543 if(level != 0)
6544 {
6545 return error(GL_INVALID_VALUE);
6546 }
6547 }
6548
6549 es2::Framebuffer *framebuffer = nullptr;
6550 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006551 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006552 {
6553 framebuffer = context->getReadFramebuffer();
6554 framebufferName = context->getReadFramebufferName();
6555 }
6556 else
6557 {
6558 framebuffer = context->getDrawFramebuffer();
6559 framebufferName = context->getDrawFramebufferName();
6560 }
6561
6562 if(framebufferName == 0 || !framebuffer)
6563 {
6564 return error(GL_INVALID_OPERATION);
6565 }
6566
6567 GLint clientVersion = context->getClientVersion();
6568
6569 switch(attachment)
6570 {
6571 case GL_COLOR_ATTACHMENT1:
6572 case GL_COLOR_ATTACHMENT2:
6573 case GL_COLOR_ATTACHMENT3:
6574 case GL_COLOR_ATTACHMENT4:
6575 case GL_COLOR_ATTACHMENT5:
6576 case GL_COLOR_ATTACHMENT6:
6577 case GL_COLOR_ATTACHMENT7:
6578 case GL_COLOR_ATTACHMENT8:
6579 case GL_COLOR_ATTACHMENT9:
6580 case GL_COLOR_ATTACHMENT10:
6581 case GL_COLOR_ATTACHMENT11:
6582 case GL_COLOR_ATTACHMENT12:
6583 case GL_COLOR_ATTACHMENT13:
6584 case GL_COLOR_ATTACHMENT14:
6585 case GL_COLOR_ATTACHMENT15:
6586 case GL_COLOR_ATTACHMENT16:
6587 case GL_COLOR_ATTACHMENT17:
6588 case GL_COLOR_ATTACHMENT18:
6589 case GL_COLOR_ATTACHMENT19:
6590 case GL_COLOR_ATTACHMENT20:
6591 case GL_COLOR_ATTACHMENT21:
6592 case GL_COLOR_ATTACHMENT22:
6593 case GL_COLOR_ATTACHMENT23:
6594 case GL_COLOR_ATTACHMENT24:
6595 case GL_COLOR_ATTACHMENT25:
6596 case GL_COLOR_ATTACHMENT26:
6597 case GL_COLOR_ATTACHMENT27:
6598 case GL_COLOR_ATTACHMENT28:
6599 case GL_COLOR_ATTACHMENT29:
6600 case GL_COLOR_ATTACHMENT30:
6601 case GL_COLOR_ATTACHMENT31:
6602 if(clientVersion < 3)
6603 {
6604 return error(GL_INVALID_ENUM);
6605 }
6606 // fall through
6607 case GL_COLOR_ATTACHMENT0:
6608 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6609 {
6610 return error(GL_INVALID_ENUM);
6611 }
6612 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6613 break;
6614 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6615 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6616 default:
6617 return error(GL_INVALID_ENUM);
6618 }
6619 }
6620}
6621
6622void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6623{
6624 if(egl::getClientVersion() == 1)
6625 {
6626 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6627 }
6628
6629 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6630
6631 switch(target)
6632 {
6633 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006634 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006635 case GL_TEXTURE_EXTERNAL_OES:
6636 break;
6637 default:
6638 return error(GL_INVALID_ENUM);
6639 }
6640
Nicolas Capens0bac2852016-05-07 06:09:58 -04006641 es2::Context *context = es2::getContext();
6642
6643 if(context)
6644 {
Alexis Hetu46768622018-01-16 22:09:28 -05006645 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006646
6647 if(!texture)
6648 {
6649 return error(GL_INVALID_OPERATION);
6650 }
6651
Nicolas Capens58df2f62016-06-07 14:48:56 -04006652 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006653
Nicolas Capens58df2f62016-06-07 14:48:56 -04006654 if(!eglImage)
6655 {
6656 return error(GL_INVALID_OPERATION);
6657 }
6658
6659 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006660 }
6661}
6662
6663void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6664{
6665 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6666
6667 UNIMPLEMENTED();
6668}
6669
6670GLboolean IsRenderbufferOES(GLuint renderbuffer)
6671{
6672 return IsRenderbuffer(renderbuffer);
6673}
6674
6675void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6676{
6677 BindRenderbuffer(target, renderbuffer);
6678}
6679
6680void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6681{
6682 DeleteRenderbuffers(n, renderbuffers);
6683}
6684
6685void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6686{
6687 GenRenderbuffers(n, renderbuffers);
6688}
6689
6690void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6691{
6692 RenderbufferStorage(target, internalformat, width, height);
6693}
6694
6695void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6696{
6697 GetRenderbufferParameteriv(target, pname, params);
6698}
6699
6700GLboolean IsFramebufferOES(GLuint framebuffer)
6701{
6702 return IsFramebuffer(framebuffer);
6703}
6704
6705void BindFramebufferOES(GLenum target, GLuint framebuffer)
6706{
6707 BindFramebuffer(target, framebuffer);
6708}
6709
6710void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6711{
6712 DeleteFramebuffers(n, framebuffers);
6713}
6714
6715void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6716{
6717 GenFramebuffers(n, framebuffers);
6718}
6719
6720GLenum CheckFramebufferStatusOES(GLenum target)
6721{
6722 return CheckFramebufferStatus(target);
6723}
6724
6725void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6726{
6727 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6728}
6729
6730void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6731{
6732 FramebufferTexture2D(target, attachment, textarget, texture, level);
6733}
6734
6735void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6736{
6737 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6738}
6739
6740void GenerateMipmapOES(GLenum target)
6741{
6742 GenerateMipmap(target);
6743}
6744
6745void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6746{
6747 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6748
6749 if(n < 0 || n > MAX_DRAW_BUFFERS)
6750 {
6751 return error(GL_INVALID_VALUE);
6752 }
6753
6754 es2::Context *context = es2::getContext();
6755
6756 if(context)
6757 {
6758 GLuint drawFramebufferName = context->getDrawFramebufferName();
6759
6760 if((drawFramebufferName == 0) && (n != 1))
6761 {
6762 return error(GL_INVALID_OPERATION);
6763 }
6764
6765 for(unsigned int i = 0; i < (unsigned)n; i++)
6766 {
6767 switch(bufs[i])
6768 {
6769 case GL_BACK:
6770 if(drawFramebufferName != 0)
6771 {
6772 return error(GL_INVALID_OPERATION);
6773 }
6774 break;
6775 case GL_NONE:
6776 break;
6777 case GL_COLOR_ATTACHMENT0_EXT:
6778 case GL_COLOR_ATTACHMENT1_EXT:
6779 case GL_COLOR_ATTACHMENT2_EXT:
6780 case GL_COLOR_ATTACHMENT3_EXT:
6781 case GL_COLOR_ATTACHMENT4_EXT:
6782 case GL_COLOR_ATTACHMENT5_EXT:
6783 case GL_COLOR_ATTACHMENT6_EXT:
6784 case GL_COLOR_ATTACHMENT7_EXT:
6785 case GL_COLOR_ATTACHMENT8_EXT:
6786 case GL_COLOR_ATTACHMENT9_EXT:
6787 case GL_COLOR_ATTACHMENT10_EXT:
6788 case GL_COLOR_ATTACHMENT11_EXT:
6789 case GL_COLOR_ATTACHMENT12_EXT:
6790 case GL_COLOR_ATTACHMENT13_EXT:
6791 case GL_COLOR_ATTACHMENT14_EXT:
6792 case GL_COLOR_ATTACHMENT15_EXT:
6793 {
6794 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6795
6796 if(index >= MAX_COLOR_ATTACHMENTS)
6797 {
6798 return error(GL_INVALID_OPERATION);
6799 }
6800
6801 if(index != i)
6802 {
6803 return error(GL_INVALID_OPERATION);
6804 }
6805
6806 if(drawFramebufferName == 0)
6807 {
6808 return error(GL_INVALID_OPERATION);
6809 }
6810 }
6811 break;
6812 default:
6813 return error(GL_INVALID_ENUM);
6814 }
6815 }
6816
6817 context->setFramebufferDrawBuffers(n, bufs);
6818 }
6819}
6820
6821}
6822
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006823extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006824{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006825 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006826 {
6827 const char *name;
6828 __eglMustCastToProperFunctionPointerType address;
6829 };
6830
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006831 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006832 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006833 bool operator()(const Function &a, const Function &b) const
6834 {
6835 return strcmp(a.name, b.name) < 0;
6836 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006837 };
6838
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006839 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6840 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6841 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006842 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006843 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6844
6845 FUNCTION(glActiveTexture),
6846 FUNCTION(glAttachShader),
6847 FUNCTION(glBeginQuery),
6848 FUNCTION(glBeginQueryEXT),
6849 FUNCTION(glBeginTransformFeedback),
6850 FUNCTION(glBindAttribLocation),
6851 FUNCTION(glBindBuffer),
6852 FUNCTION(glBindBufferBase),
6853 FUNCTION(glBindBufferRange),
6854 FUNCTION(glBindFramebuffer),
6855 FUNCTION(glBindFramebufferOES),
6856 FUNCTION(glBindRenderbuffer),
6857 FUNCTION(glBindRenderbufferOES),
6858 FUNCTION(glBindSampler),
6859 FUNCTION(glBindTexture),
6860 FUNCTION(glBindTransformFeedback),
6861 FUNCTION(glBindVertexArray),
6862 FUNCTION(glBlendColor),
6863 FUNCTION(glBlendEquation),
6864 FUNCTION(glBlendEquationSeparate),
6865 FUNCTION(glBlendFunc),
6866 FUNCTION(glBlendFuncSeparate),
6867 FUNCTION(glBlitFramebuffer),
6868 FUNCTION(glBlitFramebufferANGLE),
6869 FUNCTION(glBufferData),
6870 FUNCTION(glBufferSubData),
6871 FUNCTION(glCheckFramebufferStatus),
6872 FUNCTION(glCheckFramebufferStatusOES),
6873 FUNCTION(glClear),
6874 FUNCTION(glClearBufferfi),
6875 FUNCTION(glClearBufferfv),
6876 FUNCTION(glClearBufferiv),
6877 FUNCTION(glClearBufferuiv),
6878 FUNCTION(glClearColor),
6879 FUNCTION(glClearDepthf),
6880 FUNCTION(glClearStencil),
6881 FUNCTION(glClientWaitSync),
6882 FUNCTION(glColorMask),
6883 FUNCTION(glCompileShader),
6884 FUNCTION(glCompressedTexImage2D),
6885 FUNCTION(glCompressedTexImage3D),
6886 FUNCTION(glCompressedTexSubImage2D),
6887 FUNCTION(glCompressedTexSubImage3D),
6888 FUNCTION(glCopyBufferSubData),
6889 FUNCTION(glCopyTexImage2D),
6890 FUNCTION(glCopyTexSubImage2D),
6891 FUNCTION(glCopyTexSubImage3D),
6892 FUNCTION(glCreateProgram),
6893 FUNCTION(glCreateShader),
6894 FUNCTION(glCullFace),
6895 FUNCTION(glDeleteBuffers),
6896 FUNCTION(glDeleteFencesNV),
6897 FUNCTION(glDeleteFramebuffers),
6898 FUNCTION(glDeleteFramebuffersOES),
6899 FUNCTION(glDeleteProgram),
6900 FUNCTION(glDeleteQueries),
6901 FUNCTION(glDeleteQueriesEXT),
6902 FUNCTION(glDeleteRenderbuffers),
6903 FUNCTION(glDeleteRenderbuffersOES),
6904 FUNCTION(glDeleteSamplers),
6905 FUNCTION(glDeleteShader),
6906 FUNCTION(glDeleteSync),
6907 FUNCTION(glDeleteTextures),
6908 FUNCTION(glDeleteTransformFeedbacks),
6909 FUNCTION(glDeleteVertexArrays),
6910 FUNCTION(glDepthFunc),
6911 FUNCTION(glDepthMask),
6912 FUNCTION(glDepthRangef),
6913 FUNCTION(glDetachShader),
6914 FUNCTION(glDisable),
6915 FUNCTION(glDisableVertexAttribArray),
6916 FUNCTION(glDrawArrays),
6917 FUNCTION(glDrawArraysInstanced),
6918 FUNCTION(glDrawBuffers),
6919 FUNCTION(glDrawBuffersEXT),
6920 FUNCTION(glDrawElements),
6921 FUNCTION(glDrawElementsInstanced),
6922 FUNCTION(glDrawRangeElements),
6923 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6924 FUNCTION(glEGLImageTargetTexture2DOES),
6925 FUNCTION(glEnable),
6926 FUNCTION(glEnableVertexAttribArray),
6927 FUNCTION(glEndQuery),
6928 FUNCTION(glEndQueryEXT),
6929 FUNCTION(glEndTransformFeedback),
6930 FUNCTION(glFenceSync),
6931 FUNCTION(glFinish),
6932 FUNCTION(glFinishFenceNV),
6933 FUNCTION(glFlush),
6934 FUNCTION(glFlushMappedBufferRange),
6935 FUNCTION(glFramebufferRenderbuffer),
6936 FUNCTION(glFramebufferRenderbufferOES),
6937 FUNCTION(glFramebufferTexture2D),
6938 FUNCTION(glFramebufferTexture2DOES),
6939 FUNCTION(glFramebufferTextureLayer),
6940 FUNCTION(glFrontFace),
6941 FUNCTION(glGenBuffers),
6942 FUNCTION(glGenFencesNV),
6943 FUNCTION(glGenFramebuffers),
6944 FUNCTION(glGenFramebuffersOES),
6945 FUNCTION(glGenQueries),
6946 FUNCTION(glGenQueriesEXT),
6947 FUNCTION(glGenRenderbuffers),
6948 FUNCTION(glGenRenderbuffersOES),
6949 FUNCTION(glGenSamplers),
6950 FUNCTION(glGenTextures),
6951 FUNCTION(glGenTransformFeedbacks),
6952 FUNCTION(glGenVertexArrays),
6953 FUNCTION(glGenerateMipmap),
6954 FUNCTION(glGenerateMipmapOES),
6955 FUNCTION(glGetActiveAttrib),
6956 FUNCTION(glGetActiveUniform),
6957 FUNCTION(glGetActiveUniformBlockName),
6958 FUNCTION(glGetActiveUniformBlockiv),
6959 FUNCTION(glGetActiveUniformsiv),
6960 FUNCTION(glGetAttachedShaders),
6961 FUNCTION(glGetAttribLocation),
6962 FUNCTION(glGetBooleanv),
6963 FUNCTION(glGetBufferParameteri64v),
6964 FUNCTION(glGetBufferParameteriv),
6965 FUNCTION(glGetBufferPointerv),
6966 FUNCTION(glGetError),
6967 FUNCTION(glGetFenceivNV),
6968 FUNCTION(glGetFloatv),
6969 FUNCTION(glGetFragDataLocation),
6970 FUNCTION(glGetFramebufferAttachmentParameteriv),
6971 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6972 FUNCTION(glGetGraphicsResetStatusEXT),
6973 FUNCTION(glGetInteger64i_v),
6974 FUNCTION(glGetInteger64v),
6975 FUNCTION(glGetIntegeri_v),
6976 FUNCTION(glGetIntegerv),
6977 FUNCTION(glGetInternalformativ),
6978 FUNCTION(glGetProgramBinary),
6979 FUNCTION(glGetProgramInfoLog),
6980 FUNCTION(glGetProgramiv),
6981 FUNCTION(glGetQueryObjectuiv),
6982 FUNCTION(glGetQueryObjectuivEXT),
6983 FUNCTION(glGetQueryiv),
6984 FUNCTION(glGetQueryivEXT),
6985 FUNCTION(glGetRenderbufferParameteriv),
6986 FUNCTION(glGetRenderbufferParameterivOES),
6987 FUNCTION(glGetSamplerParameterfv),
6988 FUNCTION(glGetSamplerParameteriv),
6989 FUNCTION(glGetShaderInfoLog),
6990 FUNCTION(glGetShaderPrecisionFormat),
6991 FUNCTION(glGetShaderSource),
6992 FUNCTION(glGetShaderiv),
6993 FUNCTION(glGetString),
6994 FUNCTION(glGetStringi),
6995 FUNCTION(glGetSynciv),
6996 FUNCTION(glGetTexParameterfv),
6997 FUNCTION(glGetTexParameteriv),
6998 FUNCTION(glGetTransformFeedbackVarying),
6999 FUNCTION(glGetUniformBlockIndex),
7000 FUNCTION(glGetUniformIndices),
7001 FUNCTION(glGetUniformLocation),
7002 FUNCTION(glGetUniformfv),
7003 FUNCTION(glGetUniformiv),
7004 FUNCTION(glGetUniformuiv),
7005 FUNCTION(glGetVertexAttribIiv),
7006 FUNCTION(glGetVertexAttribIuiv),
7007 FUNCTION(glGetVertexAttribPointerv),
7008 FUNCTION(glGetVertexAttribfv),
7009 FUNCTION(glGetVertexAttribiv),
7010 FUNCTION(glGetnUniformfvEXT),
7011 FUNCTION(glGetnUniformivEXT),
7012 FUNCTION(glHint),
7013 FUNCTION(glInvalidateFramebuffer),
7014 FUNCTION(glInvalidateSubFramebuffer),
7015 FUNCTION(glIsBuffer),
7016 FUNCTION(glIsEnabled),
7017 FUNCTION(glIsFenceNV),
7018 FUNCTION(glIsFramebuffer),
7019 FUNCTION(glIsFramebufferOES),
7020 FUNCTION(glIsProgram),
7021 FUNCTION(glIsQuery),
7022 FUNCTION(glIsQueryEXT),
7023 FUNCTION(glIsRenderbuffer),
7024 FUNCTION(glIsRenderbufferOES),
7025 FUNCTION(glIsSampler),
7026 FUNCTION(glIsShader),
7027 FUNCTION(glIsSync),
7028 FUNCTION(glIsTexture),
7029 FUNCTION(glIsTransformFeedback),
7030 FUNCTION(glIsVertexArray),
7031 FUNCTION(glLineWidth),
7032 FUNCTION(glLinkProgram),
7033 FUNCTION(glMapBufferRange),
7034 FUNCTION(glPauseTransformFeedback),
7035 FUNCTION(glPixelStorei),
7036 FUNCTION(glPolygonOffset),
7037 FUNCTION(glProgramBinary),
7038 FUNCTION(glProgramParameteri),
7039 FUNCTION(glReadBuffer),
7040 FUNCTION(glReadPixels),
7041 FUNCTION(glReadnPixelsEXT),
7042 FUNCTION(glReleaseShaderCompiler),
7043 FUNCTION(glRenderbufferStorage),
7044 FUNCTION(glRenderbufferStorageMultisample),
7045 FUNCTION(glRenderbufferStorageMultisampleANGLE),
7046 FUNCTION(glRenderbufferStorageOES),
7047 FUNCTION(glResumeTransformFeedback),
7048 FUNCTION(glSampleCoverage),
7049 FUNCTION(glSamplerParameterf),
7050 FUNCTION(glSamplerParameterfv),
7051 FUNCTION(glSamplerParameteri),
7052 FUNCTION(glSamplerParameteriv),
7053 FUNCTION(glScissor),
7054 FUNCTION(glSetFenceNV),
7055 FUNCTION(glShaderBinary),
7056 FUNCTION(glShaderSource),
7057 FUNCTION(glStencilFunc),
7058 FUNCTION(glStencilFuncSeparate),
7059 FUNCTION(glStencilMask),
7060 FUNCTION(glStencilMaskSeparate),
7061 FUNCTION(glStencilOp),
7062 FUNCTION(glStencilOpSeparate),
7063 FUNCTION(glTestFenceNV),
7064 FUNCTION(glTexImage2D),
7065 FUNCTION(glTexImage3D),
7066 FUNCTION(glTexImage3DOES),
7067 FUNCTION(glTexParameterf),
7068 FUNCTION(glTexParameterfv),
7069 FUNCTION(glTexParameteri),
7070 FUNCTION(glTexParameteriv),
7071 FUNCTION(glTexStorage2D),
7072 FUNCTION(glTexStorage3D),
7073 FUNCTION(glTexSubImage2D),
7074 FUNCTION(glTexSubImage3D),
7075 FUNCTION(glTransformFeedbackVaryings),
7076 FUNCTION(glUniform1f),
7077 FUNCTION(glUniform1fv),
7078 FUNCTION(glUniform1i),
7079 FUNCTION(glUniform1iv),
7080 FUNCTION(glUniform1ui),
7081 FUNCTION(glUniform1uiv),
7082 FUNCTION(glUniform2f),
7083 FUNCTION(glUniform2fv),
7084 FUNCTION(glUniform2i),
7085 FUNCTION(glUniform2iv),
7086 FUNCTION(glUniform2ui),
7087 FUNCTION(glUniform2uiv),
7088 FUNCTION(glUniform3f),
7089 FUNCTION(glUniform3fv),
7090 FUNCTION(glUniform3i),
7091 FUNCTION(glUniform3iv),
7092 FUNCTION(glUniform3ui),
7093 FUNCTION(glUniform3uiv),
7094 FUNCTION(glUniform4f),
7095 FUNCTION(glUniform4fv),
7096 FUNCTION(glUniform4i),
7097 FUNCTION(glUniform4iv),
7098 FUNCTION(glUniform4ui),
7099 FUNCTION(glUniform4uiv),
7100 FUNCTION(glUniformBlockBinding),
7101 FUNCTION(glUniformMatrix2fv),
7102 FUNCTION(glUniformMatrix2x3fv),
7103 FUNCTION(glUniformMatrix2x4fv),
7104 FUNCTION(glUniformMatrix3fv),
7105 FUNCTION(glUniformMatrix3x2fv),
7106 FUNCTION(glUniformMatrix3x4fv),
7107 FUNCTION(glUniformMatrix4fv),
7108 FUNCTION(glUniformMatrix4x2fv),
7109 FUNCTION(glUniformMatrix4x3fv),
7110 FUNCTION(glUnmapBuffer),
7111 FUNCTION(glUseProgram),
7112 FUNCTION(glValidateProgram),
7113 FUNCTION(glVertexAttrib1f),
7114 FUNCTION(glVertexAttrib1fv),
7115 FUNCTION(glVertexAttrib2f),
7116 FUNCTION(glVertexAttrib2fv),
7117 FUNCTION(glVertexAttrib3f),
7118 FUNCTION(glVertexAttrib3fv),
7119 FUNCTION(glVertexAttrib4f),
7120 FUNCTION(glVertexAttrib4fv),
7121 FUNCTION(glVertexAttribDivisor),
7122 FUNCTION(glVertexAttribI4i),
7123 FUNCTION(glVertexAttribI4iv),
7124 FUNCTION(glVertexAttribI4ui),
7125 FUNCTION(glVertexAttribI4uiv),
7126 FUNCTION(glVertexAttribIPointer),
7127 FUNCTION(glVertexAttribPointer),
7128 FUNCTION(glViewport),
7129 FUNCTION(glWaitSync),
7130
7131 #undef FUNCTION
7132 };
7133
7134 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
7135 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
7136
7137 Function needle;
7138 needle.name = procname;
7139
7140 if(procname && strncmp("gl", procname, 2) == 0)
7141 {
7142 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
7143 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04007144 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01007145 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04007146 }
7147 }
7148
7149 return nullptr;
7150}