blob: b6d471817cb2012627e4e1fdb5441bbae4ac8346 [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 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400186 switch(target)
187 {
188 case GL_ARRAY_BUFFER:
189 context->bindArrayBuffer(buffer);
190 return;
191 case GL_ELEMENT_ARRAY_BUFFER:
192 context->bindElementArrayBuffer(buffer);
193 return;
194 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400195 context->bindCopyReadBuffer(buffer);
196 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400197 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400198 context->bindCopyWriteBuffer(buffer);
199 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400201 context->bindPixelPackBuffer(buffer);
202 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400204 context->bindPixelUnpackBuffer(buffer);
205 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400207 context->bindTransformFeedbackBuffer(buffer);
208 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400209 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400210 context->bindGenericUniformBuffer(buffer);
211 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 default:
213 return error(GL_INVALID_ENUM);
214 }
215 }
216}
217
218void BindFramebuffer(GLenum target, GLuint framebuffer)
219{
220 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
221
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000222 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400223 {
224 return error(GL_INVALID_ENUM);
225 }
226
227 es2::Context *context = es2::getContext();
228
229 if(context)
230 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000231 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400232 {
233 context->bindReadFramebuffer(framebuffer);
234 }
235
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000236 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400237 {
238 context->bindDrawFramebuffer(framebuffer);
239 }
240 }
241}
242
243void BindRenderbuffer(GLenum target, GLuint renderbuffer)
244{
245 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
246
247 if(target != GL_RENDERBUFFER)
248 {
249 return error(GL_INVALID_ENUM);
250 }
251
252 es2::Context *context = es2::getContext();
253
254 if(context)
255 {
256 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
257 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
258 // If renderbuffer is not zero, then the resulting renderbuffer object
259 // is a new state vector, initialized with a zero-sized memory buffer.
260 context->bindRenderbuffer(renderbuffer);
261 }
262}
263
264void BindTexture(GLenum target, GLuint texture)
265{
266 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
267
268 es2::Context *context = es2::getContext();
269
270 if(context)
271 {
272 es2::Texture *textureObject = context->getTexture(texture);
273
274 if(textureObject && textureObject->getTarget() != target && texture != 0)
275 {
276 return error(GL_INVALID_OPERATION);
277 }
278
Nicolas Capens0bac2852016-05-07 06:09:58 -0400279 switch(target)
280 {
281 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500282 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400283 break;
284 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500285 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400286 break;
287 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500288 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400289 break;
290 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500291 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400292 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500293 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500294 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500296 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500297 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500298 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400299 default:
300 return error(GL_INVALID_ENUM);
301 }
302 }
303}
304
305void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
306{
307 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
308 red, green, blue, alpha);
309
310 es2::Context* context = es2::getContext();
311
312 if(context)
313 {
314 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
315 }
316}
317
318void BlendEquation(GLenum mode)
319{
320 glBlendEquationSeparate(mode, mode);
321}
322
323void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
324{
325 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
326
327 switch(modeRGB)
328 {
329 case GL_FUNC_ADD:
330 case GL_FUNC_SUBTRACT:
331 case GL_FUNC_REVERSE_SUBTRACT:
332 case GL_MIN_EXT:
333 case GL_MAX_EXT:
334 break;
335 default:
336 return error(GL_INVALID_ENUM);
337 }
338
339 switch(modeAlpha)
340 {
341 case GL_FUNC_ADD:
342 case GL_FUNC_SUBTRACT:
343 case GL_FUNC_REVERSE_SUBTRACT:
344 case GL_MIN_EXT:
345 case GL_MAX_EXT:
346 break;
347 default:
348 return error(GL_INVALID_ENUM);
349 }
350
351 es2::Context *context = es2::getContext();
352
353 if(context)
354 {
355 context->setBlendEquation(modeRGB, modeAlpha);
356 }
357}
358
359void BlendFunc(GLenum sfactor, GLenum dfactor)
360{
361 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
362}
363
364void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
365{
366 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
367 srcRGB, dstRGB, srcAlpha, dstAlpha);
368
Nicolas Capens0bac2852016-05-07 06:09:58 -0400369 switch(srcRGB)
370 {
371 case GL_ZERO:
372 case GL_ONE:
373 case GL_SRC_COLOR:
374 case GL_ONE_MINUS_SRC_COLOR:
375 case GL_DST_COLOR:
376 case GL_ONE_MINUS_DST_COLOR:
377 case GL_SRC_ALPHA:
378 case GL_ONE_MINUS_SRC_ALPHA:
379 case GL_DST_ALPHA:
380 case GL_ONE_MINUS_DST_ALPHA:
381 case GL_CONSTANT_COLOR:
382 case GL_ONE_MINUS_CONSTANT_COLOR:
383 case GL_CONSTANT_ALPHA:
384 case GL_ONE_MINUS_CONSTANT_ALPHA:
385 case GL_SRC_ALPHA_SATURATE:
386 break;
387 default:
388 return error(GL_INVALID_ENUM);
389 }
390
391 switch(dstRGB)
392 {
393 case GL_ZERO:
394 case GL_ONE:
395 case GL_SRC_COLOR:
396 case GL_ONE_MINUS_SRC_COLOR:
397 case GL_DST_COLOR:
398 case GL_ONE_MINUS_DST_COLOR:
399 case GL_SRC_ALPHA:
400 case GL_ONE_MINUS_SRC_ALPHA:
401 case GL_DST_ALPHA:
402 case GL_ONE_MINUS_DST_ALPHA:
403 case GL_CONSTANT_COLOR:
404 case GL_ONE_MINUS_CONSTANT_COLOR:
405 case GL_CONSTANT_ALPHA:
406 case GL_ONE_MINUS_CONSTANT_ALPHA:
407 break;
408 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400409 break;
410 default:
411 return error(GL_INVALID_ENUM);
412 }
413
414 switch(srcAlpha)
415 {
416 case GL_ZERO:
417 case GL_ONE:
418 case GL_SRC_COLOR:
419 case GL_ONE_MINUS_SRC_COLOR:
420 case GL_DST_COLOR:
421 case GL_ONE_MINUS_DST_COLOR:
422 case GL_SRC_ALPHA:
423 case GL_ONE_MINUS_SRC_ALPHA:
424 case GL_DST_ALPHA:
425 case GL_ONE_MINUS_DST_ALPHA:
426 case GL_CONSTANT_COLOR:
427 case GL_ONE_MINUS_CONSTANT_COLOR:
428 case GL_CONSTANT_ALPHA:
429 case GL_ONE_MINUS_CONSTANT_ALPHA:
430 case GL_SRC_ALPHA_SATURATE:
431 break;
432 default:
433 return error(GL_INVALID_ENUM);
434 }
435
436 switch(dstAlpha)
437 {
438 case GL_ZERO:
439 case GL_ONE:
440 case GL_SRC_COLOR:
441 case GL_ONE_MINUS_SRC_COLOR:
442 case GL_DST_COLOR:
443 case GL_ONE_MINUS_DST_COLOR:
444 case GL_SRC_ALPHA:
445 case GL_ONE_MINUS_SRC_ALPHA:
446 case GL_DST_ALPHA:
447 case GL_ONE_MINUS_DST_ALPHA:
448 case GL_CONSTANT_COLOR:
449 case GL_ONE_MINUS_CONSTANT_COLOR:
450 case GL_CONSTANT_ALPHA:
451 case GL_ONE_MINUS_CONSTANT_ALPHA:
452 break;
453 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400454 break;
455 default:
456 return error(GL_INVALID_ENUM);
457 }
458
459 es2::Context *context = es2::getContext();
460
461 if(context)
462 {
463 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
464 }
465}
466
467void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
468{
469 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
470
471 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
472 target, size, data, usage);
473
474 if(size < 0)
475 {
476 return error(GL_INVALID_VALUE);
477 }
478
Nicolas Capens0bac2852016-05-07 06:09:58 -0400479 switch(usage)
480 {
481 case GL_STREAM_DRAW:
482 case GL_STATIC_DRAW:
483 case GL_DYNAMIC_DRAW:
484 break;
485 case GL_STREAM_READ:
486 case GL_STREAM_COPY:
487 case GL_STATIC_READ:
488 case GL_STATIC_COPY:
489 case GL_DYNAMIC_READ:
490 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400491 break;
492 default:
493 return error(GL_INVALID_ENUM);
494 }
495
496 es2::Context *context = es2::getContext();
497
498 if(context)
499 {
500 es2::Buffer *buffer = nullptr;
501 if(!context->getBuffer(target, &buffer))
502 {
503 return error(GL_INVALID_ENUM);
504 }
505
506 if(!buffer)
507 {
508 // A null buffer means that "0" is bound to the requested buffer target
509 return error(GL_INVALID_OPERATION);
510 }
511
512 buffer->bufferData(data, size, usage);
513 }
514}
515
516void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
517{
518 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
519 offset = static_cast<GLint>(offset);
520
521 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
522 target, offset, size, data);
523
524 if(size < 0 || offset < 0)
525 {
526 return error(GL_INVALID_VALUE);
527 }
528
529 es2::Context *context = es2::getContext();
530
531 if(context)
532 {
533 es2::Buffer *buffer = nullptr;
534 if(!context->getBuffer(target, &buffer))
535 {
536 return error(GL_INVALID_ENUM);
537 }
538
539 if(!buffer)
540 {
541 // A null buffer means that "0" is bound to the requested buffer target
542 return error(GL_INVALID_OPERATION);
543 }
544
Alexis Hetu6e864492017-11-14 15:27:00 -0500545 if(buffer->isMapped())
546 {
547 // It is an invalid operation to update an already mapped buffer
548 return error(GL_INVALID_OPERATION);
549 }
550
Nicolas Capens0bac2852016-05-07 06:09:58 -0400551 if((size_t)size + offset > buffer->size())
552 {
553 return error(GL_INVALID_VALUE);
554 }
555
556 buffer->bufferSubData(data, size, offset);
557 }
558}
559
560GLenum CheckFramebufferStatus(GLenum target)
561{
562 TRACE("(GLenum target = 0x%X)", target);
563
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000564 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400565 {
566 return error(GL_INVALID_ENUM, 0);
567 }
568
569 es2::Context *context = es2::getContext();
570
571 if(context)
572 {
573 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000574 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400575 {
576 framebuffer = context->getReadFramebuffer();
577 }
578 else
579 {
580 framebuffer = context->getDrawFramebuffer();
581 }
582
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400583 if(!framebuffer)
584 {
585 return GL_FRAMEBUFFER_UNDEFINED_OES;
586 }
587
Nicolas Capens0bac2852016-05-07 06:09:58 -0400588 return framebuffer->completeness();
589 }
590
591 return 0;
592}
593
594void Clear(GLbitfield mask)
595{
596 TRACE("(GLbitfield mask = %X)", mask);
597
598 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
599 {
600 return error(GL_INVALID_VALUE);
601 }
602
603 es2::Context *context = es2::getContext();
604
605 if(context)
606 {
607 context->clear(mask);
608 }
609}
610
611void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
612{
613 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
614 red, green, blue, alpha);
615
616 es2::Context *context = es2::getContext();
617
618 if(context)
619 {
620 context->setClearColor(red, green, blue, alpha);
621 }
622}
623
624void ClearDepthf(GLclampf depth)
625{
626 TRACE("(GLclampf depth = %f)", depth);
627
628 es2::Context *context = es2::getContext();
629
630 if(context)
631 {
632 context->setClearDepth(depth);
633 }
634}
635
636void ClearStencil(GLint s)
637{
638 TRACE("(GLint s = %d)", s);
639
640 es2::Context *context = es2::getContext();
641
642 if(context)
643 {
644 context->setClearStencil(s);
645 }
646}
647
648void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
649{
650 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
651 red, green, blue, alpha);
652
653 es2::Context *context = es2::getContext();
654
655 if(context)
656 {
657 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
658 }
659}
660
661void CompileShader(GLuint shader)
662{
663 TRACE("(GLuint shader = %d)", shader);
664
665 es2::Context *context = es2::getContext();
666
667 if(context)
668 {
669 es2::Shader *shaderObject = context->getShader(shader);
670
671 if(!shaderObject)
672 {
673 if(context->getProgram(shader))
674 {
675 return error(GL_INVALID_OPERATION);
676 }
677 else
678 {
679 return error(GL_INVALID_VALUE);
680 }
681 }
682
683 shaderObject->compile();
684 }
685}
686
687void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
688 GLint border, GLsizei imageSize, const GLvoid* data)
689{
690 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
691 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
692 target, level, internalformat, width, height, border, imageSize, data);
693
694 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
695 {
696 return error(GL_INVALID_VALUE);
697 }
698
Nicolas Capens83463112018-06-12 23:55:16 -0400699 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400700 {
Nicolas Capens03589982018-02-01 17:28:32 -0500701 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400702 }
703
704 if(border != 0)
705 {
706 return error(GL_INVALID_VALUE);
707 }
708
709 es2::Context *context = es2::getContext();
710
711 if(context)
712 {
713 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
714 {
715 return error(GL_INVALID_VALUE);
716 }
717
718 switch(target)
719 {
720 case GL_TEXTURE_2D:
721 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
722 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
723 {
724 return error(GL_INVALID_VALUE);
725 }
726 break;
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
733 if(width != height)
734 {
735 return error(GL_INVALID_VALUE);
736 }
737
738 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
739 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
740 {
741 return error(GL_INVALID_VALUE);
742 }
743 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500744 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400745 default:
746 return error(GL_INVALID_ENUM);
747 }
748
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500749 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400750 {
751 return error(GL_INVALID_VALUE);
752 }
753
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500754 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500755 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500756 {
757 return error(validationError);
758 }
759
Alexis Hetu46768622018-01-16 22:09:28 -0500760 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400761 {
Alexis Hetu46768622018-01-16 22:09:28 -0500762 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400763
764 if(!texture)
765 {
766 return error(GL_INVALID_OPERATION);
767 }
768
769 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
770 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500771 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400772 {
773 es2::TextureCubeMap *texture = context->getTextureCubeMap();
774
775 if(!texture)
776 {
777 return error(GL_INVALID_OPERATION);
778 }
779
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500780 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400781 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500782 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400783 }
784}
785
786void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
787 GLenum format, GLsizei imageSize, const GLvoid* data)
788{
789 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
790 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
791 "GLsizei imageSize = %d, const GLvoid* data = %p)",
792 target, level, xoffset, yoffset, width, height, format, imageSize, data);
793
794 if(!es2::IsTextureTarget(target))
795 {
796 return error(GL_INVALID_ENUM);
797 }
798
799 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
800 {
801 return error(GL_INVALID_VALUE);
802 }
803
804 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
805 {
806 return error(GL_INVALID_VALUE);
807 }
808
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500809 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400810 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500811 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400812 }
813
814 es2::Context *context = es2::getContext();
815
816 if(context)
817 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400818 if(xoffset % 4 != 0 || yoffset % 4 != 0)
819 {
820 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
821 return error(GL_INVALID_OPERATION);
822 }
823
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500824 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500825 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500826 {
827 return error(validationError);
828 }
829
Alexis Hetu46768622018-01-16 22:09:28 -0500830 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400831 {
Alexis Hetu46768622018-01-16 22:09:28 -0500832 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400833
Nicolas Capens83463112018-06-12 23:55:16 -0400834 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500835 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400836 {
837 return error(validationError);
838 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500839
Nicolas Capenseab70762018-02-06 16:49:36 -0500840 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400841 }
842 else if(es2::IsCubemapTextureTarget(target))
843 {
844 es2::TextureCubeMap *texture = context->getTextureCubeMap();
845
Nicolas Capens83463112018-06-12 23:55:16 -0400846 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500847 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400848 {
849 return error(validationError);
850 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500851
Nicolas Capenseab70762018-02-06 16:49:36 -0500852 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400853 }
854 else UNREACHABLE(target);
855 }
856}
857
858void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
859{
860 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
861 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
862 target, level, internalformat, x, y, width, height, border);
863
864 if(!validImageSize(level, width, height))
865 {
866 return error(GL_INVALID_VALUE);
867 }
868
869 if(border != 0)
870 {
871 return error(GL_INVALID_VALUE);
872 }
873
874 es2::Context *context = es2::getContext();
875
876 if(context)
877 {
878 switch(target)
879 {
Alexis Hetu46768622018-01-16 22:09:28 -0500880 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500881 if(level != 0)
882 {
883 return error(GL_INVALID_VALUE);
884 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400885 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500886 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400887 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
888 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
889 {
890 return error(GL_INVALID_VALUE);
891 }
892 break;
893 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
894 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
895 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
896 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
897 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
898 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
899 if(width != height)
900 {
901 return error(GL_INVALID_VALUE);
902 }
903
904 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
905 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
906 {
907 return error(GL_INVALID_VALUE);
908 }
909 break;
910 default:
911 return error(GL_INVALID_ENUM);
912 }
913
914 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
915
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400916 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400917 {
918 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
919 }
920
921 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
922
923 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
924 {
925 return error(GL_INVALID_OPERATION);
926 }
927
928 GLenum colorbufferFormat = source->getFormat();
929
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500930 // Determine the sized internal format.
931 if(gl::IsUnsizedInternalFormat(internalformat))
932 {
933 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
934 {
935 internalformat = colorbufferFormat;
936 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400937 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500938 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400939 // TODO: Convert to the smallest format that fits all components.
940 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
941
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500942 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
943 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400944 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
945 {
946 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
947 }
948 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
949 {
950 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
951 }
952 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
953 {
954 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
955 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500956 else
957 {
958 UNIMPLEMENTED();
959
960 return error(GL_INVALID_OPERATION);
961 }
962 }
963
Nicolas Capens8f215a42018-02-02 13:25:53 -0500964 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400965 {
966 return;
967 }
968
Alexis Hetu46768622018-01-16 22:09:28 -0500969 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400970 {
Alexis Hetu46768622018-01-16 22:09:28 -0500971 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400972
973 if(!texture)
974 {
975 return error(GL_INVALID_OPERATION);
976 }
977
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500978 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400979 }
980 else if(es2::IsCubemapTextureTarget(target))
981 {
982 es2::TextureCubeMap *texture = context->getTextureCubeMap();
983
984 if(!texture)
985 {
986 return error(GL_INVALID_OPERATION);
987 }
988
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500989 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400990 }
991 else UNREACHABLE(target);
992 }
993}
994
995void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
996{
997 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
998 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
999 target, level, xoffset, yoffset, x, y, width, height);
1000
1001 if(!es2::IsTextureTarget(target))
1002 {
1003 return error(GL_INVALID_ENUM);
1004 }
1005
1006 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1007 {
1008 return error(GL_INVALID_VALUE);
1009 }
1010
1011 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1012 {
1013 return error(GL_INVALID_VALUE);
1014 }
1015
1016 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1017 {
1018 return error(GL_INVALID_VALUE);
1019 }
1020
Nicolas Capens0bac2852016-05-07 06:09:58 -04001021 es2::Context *context = es2::getContext();
1022
1023 if(context)
1024 {
1025 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1026
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001027 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001028 {
1029 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1030 }
1031
1032 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1033
1034 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1035 {
1036 return error(GL_INVALID_OPERATION);
1037 }
1038
1039 es2::Texture *texture = nullptr;
1040
Alexis Hetu46768622018-01-16 22:09:28 -05001041 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001042 {
Alexis Hetu46768622018-01-16 22:09:28 -05001043 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001044 }
1045 else if(es2::IsCubemapTextureTarget(target))
1046 {
1047 texture = context->getTextureCubeMap();
1048 }
1049 else UNREACHABLE(target);
1050
Nicolas Capens83463112018-06-12 23:55:16 -04001051 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001052 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001053 {
1054 return error(validationError);
1055 }
1056
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001057 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001058 }
1059}
1060
1061GLuint CreateProgram(void)
1062{
1063 TRACE("()");
1064
1065 es2::Context *context = es2::getContext();
1066
1067 if(context)
1068 {
1069 return context->createProgram();
1070 }
1071
1072 return 0;
1073}
1074
1075GLuint CreateShader(GLenum type)
1076{
1077 TRACE("(GLenum type = 0x%X)", type);
1078
1079 es2::Context *context = es2::getContext();
1080
1081 if(context)
1082 {
1083 switch(type)
1084 {
1085 case GL_FRAGMENT_SHADER:
1086 case GL_VERTEX_SHADER:
1087 return context->createShader(type);
1088 default:
1089 return error(GL_INVALID_ENUM, 0);
1090 }
1091 }
1092
1093 return 0;
1094}
1095
1096void CullFace(GLenum mode)
1097{
1098 TRACE("(GLenum mode = 0x%X)", mode);
1099
1100 switch(mode)
1101 {
1102 case GL_FRONT:
1103 case GL_BACK:
1104 case GL_FRONT_AND_BACK:
1105 {
1106 es2::Context *context = es2::getContext();
1107
1108 if(context)
1109 {
1110 context->setCullMode(mode);
1111 }
1112 }
1113 break;
1114 default:
1115 return error(GL_INVALID_ENUM);
1116 }
1117}
1118
1119void DeleteBuffers(GLsizei n, const GLuint* buffers)
1120{
1121 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1122
1123 if(n < 0)
1124 {
1125 return error(GL_INVALID_VALUE);
1126 }
1127
1128 es2::Context *context = es2::getContext();
1129
1130 if(context)
1131 {
1132 for(int i = 0; i < n; i++)
1133 {
1134 context->deleteBuffer(buffers[i]);
1135 }
1136 }
1137}
1138
1139void DeleteFencesNV(GLsizei n, const GLuint* fences)
1140{
1141 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1142
1143 if(n < 0)
1144 {
1145 return error(GL_INVALID_VALUE);
1146 }
1147
1148 es2::Context *context = es2::getContext();
1149
1150 if(context)
1151 {
1152 for(int i = 0; i < n; i++)
1153 {
1154 context->deleteFence(fences[i]);
1155 }
1156 }
1157}
1158
1159void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1160{
1161 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1162
1163 if(n < 0)
1164 {
1165 return error(GL_INVALID_VALUE);
1166 }
1167
1168 es2::Context *context = es2::getContext();
1169
1170 if(context)
1171 {
1172 for(int i = 0; i < n; i++)
1173 {
1174 if(framebuffers[i] != 0)
1175 {
1176 context->deleteFramebuffer(framebuffers[i]);
1177 }
1178 }
1179 }
1180}
1181
1182void DeleteProgram(GLuint program)
1183{
1184 TRACE("(GLuint program = %d)", program);
1185
1186 if(program == 0)
1187 {
1188 return;
1189 }
1190
1191 es2::Context *context = es2::getContext();
1192
1193 if(context)
1194 {
1195 if(!context->getProgram(program))
1196 {
1197 if(context->getShader(program))
1198 {
1199 return error(GL_INVALID_OPERATION);
1200 }
1201 else
1202 {
1203 return error(GL_INVALID_VALUE);
1204 }
1205 }
1206
1207 context->deleteProgram(program);
1208 }
1209}
1210
1211void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1212{
1213 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1214
1215 if(n < 0)
1216 {
1217 return error(GL_INVALID_VALUE);
1218 }
1219
1220 es2::Context *context = es2::getContext();
1221
1222 if(context)
1223 {
1224 for(int i = 0; i < n; i++)
1225 {
1226 context->deleteQuery(ids[i]);
1227 }
1228 }
1229}
1230
1231void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1232{
1233 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1234
1235 if(n < 0)
1236 {
1237 return error(GL_INVALID_VALUE);
1238 }
1239
1240 es2::Context *context = es2::getContext();
1241
1242 if(context)
1243 {
1244 for(int i = 0; i < n; i++)
1245 {
1246 context->deleteRenderbuffer(renderbuffers[i]);
1247 }
1248 }
1249}
1250
1251void DeleteShader(GLuint shader)
1252{
1253 TRACE("(GLuint shader = %d)", shader);
1254
1255 if(shader == 0)
1256 {
1257 return;
1258 }
1259
1260 es2::Context *context = es2::getContext();
1261
1262 if(context)
1263 {
1264 if(!context->getShader(shader))
1265 {
1266 if(context->getProgram(shader))
1267 {
1268 return error(GL_INVALID_OPERATION);
1269 }
1270 else
1271 {
1272 return error(GL_INVALID_VALUE);
1273 }
1274 }
1275
1276 context->deleteShader(shader);
1277 }
1278}
1279
1280void DeleteTextures(GLsizei n, const GLuint* textures)
1281{
1282 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1283
1284 if(n < 0)
1285 {
1286 return error(GL_INVALID_VALUE);
1287 }
1288
1289 es2::Context *context = es2::getContext();
1290
1291 if(context)
1292 {
1293 for(int i = 0; i < n; i++)
1294 {
1295 if(textures[i] != 0)
1296 {
1297 context->deleteTexture(textures[i]);
1298 }
1299 }
1300 }
1301}
1302
1303void DepthFunc(GLenum func)
1304{
1305 TRACE("(GLenum func = 0x%X)", func);
1306
1307 switch(func)
1308 {
1309 case GL_NEVER:
1310 case GL_ALWAYS:
1311 case GL_LESS:
1312 case GL_LEQUAL:
1313 case GL_EQUAL:
1314 case GL_GREATER:
1315 case GL_GEQUAL:
1316 case GL_NOTEQUAL:
1317 break;
1318 default:
1319 return error(GL_INVALID_ENUM);
1320 }
1321
1322 es2::Context *context = es2::getContext();
1323
1324 if(context)
1325 {
1326 context->setDepthFunc(func);
1327 }
1328}
1329
1330void DepthMask(GLboolean flag)
1331{
1332 TRACE("(GLboolean flag = %d)", flag);
1333
1334 es2::Context *context = es2::getContext();
1335
1336 if(context)
1337 {
1338 context->setDepthMask(flag != GL_FALSE);
1339 }
1340}
1341
1342void DepthRangef(GLclampf zNear, GLclampf zFar)
1343{
1344 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1345
1346 es2::Context *context = es2::getContext();
1347
1348 if(context)
1349 {
1350 context->setDepthRange(zNear, zFar);
1351 }
1352}
1353
1354void DetachShader(GLuint program, GLuint shader)
1355{
1356 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1357
1358 es2::Context *context = es2::getContext();
1359
1360 if(context)
1361 {
1362
1363 es2::Program *programObject = context->getProgram(program);
1364 es2::Shader *shaderObject = context->getShader(shader);
1365
1366 if(!programObject)
1367 {
1368 es2::Shader *shaderByProgramHandle;
1369 shaderByProgramHandle = context->getShader(program);
1370 if(!shaderByProgramHandle)
1371 {
1372 return error(GL_INVALID_VALUE);
1373 }
1374 else
1375 {
1376 return error(GL_INVALID_OPERATION);
1377 }
1378 }
1379
1380 if(!shaderObject)
1381 {
1382 es2::Program *programByShaderHandle = context->getProgram(shader);
1383 if(!programByShaderHandle)
1384 {
1385 return error(GL_INVALID_VALUE);
1386 }
1387 else
1388 {
1389 return error(GL_INVALID_OPERATION);
1390 }
1391 }
1392
1393 if(!programObject->detachShader(shaderObject))
1394 {
1395 return error(GL_INVALID_OPERATION);
1396 }
1397 }
1398}
1399
1400void Disable(GLenum cap)
1401{
1402 TRACE("(GLenum cap = 0x%X)", cap);
1403
1404 es2::Context *context = es2::getContext();
1405
1406 if(context)
1407 {
1408 switch(cap)
1409 {
1410 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1411 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1412 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1413 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1414 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1415 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1416 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1417 case GL_BLEND: context->setBlendEnabled(false); break;
1418 case GL_DITHER: context->setDitherEnabled(false); break;
1419 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1420 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1421 default:
1422 return error(GL_INVALID_ENUM);
1423 }
1424 }
1425}
1426
1427void DisableVertexAttribArray(GLuint index)
1428{
1429 TRACE("(GLuint index = %d)", index);
1430
1431 if(index >= es2::MAX_VERTEX_ATTRIBS)
1432 {
1433 return error(GL_INVALID_VALUE);
1434 }
1435
1436 es2::Context *context = es2::getContext();
1437
1438 if(context)
1439 {
1440 context->setVertexAttribArrayEnabled(index, false);
1441 }
1442}
1443
1444void DrawArrays(GLenum mode, GLint first, GLsizei count)
1445{
1446 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1447
1448 switch(mode)
1449 {
1450 case GL_POINTS:
1451 case GL_LINES:
1452 case GL_LINE_LOOP:
1453 case GL_LINE_STRIP:
1454 case GL_TRIANGLES:
1455 case GL_TRIANGLE_FAN:
1456 case GL_TRIANGLE_STRIP:
1457 break;
1458 default:
1459 return error(GL_INVALID_ENUM);
1460 }
1461
1462 if(count < 0 || first < 0)
1463 {
1464 return error(GL_INVALID_VALUE);
1465 }
1466
1467 es2::Context *context = es2::getContext();
1468
1469 if(context)
1470 {
1471 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1472 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1473 {
1474 return error(GL_INVALID_OPERATION);
1475 }
1476
1477 context->drawArrays(mode, first, count);
1478 }
1479}
1480
1481void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1482{
1483 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1484 mode, count, type, indices);
1485
1486 switch(mode)
1487 {
1488 case GL_POINTS:
1489 case GL_LINES:
1490 case GL_LINE_LOOP:
1491 case GL_LINE_STRIP:
1492 case GL_TRIANGLES:
1493 case GL_TRIANGLE_FAN:
1494 case GL_TRIANGLE_STRIP:
1495 break;
1496 default:
1497 return error(GL_INVALID_ENUM);
1498 }
1499
1500 if(count < 0)
1501 {
1502 return error(GL_INVALID_VALUE);
1503 }
1504
1505 es2::Context *context = es2::getContext();
1506
1507 if(context)
1508 {
1509 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1510 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1511 {
1512 return error(GL_INVALID_OPERATION);
1513 }
1514
1515 switch(type)
1516 {
1517 case GL_UNSIGNED_BYTE:
1518 case GL_UNSIGNED_SHORT:
1519 case GL_UNSIGNED_INT:
1520 break;
1521 default:
1522 return error(GL_INVALID_ENUM);
1523 }
1524
1525 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1526 }
1527}
1528
1529void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1530{
1531 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1532 mode, first, count, instanceCount);
1533
1534 switch(mode)
1535 {
1536 case GL_POINTS:
1537 case GL_LINES:
1538 case GL_LINE_LOOP:
1539 case GL_LINE_STRIP:
1540 case GL_TRIANGLES:
1541 case GL_TRIANGLE_FAN:
1542 case GL_TRIANGLE_STRIP:
1543 break;
1544 default:
1545 return error(GL_INVALID_ENUM);
1546 }
1547
1548 if(count < 0 || instanceCount < 0)
1549 {
1550 return error(GL_INVALID_VALUE);
1551 }
1552
1553 es2::Context *context = es2::getContext();
1554
1555 if(context)
1556 {
1557 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1558 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1559 {
1560 return error(GL_INVALID_OPERATION);
1561 }
1562
1563 context->drawArrays(mode, first, count, instanceCount);
1564 }
1565}
1566
1567void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1568{
1569 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1570 mode, count, type, indices, instanceCount);
1571
1572 switch(mode)
1573 {
1574 case GL_POINTS:
1575 case GL_LINES:
1576 case GL_LINE_LOOP:
1577 case GL_LINE_STRIP:
1578 case GL_TRIANGLES:
1579 case GL_TRIANGLE_FAN:
1580 case GL_TRIANGLE_STRIP:
1581 break;
1582 default:
1583 return error(GL_INVALID_ENUM);
1584 }
1585
1586 switch(type)
1587 {
1588 case GL_UNSIGNED_BYTE:
1589 case GL_UNSIGNED_SHORT:
1590 case GL_UNSIGNED_INT:
1591 break;
1592 default:
1593 return error(GL_INVALID_ENUM);
1594 }
1595
1596 if(count < 0 || instanceCount < 0)
1597 {
1598 return error(GL_INVALID_VALUE);
1599 }
1600
1601 es2::Context *context = es2::getContext();
1602
1603 if(context)
1604 {
1605 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1606 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1607 {
1608 return error(GL_INVALID_OPERATION);
1609 }
1610
1611 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1612 }
1613}
1614
1615void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1616{
1617 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1618
1619 es2::Context *context = es2::getContext();
1620
1621 if(context)
1622 {
1623 if(index >= es2::MAX_VERTEX_ATTRIBS)
1624 {
1625 return error(GL_INVALID_VALUE);
1626 }
1627
1628 context->setVertexAttribDivisor(index, divisor);
1629 }
1630}
1631
1632void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1633{
1634 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1635 mode, first, count, instanceCount);
1636
1637 switch(mode)
1638 {
1639 case GL_POINTS:
1640 case GL_LINES:
1641 case GL_LINE_LOOP:
1642 case GL_LINE_STRIP:
1643 case GL_TRIANGLES:
1644 case GL_TRIANGLE_FAN:
1645 case GL_TRIANGLE_STRIP:
1646 break;
1647 default:
1648 return error(GL_INVALID_ENUM);
1649 }
1650
1651 if(count < 0 || instanceCount < 0)
1652 {
1653 return error(GL_INVALID_VALUE);
1654 }
1655
1656 es2::Context *context = es2::getContext();
1657
1658 if(context)
1659 {
1660 if(!context->hasZeroDivisor())
1661 {
1662 return error(GL_INVALID_OPERATION);
1663 }
1664
1665 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1666 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1667 {
1668 return error(GL_INVALID_OPERATION);
1669 }
1670
1671 context->drawArrays(mode, first, count, instanceCount);
1672 }
1673}
1674
1675void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1676{
1677 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1678 mode, count, type, indices, 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 switch(type)
1695 {
1696 case GL_UNSIGNED_BYTE:
1697 case GL_UNSIGNED_SHORT:
1698 case GL_UNSIGNED_INT:
1699 break;
1700 default:
1701 return error(GL_INVALID_ENUM);
1702 }
1703
1704 if(count < 0 || instanceCount < 0)
1705 {
1706 return error(GL_INVALID_VALUE);
1707 }
1708
1709 es2::Context *context = es2::getContext();
1710
1711 if(context)
1712 {
1713 if(!context->hasZeroDivisor())
1714 {
1715 return error(GL_INVALID_OPERATION);
1716 }
1717
1718 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1719 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1720 {
1721 return error(GL_INVALID_OPERATION);
1722 }
1723
1724 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1725 }
1726}
1727
1728void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1729{
1730 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1731
1732 es2::Context *context = es2::getContext();
1733
1734 if(context)
1735 {
1736 if(index >= MAX_VERTEX_ATTRIBS)
1737 {
1738 return error(GL_INVALID_VALUE);
1739 }
1740
1741 context->setVertexAttribDivisor(index, divisor);
1742 }
1743}
1744
1745void Enable(GLenum cap)
1746{
1747 TRACE("(GLenum cap = 0x%X)", cap);
1748
1749 es2::Context *context = es2::getContext();
1750
1751 if(context)
1752 {
1753 switch(cap)
1754 {
1755 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1756 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1757 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1758 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1759 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1760 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1761 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1762 case GL_BLEND: context->setBlendEnabled(true); break;
1763 case GL_DITHER: context->setDitherEnabled(true); break;
1764 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1765 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1766 default:
1767 return error(GL_INVALID_ENUM);
1768 }
1769 }
1770}
1771
1772void EnableVertexAttribArray(GLuint index)
1773{
1774 TRACE("(GLuint index = %d)", index);
1775
1776 if(index >= es2::MAX_VERTEX_ATTRIBS)
1777 {
1778 return error(GL_INVALID_VALUE);
1779 }
1780
1781 es2::Context *context = es2::getContext();
1782
1783 if(context)
1784 {
1785 context->setVertexAttribArrayEnabled(index, true);
1786 }
1787}
1788
1789void EndQueryEXT(GLenum target)
1790{
1791 TRACE("GLenum target = 0x%X)", target);
1792
1793 switch(target)
1794 {
1795 case GL_ANY_SAMPLES_PASSED_EXT:
1796 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1797 break;
1798 default:
1799 return error(GL_INVALID_ENUM);
1800 }
1801
1802 es2::Context *context = es2::getContext();
1803
1804 if(context)
1805 {
1806 context->endQuery(target);
1807 }
1808}
1809
1810void FinishFenceNV(GLuint fence)
1811{
1812 TRACE("(GLuint fence = %d)", fence);
1813
1814 es2::Context *context = es2::getContext();
1815
1816 if(context)
1817 {
1818 es2::Fence *fenceObject = context->getFence(fence);
1819
1820 if(!fenceObject)
1821 {
1822 return error(GL_INVALID_OPERATION);
1823 }
1824
1825 fenceObject->finishFence();
1826 }
1827}
1828
1829void Finish(void)
1830{
1831 TRACE("()");
1832
1833 es2::Context *context = es2::getContext();
1834
1835 if(context)
1836 {
1837 context->finish();
1838 }
1839}
1840
1841void Flush(void)
1842{
1843 TRACE("()");
1844
1845 es2::Context *context = es2::getContext();
1846
1847 if(context)
1848 {
1849 context->flush();
1850 }
1851}
1852
1853void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1854{
1855 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1856 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1857
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001858 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001859 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1860 {
1861 return error(GL_INVALID_ENUM);
1862 }
1863
1864 es2::Context *context = es2::getContext();
1865
1866 if(context)
1867 {
1868 es2::Framebuffer *framebuffer = nullptr;
1869 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001870 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001871 {
1872 framebuffer = context->getReadFramebuffer();
1873 framebufferName = context->getReadFramebufferName();
1874 }
1875 else
1876 {
1877 framebuffer = context->getDrawFramebuffer();
1878 framebufferName = context->getDrawFramebufferName();
1879 }
1880
1881 if(!framebuffer || framebufferName == 0)
1882 {
1883 return error(GL_INVALID_OPERATION);
1884 }
1885
1886 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1887 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1888 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1889 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1890 if(renderbuffer != 0)
1891 {
1892 if(!context->getRenderbuffer(renderbuffer))
1893 {
1894 return error(GL_INVALID_OPERATION);
1895 }
1896 }
1897
Nicolas Capens0bac2852016-05-07 06:09:58 -04001898 switch(attachment)
1899 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001900 case GL_DEPTH_ATTACHMENT:
1901 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1902 break;
1903 case GL_STENCIL_ATTACHMENT:
1904 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1905 break;
1906 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001907 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1908 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1909 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001910 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001911 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1912 {
1913 return error(GL_INVALID_ENUM);
1914 }
1915 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1916 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001917 }
1918 }
1919}
1920
1921void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1922{
1923 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1924 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1925
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001926 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001927 {
1928 return error(GL_INVALID_ENUM);
1929 }
1930
1931 es2::Context *context = es2::getContext();
1932
1933 if(context)
1934 {
1935 if(texture == 0)
1936 {
1937 textarget = GL_NONE;
1938 }
1939 else
1940 {
1941 es2::Texture *tex = context->getTexture(texture);
1942
1943 if(!tex)
1944 {
1945 return error(GL_INVALID_OPERATION);
1946 }
1947
1948 switch(textarget)
1949 {
1950 case GL_TEXTURE_2D:
1951 if(tex->getTarget() != GL_TEXTURE_2D)
1952 {
1953 return error(GL_INVALID_OPERATION);
1954 }
1955 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001956 case GL_TEXTURE_RECTANGLE_ARB:
1957 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1958 {
1959 return error(GL_INVALID_OPERATION);
1960 }
1961 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001962 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1968 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1969 {
1970 return error(GL_INVALID_OPERATION);
1971 }
1972 break;
1973 default:
1974 return error(GL_INVALID_ENUM);
1975 }
1976
Nicolas Capens83463112018-06-12 23:55:16 -04001977 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001978 {
1979 return error(GL_INVALID_VALUE);
1980 }
1981
1982 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1983 {
1984 return error(GL_INVALID_VALUE);
1985 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001986
1987 if(tex->isCompressed(textarget, level))
1988 {
1989 return error(GL_INVALID_OPERATION);
1990 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001991 }
1992
1993 es2::Framebuffer *framebuffer = nullptr;
1994 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001995 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001996 {
1997 framebuffer = context->getReadFramebuffer();
1998 framebufferName = context->getReadFramebufferName();
1999 }
2000 else
2001 {
2002 framebuffer = context->getDrawFramebuffer();
2003 framebufferName = context->getDrawFramebufferName();
2004 }
2005
2006 if(framebufferName == 0 || !framebuffer)
2007 {
2008 return error(GL_INVALID_OPERATION);
2009 }
2010
2011 switch(attachment)
2012 {
Nicolas Capens83463112018-06-12 23:55:16 -04002013 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2014 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2015 case GL_DEPTH_STENCIL_ATTACHMENT:
2016 framebuffer->setDepthbuffer(textarget, texture, level);
2017 framebuffer->setStencilbuffer(textarget, texture, level);
2018 break;
2019 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002020 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2021 {
2022 return error(GL_INVALID_ENUM);
2023 }
2024 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2025 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002026 }
2027 }
2028}
2029
2030void FrontFace(GLenum mode)
2031{
2032 TRACE("(GLenum mode = 0x%X)", mode);
2033
2034 switch(mode)
2035 {
2036 case GL_CW:
2037 case GL_CCW:
2038 {
2039 es2::Context *context = es2::getContext();
2040
2041 if(context)
2042 {
2043 context->setFrontFace(mode);
2044 }
2045 }
2046 break;
2047 default:
2048 return error(GL_INVALID_ENUM);
2049 }
2050}
2051
2052void GenBuffers(GLsizei n, GLuint* buffers)
2053{
2054 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2055
2056 if(n < 0)
2057 {
2058 return error(GL_INVALID_VALUE);
2059 }
2060
2061 es2::Context *context = es2::getContext();
2062
2063 if(context)
2064 {
2065 for(int i = 0; i < n; i++)
2066 {
2067 buffers[i] = context->createBuffer();
2068 }
2069 }
2070}
2071
2072void GenerateMipmap(GLenum target)
2073{
2074 TRACE("(GLenum target = 0x%X)", target);
2075
2076 es2::Context *context = es2::getContext();
2077
2078 if(context)
2079 {
2080 es2::Texture *texture = nullptr;
2081
Nicolas Capens0bac2852016-05-07 06:09:58 -04002082 switch(target)
2083 {
2084 case GL_TEXTURE_2D:
2085 texture = context->getTexture2D();
2086 break;
2087 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002088 {
2089 TextureCubeMap *cube = context->getTextureCubeMap();
2090 texture = cube;
2091
2092 if(!cube->isCubeComplete())
2093 {
2094 return error(GL_INVALID_OPERATION);
2095 }
2096 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002097 break;
2098 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002099 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002100 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002101 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002102 texture = context->getTexture3D();
2103 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002104 case GL_TEXTURE_RECTANGLE_ARB:
2105 texture = context->getTexture2DRect();
2106 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002107 default:
2108 return error(GL_INVALID_ENUM);
2109 }
2110
Nicolas Capens83463112018-06-12 23:55:16 -04002111 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002112 {
2113 return error(GL_INVALID_OPERATION);
2114 }
2115
Nicolas Capens0bac2852016-05-07 06:09:58 -04002116 texture->generateMipmaps();
2117 }
2118}
2119
2120void GenFencesNV(GLsizei n, GLuint* fences)
2121{
2122 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2123
2124 if(n < 0)
2125 {
2126 return error(GL_INVALID_VALUE);
2127 }
2128
2129 es2::Context *context = es2::getContext();
2130
2131 if(context)
2132 {
2133 for(int i = 0; i < n; i++)
2134 {
2135 fences[i] = context->createFence();
2136 }
2137 }
2138}
2139
2140void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2141{
2142 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2143
2144 if(n < 0)
2145 {
2146 return error(GL_INVALID_VALUE);
2147 }
2148
2149 es2::Context *context = es2::getContext();
2150
2151 if(context)
2152 {
2153 for(int i = 0; i < n; i++)
2154 {
2155 framebuffers[i] = context->createFramebuffer();
2156 }
2157 }
2158}
2159
2160void GenQueriesEXT(GLsizei n, GLuint* ids)
2161{
2162 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2163
2164 if(n < 0)
2165 {
2166 return error(GL_INVALID_VALUE);
2167 }
2168
2169 es2::Context *context = es2::getContext();
2170
2171 if(context)
2172 {
2173 for(int i = 0; i < n; i++)
2174 {
2175 ids[i] = context->createQuery();
2176 }
2177 }
2178}
2179
2180void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2181{
2182 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2183
2184 if(n < 0)
2185 {
2186 return error(GL_INVALID_VALUE);
2187 }
2188
2189 es2::Context *context = es2::getContext();
2190
2191 if(context)
2192 {
2193 for(int i = 0; i < n; i++)
2194 {
2195 renderbuffers[i] = context->createRenderbuffer();
2196 }
2197 }
2198}
2199
2200void GenTextures(GLsizei n, GLuint* textures)
2201{
2202 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2203
2204 if(n < 0)
2205 {
2206 return error(GL_INVALID_VALUE);
2207 }
2208
2209 es2::Context *context = es2::getContext();
2210
2211 if(context)
2212 {
2213 for(int i = 0; i < n; i++)
2214 {
2215 textures[i] = context->createTexture();
2216 }
2217 }
2218}
2219
2220void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2221{
2222 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2223 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2224 program, index, bufsize, length, size, type, name);
2225
2226 if(bufsize < 0)
2227 {
2228 return error(GL_INVALID_VALUE);
2229 }
2230
2231 es2::Context *context = es2::getContext();
2232
2233 if(context)
2234 {
2235 es2::Program *programObject = context->getProgram(program);
2236
2237 if(!programObject)
2238 {
2239 if(context->getShader(program))
2240 {
2241 return error(GL_INVALID_OPERATION);
2242 }
2243 else
2244 {
2245 return error(GL_INVALID_VALUE);
2246 }
2247 }
2248
2249 if(index >= programObject->getActiveAttributeCount())
2250 {
2251 return error(GL_INVALID_VALUE);
2252 }
2253
2254 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2255 }
2256}
2257
2258void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2259{
2260 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2261 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2262 program, index, bufsize, length, size, type, name);
2263
2264 if(bufsize < 0)
2265 {
2266 return error(GL_INVALID_VALUE);
2267 }
2268
2269 es2::Context *context = es2::getContext();
2270
2271 if(context)
2272 {
2273 es2::Program *programObject = context->getProgram(program);
2274
2275 if(!programObject)
2276 {
2277 if(context->getShader(program))
2278 {
2279 return error(GL_INVALID_OPERATION);
2280 }
2281 else
2282 {
2283 return error(GL_INVALID_VALUE);
2284 }
2285 }
2286
2287 if(index >= programObject->getActiveUniformCount())
2288 {
2289 return error(GL_INVALID_VALUE);
2290 }
2291
2292 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2293 }
2294}
2295
2296void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2297{
2298 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2299 program, maxcount, count, shaders);
2300
2301 if(maxcount < 0)
2302 {
2303 return error(GL_INVALID_VALUE);
2304 }
2305
2306 es2::Context *context = es2::getContext();
2307
2308 if(context)
2309 {
2310 es2::Program *programObject = context->getProgram(program);
2311
2312 if(!programObject)
2313 {
2314 if(context->getShader(program))
2315 {
2316 return error(GL_INVALID_OPERATION);
2317 }
2318 else
2319 {
2320 return error(GL_INVALID_VALUE);
2321 }
2322 }
2323
2324 return programObject->getAttachedShaders(maxcount, count, shaders);
2325 }
2326}
2327
2328int GetAttribLocation(GLuint program, const GLchar* name)
2329{
2330 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2331
2332 es2::Context *context = es2::getContext();
2333
2334 if(context)
2335 {
2336
2337 es2::Program *programObject = context->getProgram(program);
2338
2339 if(!programObject)
2340 {
2341 if(context->getShader(program))
2342 {
2343 return error(GL_INVALID_OPERATION, -1);
2344 }
2345 else
2346 {
2347 return error(GL_INVALID_VALUE, -1);
2348 }
2349 }
2350
2351 if(!programObject->isLinked())
2352 {
2353 return error(GL_INVALID_OPERATION, -1);
2354 }
2355
2356 return programObject->getAttributeLocation(name);
2357 }
2358
2359 return -1;
2360}
2361
2362void GetBooleanv(GLenum pname, GLboolean* params)
2363{
2364 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2365
2366 es2::Context *context = es2::getContext();
2367
2368 if(context)
2369 {
2370 if(!(context->getBooleanv(pname, params)))
2371 {
2372 GLenum nativeType;
2373 unsigned int numParams = 0;
2374 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2375 return error(GL_INVALID_ENUM);
2376
2377 if(numParams == 0)
2378 return; // it is known that the pname is valid, but there are no parameters to return
2379
2380 if(nativeType == GL_FLOAT)
2381 {
2382 GLfloat *floatParams = nullptr;
2383 floatParams = new GLfloat[numParams];
2384
2385 context->getFloatv(pname, floatParams);
2386
2387 for(unsigned int i = 0; i < numParams; ++i)
2388 {
2389 if(floatParams[i] == 0.0f)
2390 params[i] = GL_FALSE;
2391 else
2392 params[i] = GL_TRUE;
2393 }
2394
2395 delete [] floatParams;
2396 }
2397 else if(nativeType == GL_INT)
2398 {
2399 GLint *intParams = nullptr;
2400 intParams = new GLint[numParams];
2401
2402 context->getIntegerv(pname, intParams);
2403
2404 for(unsigned int i = 0; i < numParams; ++i)
2405 {
2406 if(intParams[i] == 0)
2407 params[i] = GL_FALSE;
2408 else
2409 params[i] = GL_TRUE;
2410 }
2411
2412 delete [] intParams;
2413 }
2414 }
2415 }
2416}
2417
2418void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2419{
2420 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2421
2422 es2::Context *context = es2::getContext();
2423
2424 if(context)
2425 {
2426 es2::Buffer *buffer;
2427 if(!context->getBuffer(target, &buffer))
2428 {
2429 return error(GL_INVALID_ENUM);
2430 }
2431
2432 if(!buffer)
2433 {
2434 // A null buffer means that "0" is bound to the requested buffer target
2435 return error(GL_INVALID_OPERATION);
2436 }
2437
Nicolas Capens0bac2852016-05-07 06:09:58 -04002438 switch(pname)
2439 {
2440 case GL_BUFFER_USAGE:
2441 *params = buffer->usage();
2442 break;
2443 case GL_BUFFER_SIZE:
2444 *params = (GLint)buffer->size();
2445 break;
2446 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002447 *params = buffer->access();
2448 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002449 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002450 *params = buffer->isMapped();
2451 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002452 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002453 *params = (GLint)buffer->length();
2454 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002455 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002456 *params = (GLint)buffer->offset();
2457 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002458 default:
2459 return error(GL_INVALID_ENUM);
2460 }
2461 }
2462}
2463
2464GLenum GetError(void)
2465{
2466 TRACE("()");
2467
2468 es2::Context *context = es2::getContext();
2469
2470 if(context)
2471 {
2472 return context->getError();
2473 }
2474
2475 return GL_NO_ERROR;
2476}
2477
2478void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2479{
2480 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2481
2482 es2::Context *context = es2::getContext();
2483
2484 if(context)
2485 {
2486 es2::Fence *fenceObject = context->getFence(fence);
2487
2488 if(!fenceObject)
2489 {
2490 return error(GL_INVALID_OPERATION);
2491 }
2492
2493 fenceObject->getFenceiv(pname, params);
2494 }
2495}
2496
2497void GetFloatv(GLenum pname, GLfloat* params)
2498{
2499 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2500
2501 es2::Context *context = es2::getContext();
2502
2503 if(context)
2504 {
2505 if(!(context->getFloatv(pname, params)))
2506 {
2507 GLenum nativeType;
2508 unsigned int numParams = 0;
2509 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2510 return error(GL_INVALID_ENUM);
2511
2512 if(numParams == 0)
2513 return; // it is known that the pname is valid, but that there are no parameters to return.
2514
2515 if(nativeType == GL_BOOL)
2516 {
2517 GLboolean *boolParams = nullptr;
2518 boolParams = new GLboolean[numParams];
2519
2520 context->getBooleanv(pname, boolParams);
2521
2522 for(unsigned int i = 0; i < numParams; ++i)
2523 {
2524 if(boolParams[i] == GL_FALSE)
2525 params[i] = 0.0f;
2526 else
2527 params[i] = 1.0f;
2528 }
2529
2530 delete [] boolParams;
2531 }
2532 else if(nativeType == GL_INT)
2533 {
2534 GLint *intParams = nullptr;
2535 intParams = new GLint[numParams];
2536
2537 context->getIntegerv(pname, intParams);
2538
2539 for(unsigned int i = 0; i < numParams; ++i)
2540 {
2541 params[i] = (GLfloat)intParams[i];
2542 }
2543
2544 delete [] intParams;
2545 }
2546 }
2547 }
2548}
2549
2550void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2551{
2552 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2553 target, attachment, pname, params);
2554
2555 es2::Context *context = es2::getContext();
2556
2557 if(context)
2558 {
2559 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2560 {
2561 return error(GL_INVALID_ENUM);
2562 }
2563
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002564 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002565
Nicolas Capens0bac2852016-05-07 06:09:58 -04002566 if(target == GL_READ_FRAMEBUFFER)
2567 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002568 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002569 }
2570 else
2571 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002572 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002573 }
2574
Nicolas Capens0bac2852016-05-07 06:09:58 -04002575 switch(attachment)
2576 {
2577 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002578 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002579 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002580 if(framebufferName != 0)
2581 {
2582 return error(GL_INVALID_OPERATION);
2583 }
2584 break;
2585 case GL_DEPTH_ATTACHMENT:
2586 case GL_STENCIL_ATTACHMENT:
2587 if(framebufferName == 0)
2588 {
2589 return error(GL_INVALID_OPERATION);
2590 }
2591 break;
2592 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002593 if(framebufferName == 0)
2594 {
2595 return error(GL_INVALID_OPERATION);
2596 }
2597 break;
2598 default:
2599 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2600 {
2601 if(framebufferName == 0)
2602 {
2603 return error(GL_INVALID_OPERATION);
2604 }
2605 }
2606 else return error(GL_INVALID_ENUM);
2607 }
2608
2609 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2610
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002611 if(!framebuffer)
2612 {
2613 return error(GL_INVALID_OPERATION);
2614 }
2615
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002616 GLenum attachmentType;
2617 GLuint attachmentHandle;
2618 GLint attachmentLayer;
2619 Renderbuffer *renderbuffer = nullptr;
2620 switch(attachment)
2621 {
2622 case GL_BACK:
2623 attachmentType = framebuffer->getColorbufferType(0);
2624 attachmentHandle = framebuffer->getColorbufferName(0);
2625 attachmentLayer = framebuffer->getColorbufferLayer(0);
2626 renderbuffer = framebuffer->getColorbuffer(0);
2627 break;
2628 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002629 case GL_DEPTH_ATTACHMENT:
2630 attachmentType = framebuffer->getDepthbufferType();
2631 attachmentHandle = framebuffer->getDepthbufferName();
2632 attachmentLayer = framebuffer->getDepthbufferLayer();
2633 renderbuffer = framebuffer->getDepthbuffer();
2634 break;
2635 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002636 case GL_STENCIL_ATTACHMENT:
2637 attachmentType = framebuffer->getStencilbufferType();
2638 attachmentHandle = framebuffer->getStencilbufferName();
2639 attachmentLayer = framebuffer->getStencilbufferLayer();
2640 renderbuffer = framebuffer->getStencilbuffer();
2641 break;
2642 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002643 attachmentType = framebuffer->getDepthbufferType();
2644 attachmentHandle = framebuffer->getDepthbufferName();
2645 attachmentLayer = framebuffer->getDepthbufferLayer();
2646 renderbuffer = framebuffer->getDepthbuffer();
2647
2648 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002649 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002650 // Different attachments to DEPTH and STENCIL, query fails
2651 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002652 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002653 break;
2654 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002655 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2656 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2657 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2658 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2659 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2660 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002661 }
2662
2663 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002664 if(framebufferName == 0)
2665 {
2666 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2667 }
2668 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002669 {
2670 attachmentObjectType = attachmentType;
2671 }
2672 else if(es2::IsTextureTarget(attachmentType))
2673 {
2674 attachmentObjectType = GL_TEXTURE;
2675 }
2676 else UNREACHABLE(attachmentType);
2677
2678 if(attachmentObjectType != GL_NONE)
2679 {
2680 switch(pname)
2681 {
2682 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2683 *params = attachmentObjectType;
2684 break;
2685 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002686 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002687 {
2688 *params = attachmentHandle;
2689 }
2690 else
2691 {
2692 return error(GL_INVALID_ENUM);
2693 }
2694 break;
2695 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2696 if(attachmentObjectType == GL_TEXTURE)
2697 {
Nicolas Capens83463112018-06-12 23:55:16 -04002698 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002699 }
2700 else
2701 {
2702 return error(GL_INVALID_ENUM);
2703 }
2704 break;
2705 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2706 if(attachmentObjectType == GL_TEXTURE)
2707 {
2708 if(es2::IsCubemapTextureTarget(attachmentType))
2709 {
2710 *params = attachmentType;
2711 }
2712 else
2713 {
2714 *params = 0;
2715 }
2716 }
2717 else
2718 {
2719 return error(GL_INVALID_ENUM);
2720 }
2721 break;
2722 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002723 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002724 break;
2725 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002726 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002727 break;
2728 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002729 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002730 break;
2731 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002732 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002733 break;
2734 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002735 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002736 break;
2737 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002738 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002739 break;
2740 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002741 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002742 break;
2743 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002744 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2745 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002746 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002747 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002748 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002749
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002750 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002751 break;
2752 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002753 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002754 break;
2755 default:
2756 return error(GL_INVALID_ENUM);
2757 }
2758 }
2759 else
2760 {
2761 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2762 // is NONE, then querying any other pname will generate INVALID_ENUM.
2763
2764 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2765 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2766 // INVALID_OPERATION for all other pnames
2767
2768 switch(pname)
2769 {
2770 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2771 *params = GL_NONE;
2772 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002773 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002774 *params = 0;
2775 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002776 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002777 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002778 }
2779 }
2780 }
2781}
2782
2783GLenum GetGraphicsResetStatusEXT(void)
2784{
2785 TRACE("()");
2786
2787 return GL_NO_ERROR;
2788}
2789
2790void GetIntegerv(GLenum pname, GLint* params)
2791{
2792 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2793
2794 es2::Context *context = es2::getContext();
2795
2796 if(!context)
2797 {
2798 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2799 #ifdef __ANDROID__
2800 ALOGI("expected_badness glGetIntegerv() called without current context.");
2801 #else
2802 ERR("glGetIntegerv() called without current context.");
2803 #endif
2804
2805 // This is not spec compliant! When there is no current GL context, functions should
2806 // have no side effects. Google Maps queries these values before creating a context,
2807 // so we need this as a bug-compatible workaround.
2808 switch(pname)
2809 {
2810 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2811 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2812 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2813 case GL_STENCIL_BITS: *params = 8; return;
2814 case GL_ALIASED_LINE_WIDTH_RANGE:
2815 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2816 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2817 return;
2818 }
2819 }
2820
2821 if(context)
2822 {
2823 if(!(context->getIntegerv(pname, params)))
2824 {
2825 GLenum nativeType;
2826 unsigned int numParams = 0;
2827 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2828 return error(GL_INVALID_ENUM);
2829
2830 if(numParams == 0)
2831 return; // it is known that pname is valid, but there are no parameters to return
2832
2833 if(nativeType == GL_BOOL)
2834 {
2835 GLboolean *boolParams = nullptr;
2836 boolParams = new GLboolean[numParams];
2837
2838 context->getBooleanv(pname, boolParams);
2839
2840 for(unsigned int i = 0; i < numParams; ++i)
2841 {
2842 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2843 }
2844
2845 delete [] boolParams;
2846 }
2847 else if(nativeType == GL_FLOAT)
2848 {
2849 GLfloat *floatParams = nullptr;
2850 floatParams = new GLfloat[numParams];
2851
2852 context->getFloatv(pname, floatParams);
2853
2854 for(unsigned int i = 0; i < numParams; ++i)
2855 {
2856 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2857 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002858 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002859 }
2860 else
2861 {
2862 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2863 }
2864 }
2865
2866 delete [] floatParams;
2867 }
2868 }
2869 }
2870}
2871
2872void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2873{
2874 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2875
2876 es2::Context *context = es2::getContext();
2877
2878 if(context)
2879 {
2880 es2::Program *programObject = context->getProgram(program);
2881
2882 if(!programObject)
2883 {
2884 if(context->getShader(program))
2885 {
2886 return error(GL_INVALID_OPERATION);
2887 }
2888 else
2889 {
2890 return error(GL_INVALID_VALUE);
2891 }
2892 }
2893
Nicolas Capens0bac2852016-05-07 06:09:58 -04002894 switch(pname)
2895 {
2896 case GL_DELETE_STATUS:
2897 *params = programObject->isFlaggedForDeletion();
2898 return;
2899 case GL_LINK_STATUS:
2900 *params = programObject->isLinked();
2901 return;
2902 case GL_VALIDATE_STATUS:
2903 *params = programObject->isValidated();
2904 return;
2905 case GL_INFO_LOG_LENGTH:
2906 *params = (GLint)programObject->getInfoLogLength();
2907 return;
2908 case GL_ATTACHED_SHADERS:
2909 *params = programObject->getAttachedShadersCount();
2910 return;
2911 case GL_ACTIVE_ATTRIBUTES:
2912 *params = (GLint)programObject->getActiveAttributeCount();
2913 return;
2914 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2915 *params = programObject->getActiveAttributeMaxLength();
2916 return;
2917 case GL_ACTIVE_UNIFORMS:
2918 *params = (GLint)programObject->getActiveUniformCount();
2919 return;
2920 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2921 *params = programObject->getActiveUniformMaxLength();
2922 return;
2923 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002924 *params = (GLint)programObject->getActiveUniformBlockCount();
2925 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002926 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002927 *params = programObject->getActiveUniformBlockMaxLength();
2928 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002929 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002930 *params = programObject->getTransformFeedbackBufferMode();
2931 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002932 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002933 *params = programObject->getTransformFeedbackVaryingCount();
2934 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002935 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002936 *params = programObject->getTransformFeedbackVaryingMaxLength();
2937 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002938 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002939 *params = programObject->getBinaryRetrievableHint();
2940 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002941 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002942 *params = programObject->getBinaryLength();
2943 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002944 default:
2945 return error(GL_INVALID_ENUM);
2946 }
2947 }
2948}
2949
2950void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2951{
2952 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2953 program, bufsize, length, infolog);
2954
2955 if(bufsize < 0)
2956 {
2957 return error(GL_INVALID_VALUE);
2958 }
2959
2960 es2::Context *context = es2::getContext();
2961
2962 if(context)
2963 {
2964 es2::Program *programObject = context->getProgram(program);
2965
2966 if(!programObject)
2967 {
2968 if(context->getShader(program))
2969 {
2970 return error(GL_INVALID_OPERATION);
2971 }
2972 else
2973 {
2974 return error(GL_INVALID_VALUE);
2975 }
2976 }
2977
2978 programObject->getInfoLog(bufsize, length, infolog);
2979 }
2980}
2981
2982void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2983{
2984 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2985
2986 switch(pname)
2987 {
2988 case GL_CURRENT_QUERY_EXT:
2989 break;
2990 default:
2991 return error(GL_INVALID_ENUM);
2992 }
2993
2994 es2::Context *context = es2::getContext();
2995
2996 if(context)
2997 {
2998 params[0] = context->getActiveQuery(target);
2999 }
3000}
3001
3002void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3003{
3004 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3005
3006 switch(pname)
3007 {
3008 case GL_QUERY_RESULT_EXT:
3009 case GL_QUERY_RESULT_AVAILABLE_EXT:
3010 break;
3011 default:
3012 return error(GL_INVALID_ENUM);
3013 }
3014
3015 es2::Context *context = es2::getContext();
3016
3017 if(context)
3018 {
3019 es2::Query *queryObject = context->getQuery(name);
3020
3021 if(!queryObject)
3022 {
3023 return error(GL_INVALID_OPERATION);
3024 }
3025
3026 if(context->getActiveQuery(queryObject->getType()) == name)
3027 {
3028 return error(GL_INVALID_OPERATION);
3029 }
3030
3031 switch(pname)
3032 {
3033 case GL_QUERY_RESULT_EXT:
3034 params[0] = queryObject->getResult();
3035 break;
3036 case GL_QUERY_RESULT_AVAILABLE_EXT:
3037 params[0] = queryObject->isResultAvailable();
3038 break;
3039 default:
3040 ASSERT(false);
3041 }
3042 }
3043}
3044
3045void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3046{
3047 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3048
3049 es2::Context *context = es2::getContext();
3050
3051 if(context)
3052 {
3053 if(target != GL_RENDERBUFFER)
3054 {
3055 return error(GL_INVALID_ENUM);
3056 }
3057
3058 if(context->getRenderbufferName() == 0)
3059 {
3060 return error(GL_INVALID_OPERATION);
3061 }
3062
3063 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3064
3065 switch(pname)
3066 {
3067 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3068 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003069 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3070 {
3071 GLint internalformat = renderbuffer->getFormat();
3072 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3073 }
3074 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003075 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3076 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3077 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3078 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3079 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3080 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003081 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003082 default:
3083 return error(GL_INVALID_ENUM);
3084 }
3085 }
3086}
3087
3088void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3089{
3090 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3091
3092 es2::Context *context = es2::getContext();
3093
3094 if(context)
3095 {
3096 es2::Shader *shaderObject = context->getShader(shader);
3097
3098 if(!shaderObject)
3099 {
3100 if(context->getProgram(shader))
3101 {
3102 return error(GL_INVALID_OPERATION);
3103 }
3104 else
3105 {
3106 return error(GL_INVALID_VALUE);
3107 }
3108 }
3109
3110 switch(pname)
3111 {
3112 case GL_SHADER_TYPE:
3113 *params = shaderObject->getType();
3114 return;
3115 case GL_DELETE_STATUS:
3116 *params = shaderObject->isFlaggedForDeletion();
3117 return;
3118 case GL_COMPILE_STATUS:
3119 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3120 return;
3121 case GL_INFO_LOG_LENGTH:
3122 *params = (GLint)shaderObject->getInfoLogLength();
3123 return;
3124 case GL_SHADER_SOURCE_LENGTH:
3125 *params = (GLint)shaderObject->getSourceLength();
3126 return;
3127 default:
3128 return error(GL_INVALID_ENUM);
3129 }
3130 }
3131}
3132
3133void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3134{
3135 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3136 shader, bufsize, length, infolog);
3137
3138 if(bufsize < 0)
3139 {
3140 return error(GL_INVALID_VALUE);
3141 }
3142
3143 es2::Context *context = es2::getContext();
3144
3145 if(context)
3146 {
3147 es2::Shader *shaderObject = context->getShader(shader);
3148
3149 if(!shaderObject)
3150 {
3151 if(context->getProgram(shader))
3152 {
3153 return error(GL_INVALID_OPERATION);
3154 }
3155 else
3156 {
3157 return error(GL_INVALID_VALUE);
3158 }
3159 }
3160
3161 shaderObject->getInfoLog(bufsize, length, infolog);
3162 }
3163}
3164
3165void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3166{
3167 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3168 shadertype, precisiontype, range, precision);
3169
3170 switch(shadertype)
3171 {
3172 case GL_VERTEX_SHADER:
3173 case GL_FRAGMENT_SHADER:
3174 break;
3175 default:
3176 return error(GL_INVALID_ENUM);
3177 }
3178
3179 switch(precisiontype)
3180 {
3181 case GL_LOW_FLOAT:
3182 case GL_MEDIUM_FLOAT:
3183 case GL_HIGH_FLOAT:
3184 // IEEE 754 single-precision
3185 range[0] = 127;
3186 range[1] = 127;
3187 *precision = 23;
3188 break;
3189 case GL_LOW_INT:
3190 case GL_MEDIUM_INT:
3191 case GL_HIGH_INT:
3192 // Full integer precision is supported
3193 range[0] = 31;
3194 range[1] = 30;
3195 *precision = 0;
3196 break;
3197 default:
3198 return error(GL_INVALID_ENUM);
3199 }
3200}
3201
3202void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3203{
3204 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3205 shader, bufsize, length, source);
3206
3207 if(bufsize < 0)
3208 {
3209 return error(GL_INVALID_VALUE);
3210 }
3211
3212 es2::Context *context = es2::getContext();
3213
3214 if(context)
3215 {
3216 es2::Shader *shaderObject = context->getShader(shader);
3217
3218 if(!shaderObject)
3219 {
3220 if(context->getProgram(shader))
3221 {
3222 return error(GL_INVALID_OPERATION);
3223 }
3224 else
3225 {
3226 return error(GL_INVALID_VALUE);
3227 }
3228 }
3229
3230 shaderObject->getSource(bufsize, length, source);
3231 }
3232}
3233
3234const GLubyte* GetString(GLenum name)
3235{
3236 TRACE("(GLenum name = 0x%X)", name);
3237
3238 switch(name)
3239 {
3240 case GL_VENDOR:
3241 return (GLubyte*)"Google Inc.";
3242 case GL_RENDERER:
3243 return (GLubyte*)"Google SwiftShader";
3244 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003245 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003246 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003247 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003248 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003249 {
3250 es2::Context *context = es2::getContext();
3251 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3252 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003253 default:
3254 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3255 }
3256}
3257
3258void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3259{
3260 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3261
3262 es2::Context *context = es2::getContext();
3263
3264 if(context)
3265 {
3266 es2::Texture *texture;
3267
Nicolas Capens0bac2852016-05-07 06:09:58 -04003268 switch(target)
3269 {
Nicolas Capens83463112018-06-12 23:55:16 -04003270 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3271 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3272 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3273 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3274 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3275 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003276 default:
3277 return error(GL_INVALID_ENUM);
3278 }
3279
3280 switch(pname)
3281 {
3282 case GL_TEXTURE_MAG_FILTER:
3283 *params = (GLfloat)texture->getMagFilter();
3284 break;
3285 case GL_TEXTURE_MIN_FILTER:
3286 *params = (GLfloat)texture->getMinFilter();
3287 break;
3288 case GL_TEXTURE_WRAP_S:
3289 *params = (GLfloat)texture->getWrapS();
3290 break;
3291 case GL_TEXTURE_WRAP_T:
3292 *params = (GLfloat)texture->getWrapT();
3293 break;
3294 case GL_TEXTURE_WRAP_R_OES:
3295 *params = (GLfloat)texture->getWrapR();
3296 break;
3297 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3298 *params = texture->getMaxAnisotropy();
3299 break;
3300 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3301 *params = (GLfloat)1;
3302 break;
3303 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003304 *params = (GLfloat)texture->getBaseLevel();
3305 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003306 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003307 *params = (GLfloat)texture->getCompareFunc();
3308 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003309 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003310 *params = (GLfloat)texture->getCompareMode();
3311 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003312 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003313 *params = (GLfloat)texture->getImmutableFormat();
3314 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003315 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003316 *params = (GLfloat)texture->getImmutableLevels();
3317 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003318 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003319 *params = (GLfloat)texture->getMaxLevel();
3320 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003321 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003322 *params = texture->getMaxLOD();
3323 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003324 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003325 *params = texture->getMinLOD();
3326 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003327 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003328 *params = (GLfloat)texture->getSwizzleR();
3329 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003330 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003331 *params = (GLfloat)texture->getSwizzleG();
3332 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003333 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003334 *params = (GLfloat)texture->getSwizzleB();
3335 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003336 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003337 *params = (GLfloat)texture->getSwizzleA();
3338 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003339 default:
3340 return error(GL_INVALID_ENUM);
3341 }
3342 }
3343}
3344
3345void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3346{
3347 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3348
3349 es2::Context *context = es2::getContext();
3350
3351 if(context)
3352 {
3353 es2::Texture *texture;
3354
Nicolas Capens0bac2852016-05-07 06:09:58 -04003355 switch(target)
3356 {
Nicolas Capens83463112018-06-12 23:55:16 -04003357 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3358 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3359 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3360 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3361 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3362 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003363 default:
3364 return error(GL_INVALID_ENUM);
3365 }
3366
3367 switch(pname)
3368 {
3369 case GL_TEXTURE_MAG_FILTER:
3370 *params = texture->getMagFilter();
3371 break;
3372 case GL_TEXTURE_MIN_FILTER:
3373 *params = texture->getMinFilter();
3374 break;
3375 case GL_TEXTURE_WRAP_S:
3376 *params = texture->getWrapS();
3377 break;
3378 case GL_TEXTURE_WRAP_T:
3379 *params = texture->getWrapT();
3380 break;
3381 case GL_TEXTURE_WRAP_R_OES:
3382 *params = texture->getWrapR();
3383 break;
3384 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3385 *params = (GLint)texture->getMaxAnisotropy();
3386 break;
3387 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3388 *params = 1;
3389 break;
3390 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003391 *params = texture->getBaseLevel();
3392 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003393 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003394 *params = (GLint)texture->getCompareFunc();
3395 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003396 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003397 *params = (GLint)texture->getCompareMode();
3398 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003399 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003400 *params = (GLint)texture->getImmutableFormat();
3401 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003402 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003403 *params = (GLint)texture->getImmutableLevels();
3404 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003405 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003406 *params = texture->getMaxLevel();
3407 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003408 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003409 *params = (GLint)roundf(texture->getMaxLOD());
3410 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003411 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003412 *params = (GLint)roundf(texture->getMinLOD());
3413 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003414 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003415 *params = (GLint)texture->getSwizzleR();
3416 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003417 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003418 *params = (GLint)texture->getSwizzleG();
3419 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003420 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003421 *params = (GLint)texture->getSwizzleB();
3422 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003423 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003424 *params = (GLint)texture->getSwizzleA();
3425 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003426 default:
3427 return error(GL_INVALID_ENUM);
3428 }
3429 }
3430}
3431
3432void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3433{
3434 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3435 program, location, bufSize, params);
3436
3437 if(bufSize < 0)
3438 {
3439 return error(GL_INVALID_VALUE);
3440 }
3441
3442 es2::Context *context = es2::getContext();
3443
3444 if(context)
3445 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003446 es2::Program *programObject = context->getProgram(program);
3447
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003448 if(!programObject)
3449 {
3450 if(context->getShader(program))
3451 {
3452 return error(GL_INVALID_OPERATION);
3453 }
3454 else
3455 {
3456 return error(GL_INVALID_VALUE);
3457 }
3458 }
3459
3460 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003461 {
3462 return error(GL_INVALID_OPERATION);
3463 }
3464
3465 if(!programObject->getUniformfv(location, &bufSize, params))
3466 {
3467 return error(GL_INVALID_OPERATION);
3468 }
3469 }
3470}
3471
3472void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3473{
3474 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3475
3476 es2::Context *context = es2::getContext();
3477
3478 if(context)
3479 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003480 es2::Program *programObject = context->getProgram(program);
3481
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003482 if(!programObject)
3483 {
3484 if(context->getShader(program))
3485 {
3486 return error(GL_INVALID_OPERATION);
3487 }
3488 else
3489 {
3490 return error(GL_INVALID_VALUE);
3491 }
3492 }
3493
3494 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003495 {
3496 return error(GL_INVALID_OPERATION);
3497 }
3498
3499 if(!programObject->getUniformfv(location, nullptr, params))
3500 {
3501 return error(GL_INVALID_OPERATION);
3502 }
3503 }
3504}
3505
3506void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3507{
3508 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3509 program, location, bufSize, params);
3510
3511 if(bufSize < 0)
3512 {
3513 return error(GL_INVALID_VALUE);
3514 }
3515
3516 es2::Context *context = es2::getContext();
3517
3518 if(context)
3519 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003520 es2::Program *programObject = context->getProgram(program);
3521
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003522 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003523 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003524 if(context->getShader(program))
3525 {
3526 return error(GL_INVALID_OPERATION);
3527 }
3528 else
3529 {
3530 return error(GL_INVALID_VALUE);
3531 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003532 }
3533
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003534 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003535 {
3536 return error(GL_INVALID_OPERATION);
3537 }
3538
3539 if(!programObject->getUniformiv(location, &bufSize, params))
3540 {
3541 return error(GL_INVALID_OPERATION);
3542 }
3543 }
3544}
3545
3546void GetUniformiv(GLuint program, GLint location, GLint* params)
3547{
3548 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3549
3550 es2::Context *context = es2::getContext();
3551
3552 if(context)
3553 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003554 es2::Program *programObject = context->getProgram(program);
3555
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003556 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003557 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003558 if(context->getShader(program))
3559 {
3560 return error(GL_INVALID_OPERATION);
3561 }
3562 else
3563 {
3564 return error(GL_INVALID_VALUE);
3565 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003566 }
3567
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003568 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003569 {
3570 return error(GL_INVALID_OPERATION);
3571 }
3572
3573 if(!programObject->getUniformiv(location, nullptr, params))
3574 {
3575 return error(GL_INVALID_OPERATION);
3576 }
3577 }
3578}
3579
3580int GetUniformLocation(GLuint program, const GLchar* name)
3581{
3582 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3583
3584 es2::Context *context = es2::getContext();
3585
3586 if(strstr(name, "gl_") == name)
3587 {
3588 return -1;
3589 }
3590
3591 if(context)
3592 {
3593 es2::Program *programObject = context->getProgram(program);
3594
3595 if(!programObject)
3596 {
3597 if(context->getShader(program))
3598 {
3599 return error(GL_INVALID_OPERATION, -1);
3600 }
3601 else
3602 {
3603 return error(GL_INVALID_VALUE, -1);
3604 }
3605 }
3606
3607 if(!programObject->isLinked())
3608 {
3609 return error(GL_INVALID_OPERATION, -1);
3610 }
3611
3612 return programObject->getUniformLocation(name);
3613 }
3614
3615 return -1;
3616}
3617
3618void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3619{
3620 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3621
3622 es2::Context *context = es2::getContext();
3623
3624 if(context)
3625 {
3626 if(index >= es2::MAX_VERTEX_ATTRIBS)
3627 {
3628 return error(GL_INVALID_VALUE);
3629 }
3630
3631 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3632
Nicolas Capens0bac2852016-05-07 06:09:58 -04003633 switch(pname)
3634 {
3635 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3636 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3637 break;
3638 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3639 *params = (GLfloat)attribState.mSize;
3640 break;
3641 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3642 *params = (GLfloat)attribState.mStride;
3643 break;
3644 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3645 *params = (GLfloat)attribState.mType;
3646 break;
3647 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3648 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3649 break;
3650 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3651 *params = (GLfloat)attribState.mBoundBuffer.name();
3652 break;
3653 case GL_CURRENT_VERTEX_ATTRIB:
3654 {
3655 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3656 for(int i = 0; i < 4; ++i)
3657 {
3658 params[i] = attrib.getCurrentValueF(i);
3659 }
3660 }
3661 break;
3662 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003663 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3664 break;
3665 default:
3666 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003667 }
3668 }
3669}
3670
3671void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3672{
3673 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3674
3675 es2::Context *context = es2::getContext();
3676
3677 if(context)
3678 {
3679 if(index >= es2::MAX_VERTEX_ATTRIBS)
3680 {
3681 return error(GL_INVALID_VALUE);
3682 }
3683
3684 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3685
Nicolas Capens0bac2852016-05-07 06:09:58 -04003686 switch(pname)
3687 {
3688 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3689 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3690 break;
3691 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3692 *params = attribState.mSize;
3693 break;
3694 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3695 *params = attribState.mStride;
3696 break;
3697 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3698 *params = attribState.mType;
3699 break;
3700 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3701 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3702 break;
3703 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3704 *params = attribState.mBoundBuffer.name();
3705 break;
3706 case GL_CURRENT_VERTEX_ATTRIB:
3707 {
3708 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3709 for(int i = 0; i < 4; ++i)
3710 {
3711 float currentValue = attrib.getCurrentValueF(i);
3712 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3713 }
3714 }
3715 break;
3716 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003717 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3718 break;
3719 default:
3720 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003721 }
3722 }
3723}
3724
3725void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3726{
3727 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3728
3729 es2::Context *context = es2::getContext();
3730
3731 if(context)
3732 {
3733 if(index >= es2::MAX_VERTEX_ATTRIBS)
3734 {
3735 return error(GL_INVALID_VALUE);
3736 }
3737
3738 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3739 {
3740 return error(GL_INVALID_ENUM);
3741 }
3742
3743 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3744 }
3745}
3746
3747void Hint(GLenum target, GLenum mode)
3748{
3749 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3750
3751 switch(mode)
3752 {
3753 case GL_FASTEST:
3754 case GL_NICEST:
3755 case GL_DONT_CARE:
3756 break;
3757 default:
3758 return error(GL_INVALID_ENUM);
3759 }
3760
3761 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003762
3763 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003764 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003765 switch(target)
3766 {
3767 case GL_GENERATE_MIPMAP_HINT:
3768 context->setGenerateMipmapHint(mode);
3769 break;
3770 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3771 context->setFragmentShaderDerivativeHint(mode);
3772 break;
3773 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3774 context->setTextureFilteringHint(mode);
3775 break;
3776 default:
3777 return error(GL_INVALID_ENUM);
3778 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003779 }
3780}
3781
3782GLboolean IsBuffer(GLuint buffer)
3783{
3784 TRACE("(GLuint buffer = %d)", buffer);
3785
3786 es2::Context *context = es2::getContext();
3787
3788 if(context && buffer)
3789 {
3790 es2::Buffer *bufferObject = context->getBuffer(buffer);
3791
3792 if(bufferObject)
3793 {
3794 return GL_TRUE;
3795 }
3796 }
3797
3798 return GL_FALSE;
3799}
3800
3801GLboolean IsEnabled(GLenum cap)
3802{
3803 TRACE("(GLenum cap = 0x%X)", cap);
3804
3805 es2::Context *context = es2::getContext();
3806
3807 if(context)
3808 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003809 switch(cap)
3810 {
3811 case GL_CULL_FACE: return context->isCullFaceEnabled();
3812 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3813 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3814 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3815 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3816 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3817 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3818 case GL_BLEND: return context->isBlendEnabled();
3819 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003820 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3821 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003822 default:
3823 return error(GL_INVALID_ENUM, false);
3824 }
3825 }
3826
3827 return false;
3828}
3829
3830GLboolean IsFenceNV(GLuint fence)
3831{
3832 TRACE("(GLuint fence = %d)", fence);
3833
3834 es2::Context *context = es2::getContext();
3835
3836 if(context)
3837 {
3838 es2::Fence *fenceObject = context->getFence(fence);
3839
3840 if(!fenceObject)
3841 {
3842 return GL_FALSE;
3843 }
3844
3845 return fenceObject->isFence();
3846 }
3847
3848 return GL_FALSE;
3849}
3850
3851GLboolean IsFramebuffer(GLuint framebuffer)
3852{
3853 TRACE("(GLuint framebuffer = %d)", framebuffer);
3854
3855 es2::Context *context = es2::getContext();
3856
3857 if(context && framebuffer)
3858 {
3859 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3860
3861 if(framebufferObject)
3862 {
3863 return GL_TRUE;
3864 }
3865 }
3866
3867 return GL_FALSE;
3868}
3869
3870GLboolean IsProgram(GLuint program)
3871{
3872 TRACE("(GLuint program = %d)", program);
3873
3874 es2::Context *context = es2::getContext();
3875
3876 if(context && program)
3877 {
3878 es2::Program *programObject = context->getProgram(program);
3879
3880 if(programObject)
3881 {
3882 return GL_TRUE;
3883 }
3884 }
3885
3886 return GL_FALSE;
3887}
3888
3889GLboolean IsQueryEXT(GLuint name)
3890{
3891 TRACE("(GLuint name = %d)", name);
3892
3893 if(name == 0)
3894 {
3895 return GL_FALSE;
3896 }
3897
3898 es2::Context *context = es2::getContext();
3899
3900 if(context)
3901 {
3902 es2::Query *queryObject = context->getQuery(name);
3903
3904 if(queryObject)
3905 {
3906 return GL_TRUE;
3907 }
3908 }
3909
3910 return GL_FALSE;
3911}
3912
3913GLboolean IsRenderbuffer(GLuint renderbuffer)
3914{
3915 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3916
3917 es2::Context *context = es2::getContext();
3918
3919 if(context && renderbuffer)
3920 {
3921 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3922
3923 if(renderbufferObject)
3924 {
3925 return GL_TRUE;
3926 }
3927 }
3928
3929 return GL_FALSE;
3930}
3931
3932GLboolean IsShader(GLuint shader)
3933{
3934 TRACE("(GLuint shader = %d)", shader);
3935
3936 es2::Context *context = es2::getContext();
3937
3938 if(context && shader)
3939 {
3940 es2::Shader *shaderObject = context->getShader(shader);
3941
3942 if(shaderObject)
3943 {
3944 return GL_TRUE;
3945 }
3946 }
3947
3948 return GL_FALSE;
3949}
3950
3951GLboolean IsTexture(GLuint texture)
3952{
3953 TRACE("(GLuint texture = %d)", texture);
3954
3955 es2::Context *context = es2::getContext();
3956
3957 if(context && texture)
3958 {
3959 es2::Texture *textureObject = context->getTexture(texture);
3960
3961 if(textureObject)
3962 {
3963 return GL_TRUE;
3964 }
3965 }
3966
3967 return GL_FALSE;
3968}
3969
3970void LineWidth(GLfloat width)
3971{
3972 TRACE("(GLfloat width = %f)", width);
3973
3974 if(width <= 0.0f)
3975 {
3976 return error(GL_INVALID_VALUE);
3977 }
3978
3979 es2::Context *context = es2::getContext();
3980
3981 if(context)
3982 {
3983 context->setLineWidth(width);
3984 }
3985}
3986
3987void LinkProgram(GLuint program)
3988{
3989 TRACE("(GLuint program = %d)", program);
3990
3991 es2::Context *context = es2::getContext();
3992
3993 if(context)
3994 {
3995 es2::Program *programObject = context->getProgram(program);
3996
3997 if(!programObject)
3998 {
3999 if(context->getShader(program))
4000 {
4001 return error(GL_INVALID_OPERATION);
4002 }
4003 else
4004 {
4005 return error(GL_INVALID_VALUE);
4006 }
4007 }
4008
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004009 if(programObject == context->getCurrentProgram())
4010 {
4011 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4012 if(transformFeedback && transformFeedback->isActive())
4013 {
4014 return error(GL_INVALID_OPERATION);
4015 }
4016 }
4017
Nicolas Capens0bac2852016-05-07 06:09:58 -04004018 programObject->link();
4019 }
4020}
4021
4022void PixelStorei(GLenum pname, GLint param)
4023{
4024 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4025
4026 es2::Context *context = es2::getContext();
4027
4028 if(context)
4029 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004030 switch(pname)
4031 {
4032 case GL_UNPACK_ALIGNMENT:
4033 if(param != 1 && param != 2 && param != 4 && param != 8)
4034 {
4035 return error(GL_INVALID_VALUE);
4036 }
4037 context->setUnpackAlignment(param);
4038 break;
4039 case GL_PACK_ALIGNMENT:
4040 if(param != 1 && param != 2 && param != 4 && param != 8)
4041 {
4042 return error(GL_INVALID_VALUE);
4043 }
4044 context->setPackAlignment(param);
4045 break;
4046 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004047 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004048 {
Nicolas Capens83463112018-06-12 23:55:16 -04004049 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004050 }
Nicolas Capens83463112018-06-12 23:55:16 -04004051 context->setPackRowLength(param);
4052 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004053 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004054 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004055 {
Nicolas Capens83463112018-06-12 23:55:16 -04004056 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004057 }
Nicolas Capens83463112018-06-12 23:55:16 -04004058 context->setPackSkipPixels(param);
4059 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004060 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004061 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004062 {
Nicolas Capens83463112018-06-12 23:55:16 -04004063 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 }
Nicolas Capens83463112018-06-12 23:55:16 -04004065 context->setPackSkipRows(param);
4066 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004067 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004068 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004069 {
Nicolas Capens83463112018-06-12 23:55:16 -04004070 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 }
Nicolas Capens83463112018-06-12 23:55:16 -04004072 context->setUnpackRowLength(param);
4073 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004074 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004075 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004076 {
Nicolas Capens83463112018-06-12 23:55:16 -04004077 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 }
Nicolas Capens83463112018-06-12 23:55:16 -04004079 context->setUnpackImageHeight(param);
4080 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004082 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 {
Nicolas Capens83463112018-06-12 23:55:16 -04004084 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 }
Nicolas Capens83463112018-06-12 23:55:16 -04004086 context->setUnpackSkipPixels(param);
4087 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004089 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 {
Nicolas Capens83463112018-06-12 23:55:16 -04004091 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 }
Nicolas Capens83463112018-06-12 23:55:16 -04004093 context->setUnpackSkipRows(param);
4094 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004096 if(param < 0)
4097 {
4098 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004099 }
Nicolas Capens83463112018-06-12 23:55:16 -04004100 context->setUnpackSkipImages(param);
4101 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 default:
4103 return error(GL_INVALID_ENUM);
4104 }
4105 }
4106}
4107
4108void PolygonOffset(GLfloat factor, GLfloat units)
4109{
4110 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4111
4112 es2::Context *context = es2::getContext();
4113
4114 if(context)
4115 {
4116 context->setPolygonOffsetParams(factor, units);
4117 }
4118}
4119
4120void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4121 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4122{
4123 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4124 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4125 x, y, width, height, format, type, bufSize, data);
4126
4127 if(width < 0 || height < 0 || bufSize < 0)
4128 {
4129 return error(GL_INVALID_VALUE);
4130 }
4131
4132 es2::Context *context = es2::getContext();
4133
4134 if(context)
4135 {
4136 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4137 }
4138}
4139
4140void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4141{
4142 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4143 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4144 x, y, width, height, format, type, pixels);
4145
4146 if(width < 0 || height < 0)
4147 {
4148 return error(GL_INVALID_VALUE);
4149 }
4150
4151 es2::Context *context = es2::getContext();
4152
4153 if(context)
4154 {
4155 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4156 }
4157}
4158
4159void ReleaseShaderCompiler(void)
4160{
4161 TRACE("()");
4162
4163 es2::Shader::releaseCompiler();
4164}
4165
Nicolas Capens400667e2017-03-29 14:40:14 -04004166void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004167{
4168 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4169 target, samples, internalformat, width, height);
4170
4171 switch(target)
4172 {
4173 case GL_RENDERBUFFER:
4174 break;
4175 default:
4176 return error(GL_INVALID_ENUM);
4177 }
4178
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004179 if(width < 0 || height < 0 || samples < 0 ||
4180 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4181 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004182 {
4183 return error(GL_INVALID_VALUE);
4184 }
4185
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004186 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004187 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004188 {
4189 return error(GL_INVALID_OPERATION);
4190 }
4191
Nicolas Capens0bac2852016-05-07 06:09:58 -04004192 es2::Context *context = es2::getContext();
4193
4194 if(context)
4195 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004196 GLuint handle = context->getRenderbufferName();
4197 if(handle == 0)
4198 {
4199 return error(GL_INVALID_OPERATION);
4200 }
4201
Nicolas Capens83463112018-06-12 23:55:16 -04004202 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004203 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004204 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004205 }
Nicolas Capens83463112018-06-12 23:55:16 -04004206 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004207 {
4208 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4209 }
Nicolas Capens83463112018-06-12 23:55:16 -04004210 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004211 {
4212 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4213 }
Nicolas Capens83463112018-06-12 23:55:16 -04004214 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004215 {
4216 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4217 }
4218 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004219 }
4220}
4221
Nicolas Capens400667e2017-03-29 14:40:14 -04004222void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4223{
4224 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4225}
4226
Nicolas Capens0bac2852016-05-07 06:09:58 -04004227void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4228{
Nicolas Capens400667e2017-03-29 14:40:14 -04004229 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004230}
4231
4232void SampleCoverage(GLclampf value, GLboolean invert)
4233{
4234 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4235
4236 es2::Context* context = es2::getContext();
4237
4238 if(context)
4239 {
4240 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4241 }
4242}
4243
4244void SetFenceNV(GLuint fence, GLenum condition)
4245{
4246 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4247
4248 if(condition != GL_ALL_COMPLETED_NV)
4249 {
4250 return error(GL_INVALID_ENUM);
4251 }
4252
4253 es2::Context *context = es2::getContext();
4254
4255 if(context)
4256 {
4257 es2::Fence *fenceObject = context->getFence(fence);
4258
4259 if(!fenceObject)
4260 {
4261 return error(GL_INVALID_OPERATION);
4262 }
4263
4264 fenceObject->setFence(condition);
4265 }
4266}
4267
4268void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4269{
4270 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4271
4272 if(width < 0 || height < 0)
4273 {
4274 return error(GL_INVALID_VALUE);
4275 }
4276
4277 es2::Context* context = es2::getContext();
4278
4279 if(context)
4280 {
4281 context->setScissorParams(x, y, width, height);
4282 }
4283}
4284
4285void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4286{
4287 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4288 "const GLvoid* binary = %p, GLsizei length = %d)",
4289 n, shaders, binaryformat, binary, length);
4290
4291 // No binary shader formats are supported.
4292 return error(GL_INVALID_ENUM);
4293}
4294
4295void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4296{
4297 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4298 shader, count, string, length);
4299
4300 if(count < 0)
4301 {
4302 return error(GL_INVALID_VALUE);
4303 }
4304
4305 es2::Context *context = es2::getContext();
4306
4307 if(context)
4308 {
4309 es2::Shader *shaderObject = context->getShader(shader);
4310
4311 if(!shaderObject)
4312 {
4313 if(context->getProgram(shader))
4314 {
4315 return error(GL_INVALID_OPERATION);
4316 }
4317 else
4318 {
4319 return error(GL_INVALID_VALUE);
4320 }
4321 }
4322
4323 shaderObject->setSource(count, string, length);
4324 }
4325}
4326
4327void StencilFunc(GLenum func, GLint ref, GLuint mask)
4328{
4329 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4330}
4331
4332void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4333{
4334 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4335
4336 switch(face)
4337 {
4338 case GL_FRONT:
4339 case GL_BACK:
4340 case GL_FRONT_AND_BACK:
4341 break;
4342 default:
4343 return error(GL_INVALID_ENUM);
4344 }
4345
4346 switch(func)
4347 {
4348 case GL_NEVER:
4349 case GL_ALWAYS:
4350 case GL_LESS:
4351 case GL_LEQUAL:
4352 case GL_EQUAL:
4353 case GL_GEQUAL:
4354 case GL_GREATER:
4355 case GL_NOTEQUAL:
4356 break;
4357 default:
4358 return error(GL_INVALID_ENUM);
4359 }
4360
4361 es2::Context *context = es2::getContext();
4362
4363 if(context)
4364 {
4365 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4366 {
4367 context->setStencilParams(func, ref, mask);
4368 }
4369
4370 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4371 {
4372 context->setStencilBackParams(func, ref, mask);
4373 }
4374 }
4375}
4376
4377void StencilMask(GLuint mask)
4378{
4379 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4380}
4381
4382void StencilMaskSeparate(GLenum face, GLuint mask)
4383{
4384 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4385
4386 switch(face)
4387 {
4388 case GL_FRONT:
4389 case GL_BACK:
4390 case GL_FRONT_AND_BACK:
4391 break;
4392 default:
4393 return error(GL_INVALID_ENUM);
4394 }
4395
4396 es2::Context *context = es2::getContext();
4397
4398 if(context)
4399 {
4400 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4401 {
4402 context->setStencilWritemask(mask);
4403 }
4404
4405 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4406 {
4407 context->setStencilBackWritemask(mask);
4408 }
4409 }
4410}
4411
4412void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4413{
4414 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4415}
4416
4417void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4418{
4419 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4420 face, fail, zfail, zpass);
4421
4422 switch(face)
4423 {
4424 case GL_FRONT:
4425 case GL_BACK:
4426 case GL_FRONT_AND_BACK:
4427 break;
4428 default:
4429 return error(GL_INVALID_ENUM);
4430 }
4431
4432 switch(fail)
4433 {
4434 case GL_ZERO:
4435 case GL_KEEP:
4436 case GL_REPLACE:
4437 case GL_INCR:
4438 case GL_DECR:
4439 case GL_INVERT:
4440 case GL_INCR_WRAP:
4441 case GL_DECR_WRAP:
4442 break;
4443 default:
4444 return error(GL_INVALID_ENUM);
4445 }
4446
4447 switch(zfail)
4448 {
4449 case GL_ZERO:
4450 case GL_KEEP:
4451 case GL_REPLACE:
4452 case GL_INCR:
4453 case GL_DECR:
4454 case GL_INVERT:
4455 case GL_INCR_WRAP:
4456 case GL_DECR_WRAP:
4457 break;
4458 default:
4459 return error(GL_INVALID_ENUM);
4460 }
4461
4462 switch(zpass)
4463 {
4464 case GL_ZERO:
4465 case GL_KEEP:
4466 case GL_REPLACE:
4467 case GL_INCR:
4468 case GL_DECR:
4469 case GL_INVERT:
4470 case GL_INCR_WRAP:
4471 case GL_DECR_WRAP:
4472 break;
4473 default:
4474 return error(GL_INVALID_ENUM);
4475 }
4476
4477 es2::Context *context = es2::getContext();
4478
4479 if(context)
4480 {
4481 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4482 {
4483 context->setStencilOperations(fail, zfail, zpass);
4484 }
4485
4486 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4487 {
4488 context->setStencilBackOperations(fail, zfail, zpass);
4489 }
4490 }
4491}
4492
4493GLboolean TestFenceNV(GLuint fence)
4494{
4495 TRACE("(GLuint fence = %d)", fence);
4496
4497 es2::Context *context = es2::getContext();
4498
4499 if(context)
4500 {
4501 es2::Fence *fenceObject = context->getFence(fence);
4502
4503 if(!fenceObject)
4504 {
4505 return error(GL_INVALID_OPERATION, GL_TRUE);
4506 }
4507
4508 return fenceObject->testFence();
4509 }
4510
4511 return GL_TRUE;
4512}
4513
4514void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004515 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004516{
4517 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004518 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4519 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004520
4521 if(!validImageSize(level, width, height))
4522 {
4523 return error(GL_INVALID_VALUE);
4524 }
4525
4526 es2::Context *context = es2::getContext();
4527
4528 if(context)
4529 {
Nicolas Capens83463112018-06-12 23:55:16 -04004530 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004531 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4532 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4533 {
4534 internalformat = GL_BGRA_EXT;
4535 }
4536
Nicolas Capens83463112018-06-12 23:55:16 -04004537 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004538 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004539 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004540 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004541 }
4542
4543 if(border != 0)
4544 {
4545 return error(GL_INVALID_VALUE);
4546 }
4547
4548 switch(target)
4549 {
Alexis Hetu46768622018-01-16 22:09:28 -05004550 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004551 if(level != 0)
4552 {
4553 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4554 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004555 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004556 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004557 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4558 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4559 {
4560 return error(GL_INVALID_VALUE);
4561 }
4562 break;
4563 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4564 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4566 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4567 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4569 if(width != height)
4570 {
4571 return error(GL_INVALID_VALUE);
4572 }
4573
4574 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4575 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4576 {
4577 return error(GL_INVALID_VALUE);
4578 }
4579 break;
4580 default:
4581 return error(GL_INVALID_ENUM);
4582 }
4583
Nicolas Capens5555af42017-12-14 13:14:03 -05004584 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004585 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004586 {
4587 return error(validationError);
4588 }
4589
Nicolas Capens894858a2018-03-22 00:55:23 -04004590 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4591
Alexis Hetu46768622018-01-16 22:09:28 -05004592 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004593 {
Alexis Hetu46768622018-01-16 22:09:28 -05004594 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004595
4596 if(!texture)
4597 {
4598 return error(GL_INVALID_OPERATION);
4599 }
4600
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004601 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004602 }
4603 else
4604 {
4605 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4606
4607 if(!texture)
4608 {
4609 return error(GL_INVALID_OPERATION);
4610 }
4611
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004612 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004613 }
4614 }
4615}
4616
4617void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4618{
4619 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4620
4621 es2::Context *context = es2::getContext();
4622
4623 if(context)
4624 {
4625 es2::Texture *texture;
4626
Nicolas Capens0bac2852016-05-07 06:09:58 -04004627 switch(target)
4628 {
Nicolas Capens83463112018-06-12 23:55:16 -04004629 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4630 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4631 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4632 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4633 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4634 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004635 default:
4636 return error(GL_INVALID_ENUM);
4637 }
4638
4639 switch(pname)
4640 {
4641 case GL_TEXTURE_WRAP_S:
4642 if(!texture->setWrapS((GLenum)param))
4643 {
4644 return error(GL_INVALID_ENUM);
4645 }
4646 break;
4647 case GL_TEXTURE_WRAP_T:
4648 if(!texture->setWrapT((GLenum)param))
4649 {
4650 return error(GL_INVALID_ENUM);
4651 }
4652 break;
4653 case GL_TEXTURE_WRAP_R_OES:
4654 if(!texture->setWrapR((GLenum)param))
4655 {
4656 return error(GL_INVALID_ENUM);
4657 }
4658 break;
4659 case GL_TEXTURE_MIN_FILTER:
4660 if(!texture->setMinFilter((GLenum)param))
4661 {
4662 return error(GL_INVALID_ENUM);
4663 }
4664 break;
4665 case GL_TEXTURE_MAG_FILTER:
4666 if(!texture->setMagFilter((GLenum)param))
4667 {
4668 return error(GL_INVALID_ENUM);
4669 }
4670 break;
4671 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4672 if(!texture->setMaxAnisotropy(param))
4673 {
4674 return error(GL_INVALID_VALUE);
4675 }
4676 break;
4677 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004678 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004679 {
4680 return error(GL_INVALID_VALUE);
4681 }
4682 break;
4683 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004684 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004685 {
4686 return error(GL_INVALID_VALUE);
4687 }
4688 break;
4689 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004690 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004691 {
4692 return error(GL_INVALID_VALUE);
4693 }
4694 break;
4695 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004696 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004697 {
4698 return error(GL_INVALID_VALUE);
4699 }
4700 break;
4701 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004702 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004703 {
4704 return error(GL_INVALID_VALUE);
4705 }
4706 break;
4707 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004708 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004709 {
4710 return error(GL_INVALID_VALUE);
4711 }
4712 break;
4713 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004714 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004715 {
4716 return error(GL_INVALID_VALUE);
4717 }
4718 break;
4719 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004720 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004721 {
4722 return error(GL_INVALID_VALUE);
4723 }
4724 break;
4725 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004726 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004727 {
4728 return error(GL_INVALID_VALUE);
4729 }
4730 break;
4731 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004732 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004733 {
4734 return error(GL_INVALID_VALUE);
4735 }
4736 break;
4737 default:
4738 return error(GL_INVALID_ENUM);
4739 }
4740 }
4741}
4742
4743void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4744{
4745 glTexParameterf(target, pname, *params);
4746}
4747
4748void TexParameteri(GLenum target, GLenum pname, GLint param)
4749{
4750 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4751
4752 es2::Context *context = es2::getContext();
4753
4754 if(context)
4755 {
4756 es2::Texture *texture;
4757
Nicolas Capens0bac2852016-05-07 06:09:58 -04004758 switch(target)
4759 {
Nicolas Capens83463112018-06-12 23:55:16 -04004760 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4761 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4762 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4763 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4764 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4765 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004766 default:
4767 return error(GL_INVALID_ENUM);
4768 }
4769
4770 switch(pname)
4771 {
4772 case GL_TEXTURE_WRAP_S:
4773 if(!texture->setWrapS((GLenum)param))
4774 {
4775 return error(GL_INVALID_ENUM);
4776 }
4777 break;
4778 case GL_TEXTURE_WRAP_T:
4779 if(!texture->setWrapT((GLenum)param))
4780 {
4781 return error(GL_INVALID_ENUM);
4782 }
4783 break;
4784 case GL_TEXTURE_WRAP_R_OES:
4785 if(!texture->setWrapR((GLenum)param))
4786 {
4787 return error(GL_INVALID_ENUM);
4788 }
4789 break;
4790 case GL_TEXTURE_MIN_FILTER:
4791 if(!texture->setMinFilter((GLenum)param))
4792 {
4793 return error(GL_INVALID_ENUM);
4794 }
4795 break;
4796 case GL_TEXTURE_MAG_FILTER:
4797 if(!texture->setMagFilter((GLenum)param))
4798 {
4799 return error(GL_INVALID_ENUM);
4800 }
4801 break;
4802 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4803 if(!texture->setMaxAnisotropy((GLfloat)param))
4804 {
4805 return error(GL_INVALID_VALUE);
4806 }
4807 break;
4808 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004809 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4810 {
4811 return error(GL_INVALID_OPERATION); // Base level has to be 0
4812 }
Nicolas Capens83463112018-06-12 23:55:16 -04004813 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004814 {
4815 return error(GL_INVALID_VALUE);
4816 }
4817 break;
4818 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004819 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004820 {
4821 return error(GL_INVALID_VALUE);
4822 }
4823 break;
4824 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004825 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004826 {
4827 return error(GL_INVALID_VALUE);
4828 }
4829 break;
4830 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004831 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004832 {
4833 return error(GL_INVALID_VALUE);
4834 }
4835 break;
4836 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004837 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004838 {
4839 return error(GL_INVALID_VALUE);
4840 }
4841 break;
4842 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004843 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004844 {
4845 return error(GL_INVALID_VALUE);
4846 }
4847 break;
4848 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004849 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004850 {
4851 return error(GL_INVALID_VALUE);
4852 }
4853 break;
4854 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004855 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004856 {
4857 return error(GL_INVALID_VALUE);
4858 }
4859 break;
4860 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004861 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004862 {
4863 return error(GL_INVALID_VALUE);
4864 }
4865 break;
4866 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004867 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004868 {
4869 return error(GL_INVALID_VALUE);
4870 }
4871 break;
4872 default:
4873 return error(GL_INVALID_ENUM);
4874 }
4875 }
4876}
4877
4878void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4879{
4880 glTexParameteri(target, pname, *params);
4881}
4882
4883void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004884 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004885{
4886 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4887 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004888 "const GLvoid* data = %p)",
4889 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004890
4891 if(!es2::IsTextureTarget(target))
4892 {
4893 return error(GL_INVALID_ENUM);
4894 }
4895
4896 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4897 {
4898 return error(GL_INVALID_VALUE);
4899 }
4900
4901 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4902 {
4903 return error(GL_INVALID_VALUE);
4904 }
4905
4906 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4907 {
4908 return error(GL_INVALID_VALUE);
4909 }
4910
Nicolas Capens0bac2852016-05-07 06:09:58 -04004911 es2::Context *context = es2::getContext();
4912
4913 if(context)
4914 {
Alexis Hetu46768622018-01-16 22:09:28 -05004915 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004916 {
Alexis Hetu46768622018-01-16 22:09:28 -05004917 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004918
Nicolas Capens83463112018-06-12 23:55:16 -04004919 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004920 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004921 {
4922 return error(validationError);
4923 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004924
Nicolas Capens5555af42017-12-14 13:14:03 -05004925 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004926 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004927 {
4928 return error(validationError);
4929 }
4930
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004931 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004932 }
4933 else if(es2::IsCubemapTextureTarget(target))
4934 {
4935 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4936
Nicolas Capens83463112018-06-12 23:55:16 -04004937 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004938 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004939 {
4940 return error(validationError);
4941 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004942
Nicolas Capens5555af42017-12-14 13:14:03 -05004943 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004944 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004945 {
4946 return error(validationError);
4947 }
4948
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004949 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004950 }
4951 else UNREACHABLE(target);
4952 }
4953}
4954
4955void Uniform1f(GLint location, GLfloat x)
4956{
4957 glUniform1fv(location, 1, &x);
4958}
4959
4960void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4961{
4962 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4963
4964 if(count < 0)
4965 {
4966 return error(GL_INVALID_VALUE);
4967 }
4968
Nicolas Capens0bac2852016-05-07 06:09:58 -04004969 es2::Context *context = es2::getContext();
4970
4971 if(context)
4972 {
4973 es2::Program *program = context->getCurrentProgram();
4974
4975 if(!program)
4976 {
4977 return error(GL_INVALID_OPERATION);
4978 }
4979
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004980 if(location == -1)
4981 {
4982 return;
4983 }
4984
Nicolas Capens0bac2852016-05-07 06:09:58 -04004985 if(!program->setUniform1fv(location, count, v))
4986 {
4987 return error(GL_INVALID_OPERATION);
4988 }
4989 }
4990}
4991
4992void Uniform1i(GLint location, GLint x)
4993{
4994 glUniform1iv(location, 1, &x);
4995}
4996
4997void Uniform1iv(GLint location, GLsizei count, const GLint* v)
4998{
4999 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5000
5001 if(count < 0)
5002 {
5003 return error(GL_INVALID_VALUE);
5004 }
5005
Nicolas Capens0bac2852016-05-07 06:09:58 -04005006 es2::Context *context = es2::getContext();
5007
5008 if(context)
5009 {
5010 es2::Program *program = context->getCurrentProgram();
5011
5012 if(!program)
5013 {
5014 return error(GL_INVALID_OPERATION);
5015 }
5016
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005017 if(location == -1)
5018 {
5019 return;
5020 }
5021
Nicolas Capens0bac2852016-05-07 06:09:58 -04005022 if(!program->setUniform1iv(location, count, v))
5023 {
5024 return error(GL_INVALID_OPERATION);
5025 }
5026 }
5027}
5028
5029void Uniform2f(GLint location, GLfloat x, GLfloat y)
5030{
5031 GLfloat xy[2] = {x, y};
5032
5033 glUniform2fv(location, 1, (GLfloat*)&xy);
5034}
5035
5036void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5037{
5038 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5039
5040 if(count < 0)
5041 {
5042 return error(GL_INVALID_VALUE);
5043 }
5044
Nicolas Capens0bac2852016-05-07 06:09:58 -04005045 es2::Context *context = es2::getContext();
5046
5047 if(context)
5048 {
5049 es2::Program *program = context->getCurrentProgram();
5050
5051 if(!program)
5052 {
5053 return error(GL_INVALID_OPERATION);
5054 }
5055
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005056 if(location == -1)
5057 {
5058 return;
5059 }
5060
Nicolas Capens0bac2852016-05-07 06:09:58 -04005061 if(!program->setUniform2fv(location, count, v))
5062 {
5063 return error(GL_INVALID_OPERATION);
5064 }
5065 }
5066}
5067
5068void Uniform2i(GLint location, GLint x, GLint y)
5069{
5070 GLint xy[4] = {x, y};
5071
5072 glUniform2iv(location, 1, (GLint*)&xy);
5073}
5074
5075void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5076{
5077 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5078
5079 if(count < 0)
5080 {
5081 return error(GL_INVALID_VALUE);
5082 }
5083
Nicolas Capens0bac2852016-05-07 06:09:58 -04005084 es2::Context *context = es2::getContext();
5085
5086 if(context)
5087 {
5088 es2::Program *program = context->getCurrentProgram();
5089
5090 if(!program)
5091 {
5092 return error(GL_INVALID_OPERATION);
5093 }
5094
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005095 if(location == -1)
5096 {
5097 return;
5098 }
5099
Nicolas Capens0bac2852016-05-07 06:09:58 -04005100 if(!program->setUniform2iv(location, count, v))
5101 {
5102 return error(GL_INVALID_OPERATION);
5103 }
5104 }
5105}
5106
5107void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5108{
5109 GLfloat xyz[3] = {x, y, z};
5110
5111 glUniform3fv(location, 1, (GLfloat*)&xyz);
5112}
5113
5114void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5115{
5116 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5117
5118 if(count < 0)
5119 {
5120 return error(GL_INVALID_VALUE);
5121 }
5122
Nicolas Capens0bac2852016-05-07 06:09:58 -04005123 es2::Context *context = es2::getContext();
5124
5125 if(context)
5126 {
5127 es2::Program *program = context->getCurrentProgram();
5128
5129 if(!program)
5130 {
5131 return error(GL_INVALID_OPERATION);
5132 }
5133
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005134 if(location == -1)
5135 {
5136 return;
5137 }
5138
Nicolas Capens0bac2852016-05-07 06:09:58 -04005139 if(!program->setUniform3fv(location, count, v))
5140 {
5141 return error(GL_INVALID_OPERATION);
5142 }
5143 }
5144}
5145
5146void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5147{
5148 GLint xyz[3] = {x, y, z};
5149
5150 glUniform3iv(location, 1, (GLint*)&xyz);
5151}
5152
5153void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5154{
5155 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5156
5157 if(count < 0)
5158 {
5159 return error(GL_INVALID_VALUE);
5160 }
5161
Nicolas Capens0bac2852016-05-07 06:09:58 -04005162 es2::Context *context = es2::getContext();
5163
5164 if(context)
5165 {
5166 es2::Program *program = context->getCurrentProgram();
5167
5168 if(!program)
5169 {
5170 return error(GL_INVALID_OPERATION);
5171 }
5172
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005173 if(location == -1)
5174 {
5175 return;
5176 }
5177
Nicolas Capens0bac2852016-05-07 06:09:58 -04005178 if(!program->setUniform3iv(location, count, v))
5179 {
5180 return error(GL_INVALID_OPERATION);
5181 }
5182 }
5183}
5184
5185void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5186{
5187 GLfloat xyzw[4] = {x, y, z, w};
5188
5189 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5190}
5191
5192void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5193{
5194 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5195
5196 if(count < 0)
5197 {
5198 return error(GL_INVALID_VALUE);
5199 }
5200
Nicolas Capens0bac2852016-05-07 06:09:58 -04005201 es2::Context *context = es2::getContext();
5202
5203 if(context)
5204 {
5205 es2::Program *program = context->getCurrentProgram();
5206
5207 if(!program)
5208 {
5209 return error(GL_INVALID_OPERATION);
5210 }
5211
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005212 if(location == -1)
5213 {
5214 return;
5215 }
5216
Nicolas Capens0bac2852016-05-07 06:09:58 -04005217 if(!program->setUniform4fv(location, count, v))
5218 {
5219 return error(GL_INVALID_OPERATION);
5220 }
5221 }
5222}
5223
5224void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5225{
5226 GLint xyzw[4] = {x, y, z, w};
5227
5228 glUniform4iv(location, 1, (GLint*)&xyzw);
5229}
5230
5231void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5232{
5233 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5234
5235 if(count < 0)
5236 {
5237 return error(GL_INVALID_VALUE);
5238 }
5239
Nicolas Capens0bac2852016-05-07 06:09:58 -04005240 es2::Context *context = es2::getContext();
5241
5242 if(context)
5243 {
5244 es2::Program *program = context->getCurrentProgram();
5245
5246 if(!program)
5247 {
5248 return error(GL_INVALID_OPERATION);
5249 }
5250
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005251 if(location == -1)
5252 {
5253 return;
5254 }
5255
Nicolas Capens0bac2852016-05-07 06:09:58 -04005256 if(!program->setUniform4iv(location, count, v))
5257 {
5258 return error(GL_INVALID_OPERATION);
5259 }
5260 }
5261}
5262
5263void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5264{
5265 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5266 location, count, transpose, value);
5267
5268 if(count < 0)
5269 {
5270 return error(GL_INVALID_VALUE);
5271 }
5272
Nicolas Capens0bac2852016-05-07 06:09:58 -04005273 es2::Context *context = es2::getContext();
5274
5275 if(context)
5276 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005277 es2::Program *program = context->getCurrentProgram();
5278
5279 if(!program)
5280 {
5281 return error(GL_INVALID_OPERATION);
5282 }
5283
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005284 if(location == -1)
5285 {
5286 return;
5287 }
5288
Nicolas Capens0bac2852016-05-07 06:09:58 -04005289 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5290 {
5291 return error(GL_INVALID_OPERATION);
5292 }
5293 }
5294}
5295
5296void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5297{
5298 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5299 location, count, transpose, value);
5300
5301 if(count < 0)
5302 {
5303 return error(GL_INVALID_VALUE);
5304 }
5305
Nicolas Capens0bac2852016-05-07 06:09:58 -04005306 es2::Context *context = es2::getContext();
5307
5308 if(context)
5309 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005310 es2::Program *program = context->getCurrentProgram();
5311
5312 if(!program)
5313 {
5314 return error(GL_INVALID_OPERATION);
5315 }
5316
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005317 if(location == -1)
5318 {
5319 return;
5320 }
5321
Nicolas Capens0bac2852016-05-07 06:09:58 -04005322 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5323 {
5324 return error(GL_INVALID_OPERATION);
5325 }
5326 }
5327}
5328
5329void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5330{
5331 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5332 location, count, transpose, value);
5333
5334 if(count < 0)
5335 {
5336 return error(GL_INVALID_VALUE);
5337 }
5338
Nicolas Capens0bac2852016-05-07 06:09:58 -04005339 es2::Context *context = es2::getContext();
5340
5341 if(context)
5342 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005343 es2::Program *program = context->getCurrentProgram();
5344
5345 if(!program)
5346 {
5347 return error(GL_INVALID_OPERATION);
5348 }
5349
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005350 if(location == -1)
5351 {
5352 return;
5353 }
5354
Nicolas Capens0bac2852016-05-07 06:09:58 -04005355 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5356 {
5357 return error(GL_INVALID_OPERATION);
5358 }
5359 }
5360}
5361
5362void UseProgram(GLuint program)
5363{
5364 TRACE("(GLuint program = %d)", program);
5365
5366 es2::Context *context = es2::getContext();
5367
5368 if(context)
5369 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005370 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5371 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5372 {
5373 return error(GL_INVALID_OPERATION);
5374 }
5375
Nicolas Capens0bac2852016-05-07 06:09:58 -04005376 es2::Program *programObject = context->getProgram(program);
5377
5378 if(!programObject && program != 0)
5379 {
5380 if(context->getShader(program))
5381 {
5382 return error(GL_INVALID_OPERATION);
5383 }
5384 else
5385 {
5386 return error(GL_INVALID_VALUE);
5387 }
5388 }
5389
5390 if(program != 0 && !programObject->isLinked())
5391 {
5392 return error(GL_INVALID_OPERATION);
5393 }
5394
5395 context->useProgram(program);
5396 }
5397}
5398
5399void ValidateProgram(GLuint program)
5400{
5401 TRACE("(GLuint program = %d)", program);
5402
5403 es2::Context *context = es2::getContext();
5404
5405 if(context)
5406 {
5407 es2::Program *programObject = context->getProgram(program);
5408
5409 if(!programObject)
5410 {
5411 if(context->getShader(program))
5412 {
5413 return error(GL_INVALID_OPERATION);
5414 }
5415 else
5416 {
5417 return error(GL_INVALID_VALUE);
5418 }
5419 }
5420
Ben Vanik1fd3b282017-07-10 14:08:12 -07005421 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005422 }
5423}
5424
5425void VertexAttrib1f(GLuint index, GLfloat x)
5426{
5427 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5428
5429 if(index >= es2::MAX_VERTEX_ATTRIBS)
5430 {
5431 return error(GL_INVALID_VALUE);
5432 }
5433
5434 es2::Context *context = es2::getContext();
5435
5436 if(context)
5437 {
5438 GLfloat vals[4] = { x, 0, 0, 1 };
5439 context->setVertexAttrib(index, vals);
5440 }
5441}
5442
5443void VertexAttrib1fv(GLuint index, const GLfloat* values)
5444{
5445 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5446
5447 if(index >= es2::MAX_VERTEX_ATTRIBS)
5448 {
5449 return error(GL_INVALID_VALUE);
5450 }
5451
5452 es2::Context *context = es2::getContext();
5453
5454 if(context)
5455 {
5456 GLfloat vals[4] = { values[0], 0, 0, 1 };
5457 context->setVertexAttrib(index, vals);
5458 }
5459}
5460
5461void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5462{
5463 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5464
5465 if(index >= es2::MAX_VERTEX_ATTRIBS)
5466 {
5467 return error(GL_INVALID_VALUE);
5468 }
5469
5470 es2::Context *context = es2::getContext();
5471
5472 if(context)
5473 {
5474 GLfloat vals[4] = { x, y, 0, 1 };
5475 context->setVertexAttrib(index, vals);
5476 }
5477}
5478
5479void VertexAttrib2fv(GLuint index, const GLfloat* values)
5480{
5481 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5482
5483 if(index >= es2::MAX_VERTEX_ATTRIBS)
5484 {
5485 return error(GL_INVALID_VALUE);
5486 }
5487
5488 es2::Context *context = es2::getContext();
5489
5490 if(context)
5491 {
5492 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5493 context->setVertexAttrib(index, vals);
5494 }
5495}
5496
5497void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5498{
5499 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5500
5501 if(index >= es2::MAX_VERTEX_ATTRIBS)
5502 {
5503 return error(GL_INVALID_VALUE);
5504 }
5505
5506 es2::Context *context = es2::getContext();
5507
5508 if(context)
5509 {
5510 GLfloat vals[4] = { x, y, z, 1 };
5511 context->setVertexAttrib(index, vals);
5512 }
5513}
5514
5515void VertexAttrib3fv(GLuint index, const GLfloat* values)
5516{
5517 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5518
5519 if(index >= es2::MAX_VERTEX_ATTRIBS)
5520 {
5521 return error(GL_INVALID_VALUE);
5522 }
5523
5524 es2::Context *context = es2::getContext();
5525
5526 if(context)
5527 {
5528 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5529 context->setVertexAttrib(index, vals);
5530 }
5531}
5532
5533void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5534{
5535 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5536
5537 if(index >= es2::MAX_VERTEX_ATTRIBS)
5538 {
5539 return error(GL_INVALID_VALUE);
5540 }
5541
5542 es2::Context *context = es2::getContext();
5543
5544 if(context)
5545 {
5546 GLfloat vals[4] = { x, y, z, w };
5547 context->setVertexAttrib(index, vals);
5548 }
5549}
5550
5551void VertexAttrib4fv(GLuint index, const GLfloat* values)
5552{
5553 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5554
5555 if(index >= es2::MAX_VERTEX_ATTRIBS)
5556 {
5557 return error(GL_INVALID_VALUE);
5558 }
5559
5560 es2::Context *context = es2::getContext();
5561
5562 if(context)
5563 {
5564 context->setVertexAttrib(index, values);
5565 }
5566}
5567
5568void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5569{
5570 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5571 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5572 index, size, type, normalized, stride, ptr);
5573
5574 if(index >= es2::MAX_VERTEX_ATTRIBS)
5575 {
5576 return error(GL_INVALID_VALUE);
5577 }
5578
5579 if(size < 1 || size > 4)
5580 {
5581 return error(GL_INVALID_VALUE);
5582 }
5583
Nicolas Capens0bac2852016-05-07 06:09:58 -04005584 switch(type)
5585 {
5586 case GL_BYTE:
5587 case GL_UNSIGNED_BYTE:
5588 case GL_SHORT:
5589 case GL_UNSIGNED_SHORT:
5590 case GL_FIXED:
5591 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005592 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005593 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005594 break;
5595 case GL_INT_2_10_10_10_REV:
5596 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005597 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005598 {
Nicolas Capens83463112018-06-12 23:55:16 -04005599 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005600 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005601 case GL_INT:
5602 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005603 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005604 default:
5605 return error(GL_INVALID_ENUM);
5606 }
5607
5608 if(stride < 0)
5609 {
5610 return error(GL_INVALID_VALUE);
5611 }
5612
5613 es2::Context *context = es2::getContext();
5614
5615 if(context)
5616 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005617 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5618 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5619 {
5620 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5621 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5622 return error(GL_INVALID_OPERATION);
5623 }
5624
Alexis Hetu6f284032017-12-11 15:19:36 -05005625 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005626 }
5627}
5628
5629void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5630{
5631 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5632
5633 if(width < 0 || height < 0)
5634 {
5635 return error(GL_INVALID_VALUE);
5636 }
5637
5638 es2::Context *context = es2::getContext();
5639
5640 if(context)
5641 {
5642 context->setViewportParams(x, y, width, height);
5643 }
5644}
5645
Alexis Hetub9dda642016-10-06 11:25:32 -04005646static 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 -04005647{
5648 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5649 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5650 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5651 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5652
5653 switch(filter)
5654 {
5655 case GL_NEAREST:
5656 break;
5657 default:
5658 return error(GL_INVALID_ENUM);
5659 }
5660
5661 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5662 {
5663 return error(GL_INVALID_VALUE);
5664 }
5665
5666 es2::Context *context = es2::getContext();
5667
5668 if(context)
5669 {
5670 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5671 {
5672 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5673 return error(GL_INVALID_OPERATION);
5674 }
5675
Alexis Hetub9dda642016-10-06 11:25:32 -04005676 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005677 }
5678}
5679
Alexis Hetub9dda642016-10-06 11:25:32 -04005680void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5681{
5682 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5683}
5684
Nicolas Capens0bac2852016-05-07 06:09:58 -04005685void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5686 GLbitfield mask, GLenum filter)
5687{
5688 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5689 {
5690 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5691 return error(GL_INVALID_OPERATION);
5692 }
5693
Alexis Hetub9dda642016-10-06 11:25:32 -04005694 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005695}
5696
5697void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005698 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005699{
5700 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5701 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005702 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5703 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005704
5705 switch(target)
5706 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005707 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005708 switch(format)
5709 {
5710 case GL_DEPTH_COMPONENT:
5711 case GL_DEPTH_STENCIL_OES:
5712 return error(GL_INVALID_OPERATION);
5713 default:
5714 break;
5715 }
5716 break;
5717 default:
5718 return error(GL_INVALID_ENUM);
5719 }
5720
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005721 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005722 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005723 return error(GL_INVALID_OPERATION);
5724 }
5725
Nicolas Capens83463112018-06-12 23:55:16 -04005726 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005727 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005728 {
5729 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005730 }
5731
5732 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5733 {
5734 return error(GL_INVALID_VALUE);
5735 }
5736
Nicolas Capensefdf1032018-05-08 16:03:16 -04005737 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005738 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5739 {
5740 return error(GL_INVALID_VALUE);
5741 }
5742
5743 if(border != 0)
5744 {
5745 return error(GL_INVALID_VALUE);
5746 }
5747
5748 es2::Context *context = es2::getContext();
5749
5750 if(context)
5751 {
5752 es2::Texture3D *texture = context->getTexture3D();
5753
5754 if(!texture)
5755 {
5756 return error(GL_INVALID_OPERATION);
5757 }
5758
Nicolas Capens2fc90512018-01-23 22:24:22 +00005759 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005760 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005761 {
5762 return error(validationError);
5763 }
5764
Nicolas Capens894858a2018-03-22 00:55:23 -04005765 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005766 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005767 }
5768}
5769
Alexis Hetu53f48092016-06-17 14:08:06 -04005770void 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 -04005771{
5772 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5773 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005774 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5775 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005776
5777 switch(target)
5778 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005779 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005780 break;
5781 default:
5782 return error(GL_INVALID_ENUM);
5783 }
5784
Nicolas Capens0bac2852016-05-07 06:09:58 -04005785 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5786 {
5787 return error(GL_INVALID_VALUE);
5788 }
5789
5790 if((width < 0) || (height < 0) || (depth < 0))
5791 {
5792 return error(GL_INVALID_VALUE);
5793 }
5794
5795 es2::Context *context = es2::getContext();
5796
5797 if(context)
5798 {
5799 es2::Texture3D *texture = context->getTexture3D();
5800
Nicolas Capens83463112018-06-12 23:55:16 -04005801 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005802 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005803 {
5804 return error(validationError);
5805 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005806
Nicolas Capens5555af42017-12-14 13:14:03 -05005807 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005808 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005809 {
5810 return error(validationError);
5811 }
5812
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005813 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005814 }
5815}
5816
5817void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5818{
5819 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5820 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5821 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5822
5823 switch(target)
5824 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005825 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005826 break;
5827 default:
5828 return error(GL_INVALID_ENUM);
5829 }
5830
5831 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5832 {
5833 return error(GL_INVALID_VALUE);
5834 }
5835
5836 es2::Context *context = es2::getContext();
5837
5838 if(context)
5839 {
5840 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5841
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005842 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005843 {
5844 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5845 }
5846
5847 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5848
5849 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5850 {
5851 return error(GL_INVALID_OPERATION);
5852 }
5853
5854 es2::Texture3D *texture = context->getTexture3D();
5855
Nicolas Capens83463112018-06-12 23:55:16 -04005856 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005857 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005858 {
5859 return error(validationError);
5860 }
5861
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005862 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005863 }
5864}
5865
5866void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5867{
5868 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5869 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5870 target, level, internalformat, width, height, depth, border, imageSize, data);
5871
5872 switch(target)
5873 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005874 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005875 break;
5876 default:
5877 return error(GL_INVALID_ENUM);
5878 }
5879
5880 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5881 {
5882 return error(GL_INVALID_VALUE);
5883 }
5884
Nicolas Capensefdf1032018-05-08 16:03:16 -04005885 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005886 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5887 {
5888 return error(GL_INVALID_VALUE);
5889 }
5890
Nicolas Capens83463112018-06-12 23:55:16 -04005891 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005892 {
Nicolas Capens03589982018-02-01 17:28:32 -05005893 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005894 }
5895
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005896 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005897 {
5898 return error(GL_INVALID_VALUE);
5899 }
5900
5901 es2::Context *context = es2::getContext();
5902
5903 if(context)
5904 {
5905 es2::Texture3D *texture = context->getTexture3D();
5906
5907 if(!texture)
5908 {
5909 return error(GL_INVALID_OPERATION);
5910 }
5911
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005912 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005913
Nicolas Capense65f5642018-02-26 17:47:06 -05005914 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005915 {
5916 return error(validationError);
5917 }
5918
Nicolas Capens0bac2852016-05-07 06:09:58 -04005919 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5920 }
5921}
5922
5923void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5924{
5925 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5926 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5927 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5928 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5929
5930 switch(target)
5931 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005932 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005933 break;
5934 default:
5935 return error(GL_INVALID_ENUM);
5936 }
5937
5938 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5939 {
5940 return error(GL_INVALID_VALUE);
5941 }
5942
5943 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5944 {
5945 return error(GL_INVALID_VALUE);
5946 }
5947
Nicolas Capens83463112018-06-12 23:55:16 -04005948 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005949 {
Nicolas Capens03589982018-02-01 17:28:32 -05005950 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005951 }
5952
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005953 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005954 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005955 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005956 }
5957
5958 es2::Context *context = es2::getContext();
5959
5960 if(context)
5961 {
5962 es2::Texture3D *texture = context->getTexture3D();
5963
5964 if(!texture)
5965 {
5966 return error(GL_INVALID_OPERATION);
5967 }
5968
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005969 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005970 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005971 {
5972 return error(validationError);
5973 }
5974
5975 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005976 }
5977}
5978
5979void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5980{
5981 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5982 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5983
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005984 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005985 {
5986 return error(GL_INVALID_ENUM);
5987 }
5988
5989 es2::Context *context = es2::getContext();
5990
5991 if(context)
5992 {
5993 if(texture == 0)
5994 {
5995 textarget = GL_NONE;
5996 }
5997 else
5998 {
5999 es2::Texture *tex = context->getTexture(texture);
6000
6001 if(!tex)
6002 {
6003 return error(GL_INVALID_OPERATION);
6004 }
6005
6006 if(tex->isCompressed(textarget, level))
6007 {
6008 return error(GL_INVALID_OPERATION);
6009 }
6010
6011 switch(textarget)
6012 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006013 case GL_TEXTURE_3D:
6014 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006015 {
6016 return error(GL_INVALID_OPERATION);
6017 }
6018 break;
6019 default:
6020 return error(GL_INVALID_ENUM);
6021 }
6022
6023 if(level != 0)
6024 {
6025 return error(GL_INVALID_VALUE);
6026 }
6027 }
6028
6029 es2::Framebuffer *framebuffer = nullptr;
6030 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006031 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006032 {
6033 framebuffer = context->getReadFramebuffer();
6034 framebufferName = context->getReadFramebufferName();
6035 }
6036 else
6037 {
6038 framebuffer = context->getDrawFramebuffer();
6039 framebufferName = context->getDrawFramebufferName();
6040 }
6041
6042 if(framebufferName == 0 || !framebuffer)
6043 {
6044 return error(GL_INVALID_OPERATION);
6045 }
6046
Nicolas Capens0bac2852016-05-07 06:09:58 -04006047 switch(attachment)
6048 {
Nicolas Capens83463112018-06-12 23:55:16 -04006049 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6050 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6051 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006052 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6053 {
6054 return error(GL_INVALID_ENUM);
6055 }
6056 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6057 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006058 }
6059 }
6060}
6061
6062void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6063{
6064 if(egl::getClientVersion() == 1)
6065 {
6066 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6067 }
6068
6069 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6070
6071 switch(target)
6072 {
6073 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006074 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006075 case GL_TEXTURE_EXTERNAL_OES:
6076 break;
6077 default:
6078 return error(GL_INVALID_ENUM);
6079 }
6080
Nicolas Capens0bac2852016-05-07 06:09:58 -04006081 es2::Context *context = es2::getContext();
6082
6083 if(context)
6084 {
Alexis Hetu46768622018-01-16 22:09:28 -05006085 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006086
6087 if(!texture)
6088 {
6089 return error(GL_INVALID_OPERATION);
6090 }
6091
Nicolas Capens58df2f62016-06-07 14:48:56 -04006092 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006093
Nicolas Capens58df2f62016-06-07 14:48:56 -04006094 if(!eglImage)
6095 {
6096 return error(GL_INVALID_OPERATION);
6097 }
6098
6099 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006100 }
6101}
6102
6103void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6104{
6105 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6106
6107 UNIMPLEMENTED();
6108}
6109
6110GLboolean IsRenderbufferOES(GLuint renderbuffer)
6111{
6112 return IsRenderbuffer(renderbuffer);
6113}
6114
6115void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6116{
6117 BindRenderbuffer(target, renderbuffer);
6118}
6119
6120void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6121{
6122 DeleteRenderbuffers(n, renderbuffers);
6123}
6124
6125void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6126{
6127 GenRenderbuffers(n, renderbuffers);
6128}
6129
6130void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6131{
6132 RenderbufferStorage(target, internalformat, width, height);
6133}
6134
6135void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6136{
6137 GetRenderbufferParameteriv(target, pname, params);
6138}
6139
6140GLboolean IsFramebufferOES(GLuint framebuffer)
6141{
6142 return IsFramebuffer(framebuffer);
6143}
6144
6145void BindFramebufferOES(GLenum target, GLuint framebuffer)
6146{
6147 BindFramebuffer(target, framebuffer);
6148}
6149
6150void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6151{
6152 DeleteFramebuffers(n, framebuffers);
6153}
6154
6155void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6156{
6157 GenFramebuffers(n, framebuffers);
6158}
6159
6160GLenum CheckFramebufferStatusOES(GLenum target)
6161{
6162 return CheckFramebufferStatus(target);
6163}
6164
6165void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6166{
6167 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6168}
6169
6170void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6171{
6172 FramebufferTexture2D(target, attachment, textarget, texture, level);
6173}
6174
6175void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6176{
6177 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6178}
6179
6180void GenerateMipmapOES(GLenum target)
6181{
6182 GenerateMipmap(target);
6183}
6184
6185void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6186{
6187 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6188
6189 if(n < 0 || n > MAX_DRAW_BUFFERS)
6190 {
6191 return error(GL_INVALID_VALUE);
6192 }
6193
6194 es2::Context *context = es2::getContext();
6195
6196 if(context)
6197 {
6198 GLuint drawFramebufferName = context->getDrawFramebufferName();
6199
6200 if((drawFramebufferName == 0) && (n != 1))
6201 {
6202 return error(GL_INVALID_OPERATION);
6203 }
6204
6205 for(unsigned int i = 0; i < (unsigned)n; i++)
6206 {
6207 switch(bufs[i])
6208 {
6209 case GL_BACK:
6210 if(drawFramebufferName != 0)
6211 {
6212 return error(GL_INVALID_OPERATION);
6213 }
6214 break;
6215 case GL_NONE:
6216 break;
6217 case GL_COLOR_ATTACHMENT0_EXT:
6218 case GL_COLOR_ATTACHMENT1_EXT:
6219 case GL_COLOR_ATTACHMENT2_EXT:
6220 case GL_COLOR_ATTACHMENT3_EXT:
6221 case GL_COLOR_ATTACHMENT4_EXT:
6222 case GL_COLOR_ATTACHMENT5_EXT:
6223 case GL_COLOR_ATTACHMENT6_EXT:
6224 case GL_COLOR_ATTACHMENT7_EXT:
6225 case GL_COLOR_ATTACHMENT8_EXT:
6226 case GL_COLOR_ATTACHMENT9_EXT:
6227 case GL_COLOR_ATTACHMENT10_EXT:
6228 case GL_COLOR_ATTACHMENT11_EXT:
6229 case GL_COLOR_ATTACHMENT12_EXT:
6230 case GL_COLOR_ATTACHMENT13_EXT:
6231 case GL_COLOR_ATTACHMENT14_EXT:
6232 case GL_COLOR_ATTACHMENT15_EXT:
6233 {
6234 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6235
6236 if(index >= MAX_COLOR_ATTACHMENTS)
6237 {
6238 return error(GL_INVALID_OPERATION);
6239 }
6240
6241 if(index != i)
6242 {
6243 return error(GL_INVALID_OPERATION);
6244 }
6245
6246 if(drawFramebufferName == 0)
6247 {
6248 return error(GL_INVALID_OPERATION);
6249 }
6250 }
6251 break;
6252 default:
6253 return error(GL_INVALID_ENUM);
6254 }
6255 }
6256
6257 context->setFramebufferDrawBuffers(n, bufs);
6258 }
6259}
6260
6261}
6262
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006263extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006264{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006265 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006266 {
6267 const char *name;
6268 __eglMustCastToProperFunctionPointerType address;
6269 };
6270
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006271 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006272 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006273 bool operator()(const Function &a, const Function &b) const
6274 {
6275 return strcmp(a.name, b.name) < 0;
6276 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006277 };
6278
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006279 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6280 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6281 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006282 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006283 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6284
6285 FUNCTION(glActiveTexture),
6286 FUNCTION(glAttachShader),
6287 FUNCTION(glBeginQuery),
6288 FUNCTION(glBeginQueryEXT),
6289 FUNCTION(glBeginTransformFeedback),
6290 FUNCTION(glBindAttribLocation),
6291 FUNCTION(glBindBuffer),
6292 FUNCTION(glBindBufferBase),
6293 FUNCTION(glBindBufferRange),
6294 FUNCTION(glBindFramebuffer),
6295 FUNCTION(glBindFramebufferOES),
6296 FUNCTION(glBindRenderbuffer),
6297 FUNCTION(glBindRenderbufferOES),
6298 FUNCTION(glBindSampler),
6299 FUNCTION(glBindTexture),
6300 FUNCTION(glBindTransformFeedback),
6301 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006302 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006303 FUNCTION(glBlendColor),
6304 FUNCTION(glBlendEquation),
6305 FUNCTION(glBlendEquationSeparate),
6306 FUNCTION(glBlendFunc),
6307 FUNCTION(glBlendFuncSeparate),
6308 FUNCTION(glBlitFramebuffer),
6309 FUNCTION(glBlitFramebufferANGLE),
6310 FUNCTION(glBufferData),
6311 FUNCTION(glBufferSubData),
6312 FUNCTION(glCheckFramebufferStatus),
6313 FUNCTION(glCheckFramebufferStatusOES),
6314 FUNCTION(glClear),
6315 FUNCTION(glClearBufferfi),
6316 FUNCTION(glClearBufferfv),
6317 FUNCTION(glClearBufferiv),
6318 FUNCTION(glClearBufferuiv),
6319 FUNCTION(glClearColor),
6320 FUNCTION(glClearDepthf),
6321 FUNCTION(glClearStencil),
6322 FUNCTION(glClientWaitSync),
6323 FUNCTION(glColorMask),
6324 FUNCTION(glCompileShader),
6325 FUNCTION(glCompressedTexImage2D),
6326 FUNCTION(glCompressedTexImage3D),
6327 FUNCTION(glCompressedTexSubImage2D),
6328 FUNCTION(glCompressedTexSubImage3D),
6329 FUNCTION(glCopyBufferSubData),
6330 FUNCTION(glCopyTexImage2D),
6331 FUNCTION(glCopyTexSubImage2D),
6332 FUNCTION(glCopyTexSubImage3D),
6333 FUNCTION(glCreateProgram),
6334 FUNCTION(glCreateShader),
6335 FUNCTION(glCullFace),
6336 FUNCTION(glDeleteBuffers),
6337 FUNCTION(glDeleteFencesNV),
6338 FUNCTION(glDeleteFramebuffers),
6339 FUNCTION(glDeleteFramebuffersOES),
6340 FUNCTION(glDeleteProgram),
6341 FUNCTION(glDeleteQueries),
6342 FUNCTION(glDeleteQueriesEXT),
6343 FUNCTION(glDeleteRenderbuffers),
6344 FUNCTION(glDeleteRenderbuffersOES),
6345 FUNCTION(glDeleteSamplers),
6346 FUNCTION(glDeleteShader),
6347 FUNCTION(glDeleteSync),
6348 FUNCTION(glDeleteTextures),
6349 FUNCTION(glDeleteTransformFeedbacks),
6350 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006351 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006352 FUNCTION(glDepthFunc),
6353 FUNCTION(glDepthMask),
6354 FUNCTION(glDepthRangef),
6355 FUNCTION(glDetachShader),
6356 FUNCTION(glDisable),
6357 FUNCTION(glDisableVertexAttribArray),
6358 FUNCTION(glDrawArrays),
6359 FUNCTION(glDrawArraysInstanced),
6360 FUNCTION(glDrawBuffers),
6361 FUNCTION(glDrawBuffersEXT),
6362 FUNCTION(glDrawElements),
6363 FUNCTION(glDrawElementsInstanced),
6364 FUNCTION(glDrawRangeElements),
6365 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6366 FUNCTION(glEGLImageTargetTexture2DOES),
6367 FUNCTION(glEnable),
6368 FUNCTION(glEnableVertexAttribArray),
6369 FUNCTION(glEndQuery),
6370 FUNCTION(glEndQueryEXT),
6371 FUNCTION(glEndTransformFeedback),
6372 FUNCTION(glFenceSync),
6373 FUNCTION(glFinish),
6374 FUNCTION(glFinishFenceNV),
6375 FUNCTION(glFlush),
6376 FUNCTION(glFlushMappedBufferRange),
6377 FUNCTION(glFramebufferRenderbuffer),
6378 FUNCTION(glFramebufferRenderbufferOES),
6379 FUNCTION(glFramebufferTexture2D),
6380 FUNCTION(glFramebufferTexture2DOES),
6381 FUNCTION(glFramebufferTextureLayer),
6382 FUNCTION(glFrontFace),
6383 FUNCTION(glGenBuffers),
6384 FUNCTION(glGenFencesNV),
6385 FUNCTION(glGenFramebuffers),
6386 FUNCTION(glGenFramebuffersOES),
6387 FUNCTION(glGenQueries),
6388 FUNCTION(glGenQueriesEXT),
6389 FUNCTION(glGenRenderbuffers),
6390 FUNCTION(glGenRenderbuffersOES),
6391 FUNCTION(glGenSamplers),
6392 FUNCTION(glGenTextures),
6393 FUNCTION(glGenTransformFeedbacks),
6394 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006395 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006396 FUNCTION(glGenerateMipmap),
6397 FUNCTION(glGenerateMipmapOES),
6398 FUNCTION(glGetActiveAttrib),
6399 FUNCTION(glGetActiveUniform),
6400 FUNCTION(glGetActiveUniformBlockName),
6401 FUNCTION(glGetActiveUniformBlockiv),
6402 FUNCTION(glGetActiveUniformsiv),
6403 FUNCTION(glGetAttachedShaders),
6404 FUNCTION(glGetAttribLocation),
6405 FUNCTION(glGetBooleanv),
6406 FUNCTION(glGetBufferParameteri64v),
6407 FUNCTION(glGetBufferParameteriv),
6408 FUNCTION(glGetBufferPointerv),
6409 FUNCTION(glGetError),
6410 FUNCTION(glGetFenceivNV),
6411 FUNCTION(glGetFloatv),
6412 FUNCTION(glGetFragDataLocation),
6413 FUNCTION(glGetFramebufferAttachmentParameteriv),
6414 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6415 FUNCTION(glGetGraphicsResetStatusEXT),
6416 FUNCTION(glGetInteger64i_v),
6417 FUNCTION(glGetInteger64v),
6418 FUNCTION(glGetIntegeri_v),
6419 FUNCTION(glGetIntegerv),
6420 FUNCTION(glGetInternalformativ),
6421 FUNCTION(glGetProgramBinary),
6422 FUNCTION(glGetProgramInfoLog),
6423 FUNCTION(glGetProgramiv),
6424 FUNCTION(glGetQueryObjectuiv),
6425 FUNCTION(glGetQueryObjectuivEXT),
6426 FUNCTION(glGetQueryiv),
6427 FUNCTION(glGetQueryivEXT),
6428 FUNCTION(glGetRenderbufferParameteriv),
6429 FUNCTION(glGetRenderbufferParameterivOES),
6430 FUNCTION(glGetSamplerParameterfv),
6431 FUNCTION(glGetSamplerParameteriv),
6432 FUNCTION(glGetShaderInfoLog),
6433 FUNCTION(glGetShaderPrecisionFormat),
6434 FUNCTION(glGetShaderSource),
6435 FUNCTION(glGetShaderiv),
6436 FUNCTION(glGetString),
6437 FUNCTION(glGetStringi),
6438 FUNCTION(glGetSynciv),
6439 FUNCTION(glGetTexParameterfv),
6440 FUNCTION(glGetTexParameteriv),
6441 FUNCTION(glGetTransformFeedbackVarying),
6442 FUNCTION(glGetUniformBlockIndex),
6443 FUNCTION(glGetUniformIndices),
6444 FUNCTION(glGetUniformLocation),
6445 FUNCTION(glGetUniformfv),
6446 FUNCTION(glGetUniformiv),
6447 FUNCTION(glGetUniformuiv),
6448 FUNCTION(glGetVertexAttribIiv),
6449 FUNCTION(glGetVertexAttribIuiv),
6450 FUNCTION(glGetVertexAttribPointerv),
6451 FUNCTION(glGetVertexAttribfv),
6452 FUNCTION(glGetVertexAttribiv),
6453 FUNCTION(glGetnUniformfvEXT),
6454 FUNCTION(glGetnUniformivEXT),
6455 FUNCTION(glHint),
6456 FUNCTION(glInvalidateFramebuffer),
6457 FUNCTION(glInvalidateSubFramebuffer),
6458 FUNCTION(glIsBuffer),
6459 FUNCTION(glIsEnabled),
6460 FUNCTION(glIsFenceNV),
6461 FUNCTION(glIsFramebuffer),
6462 FUNCTION(glIsFramebufferOES),
6463 FUNCTION(glIsProgram),
6464 FUNCTION(glIsQuery),
6465 FUNCTION(glIsQueryEXT),
6466 FUNCTION(glIsRenderbuffer),
6467 FUNCTION(glIsRenderbufferOES),
6468 FUNCTION(glIsSampler),
6469 FUNCTION(glIsShader),
6470 FUNCTION(glIsSync),
6471 FUNCTION(glIsTexture),
6472 FUNCTION(glIsTransformFeedback),
6473 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006474 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006475 FUNCTION(glLineWidth),
6476 FUNCTION(glLinkProgram),
6477 FUNCTION(glMapBufferRange),
6478 FUNCTION(glPauseTransformFeedback),
6479 FUNCTION(glPixelStorei),
6480 FUNCTION(glPolygonOffset),
6481 FUNCTION(glProgramBinary),
6482 FUNCTION(glProgramParameteri),
6483 FUNCTION(glReadBuffer),
6484 FUNCTION(glReadPixels),
6485 FUNCTION(glReadnPixelsEXT),
6486 FUNCTION(glReleaseShaderCompiler),
6487 FUNCTION(glRenderbufferStorage),
6488 FUNCTION(glRenderbufferStorageMultisample),
6489 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6490 FUNCTION(glRenderbufferStorageOES),
6491 FUNCTION(glResumeTransformFeedback),
6492 FUNCTION(glSampleCoverage),
6493 FUNCTION(glSamplerParameterf),
6494 FUNCTION(glSamplerParameterfv),
6495 FUNCTION(glSamplerParameteri),
6496 FUNCTION(glSamplerParameteriv),
6497 FUNCTION(glScissor),
6498 FUNCTION(glSetFenceNV),
6499 FUNCTION(glShaderBinary),
6500 FUNCTION(glShaderSource),
6501 FUNCTION(glStencilFunc),
6502 FUNCTION(glStencilFuncSeparate),
6503 FUNCTION(glStencilMask),
6504 FUNCTION(glStencilMaskSeparate),
6505 FUNCTION(glStencilOp),
6506 FUNCTION(glStencilOpSeparate),
6507 FUNCTION(glTestFenceNV),
6508 FUNCTION(glTexImage2D),
6509 FUNCTION(glTexImage3D),
6510 FUNCTION(glTexImage3DOES),
6511 FUNCTION(glTexParameterf),
6512 FUNCTION(glTexParameterfv),
6513 FUNCTION(glTexParameteri),
6514 FUNCTION(glTexParameteriv),
6515 FUNCTION(glTexStorage2D),
6516 FUNCTION(glTexStorage3D),
6517 FUNCTION(glTexSubImage2D),
6518 FUNCTION(glTexSubImage3D),
6519 FUNCTION(glTransformFeedbackVaryings),
6520 FUNCTION(glUniform1f),
6521 FUNCTION(glUniform1fv),
6522 FUNCTION(glUniform1i),
6523 FUNCTION(glUniform1iv),
6524 FUNCTION(glUniform1ui),
6525 FUNCTION(glUniform1uiv),
6526 FUNCTION(glUniform2f),
6527 FUNCTION(glUniform2fv),
6528 FUNCTION(glUniform2i),
6529 FUNCTION(glUniform2iv),
6530 FUNCTION(glUniform2ui),
6531 FUNCTION(glUniform2uiv),
6532 FUNCTION(glUniform3f),
6533 FUNCTION(glUniform3fv),
6534 FUNCTION(glUniform3i),
6535 FUNCTION(glUniform3iv),
6536 FUNCTION(glUniform3ui),
6537 FUNCTION(glUniform3uiv),
6538 FUNCTION(glUniform4f),
6539 FUNCTION(glUniform4fv),
6540 FUNCTION(glUniform4i),
6541 FUNCTION(glUniform4iv),
6542 FUNCTION(glUniform4ui),
6543 FUNCTION(glUniform4uiv),
6544 FUNCTION(glUniformBlockBinding),
6545 FUNCTION(glUniformMatrix2fv),
6546 FUNCTION(glUniformMatrix2x3fv),
6547 FUNCTION(glUniformMatrix2x4fv),
6548 FUNCTION(glUniformMatrix3fv),
6549 FUNCTION(glUniformMatrix3x2fv),
6550 FUNCTION(glUniformMatrix3x4fv),
6551 FUNCTION(glUniformMatrix4fv),
6552 FUNCTION(glUniformMatrix4x2fv),
6553 FUNCTION(glUniformMatrix4x3fv),
6554 FUNCTION(glUnmapBuffer),
6555 FUNCTION(glUseProgram),
6556 FUNCTION(glValidateProgram),
6557 FUNCTION(glVertexAttrib1f),
6558 FUNCTION(glVertexAttrib1fv),
6559 FUNCTION(glVertexAttrib2f),
6560 FUNCTION(glVertexAttrib2fv),
6561 FUNCTION(glVertexAttrib3f),
6562 FUNCTION(glVertexAttrib3fv),
6563 FUNCTION(glVertexAttrib4f),
6564 FUNCTION(glVertexAttrib4fv),
6565 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006566 FUNCTION(glVertexAttribDivisorANGLE),
6567 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006568 FUNCTION(glVertexAttribI4i),
6569 FUNCTION(glVertexAttribI4iv),
6570 FUNCTION(glVertexAttribI4ui),
6571 FUNCTION(glVertexAttribI4uiv),
6572 FUNCTION(glVertexAttribIPointer),
6573 FUNCTION(glVertexAttribPointer),
6574 FUNCTION(glViewport),
6575 FUNCTION(glWaitSync),
6576
6577 #undef FUNCTION
6578 };
6579
6580 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6581 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6582
6583 Function needle;
6584 needle.name = procname;
6585
6586 if(procname && strncmp("gl", procname, 2) == 0)
6587 {
6588 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
6589 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006590 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006591 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006592 }
6593 }
6594
6595 return nullptr;
6596}