blob: b3f1d201a8d3061c575e1bf250639226c32e6e0d [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 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400933 if(colorbufferFormat == GL_RGB10_A2)
934 {
935 // Not supported with unsized internalformat.
936 // https://www.khronos.org/members/login/bugzilla/show_bug.cgi?id=9807#c56
937 return error(GL_INVALID_OPERATION);
938 }
939
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500940 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
941 {
942 internalformat = colorbufferFormat;
943 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400944 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500945 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400946 // TODO: Convert to the smallest format that fits all components.
947 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
948
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500949 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
950 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400951 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
952 {
953 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
954 }
955 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
956 {
957 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
958 }
959 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
960 {
961 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
962 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400963 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
964 {
965 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
966 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500967 else
968 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400969 printf("internalformat = %x, colorbufferFormat = %X\n", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500970 UNIMPLEMENTED();
971
972 return error(GL_INVALID_OPERATION);
973 }
974 }
975
Nicolas Capens8f215a42018-02-02 13:25:53 -0500976 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400977 {
978 return;
979 }
980
Alexis Hetu46768622018-01-16 22:09:28 -0500981 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400982 {
Alexis Hetu46768622018-01-16 22:09:28 -0500983 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400984
985 if(!texture)
986 {
987 return error(GL_INVALID_OPERATION);
988 }
989
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500990 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400991 }
992 else if(es2::IsCubemapTextureTarget(target))
993 {
994 es2::TextureCubeMap *texture = context->getTextureCubeMap();
995
996 if(!texture)
997 {
998 return error(GL_INVALID_OPERATION);
999 }
1000
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001001 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001002 }
1003 else UNREACHABLE(target);
1004 }
1005}
1006
1007void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1008{
1009 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1010 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1011 target, level, xoffset, yoffset, x, y, width, height);
1012
1013 if(!es2::IsTextureTarget(target))
1014 {
1015 return error(GL_INVALID_ENUM);
1016 }
1017
1018 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1019 {
1020 return error(GL_INVALID_VALUE);
1021 }
1022
1023 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1024 {
1025 return error(GL_INVALID_VALUE);
1026 }
1027
1028 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1029 {
1030 return error(GL_INVALID_VALUE);
1031 }
1032
Nicolas Capens0bac2852016-05-07 06:09:58 -04001033 es2::Context *context = es2::getContext();
1034
1035 if(context)
1036 {
1037 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1038
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001039 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001040 {
1041 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1042 }
1043
1044 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1045
1046 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1047 {
1048 return error(GL_INVALID_OPERATION);
1049 }
1050
1051 es2::Texture *texture = nullptr;
1052
Alexis Hetu46768622018-01-16 22:09:28 -05001053 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001054 {
Alexis Hetu46768622018-01-16 22:09:28 -05001055 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001056 }
1057 else if(es2::IsCubemapTextureTarget(target))
1058 {
1059 texture = context->getTextureCubeMap();
1060 }
1061 else UNREACHABLE(target);
1062
Nicolas Capens83463112018-06-12 23:55:16 -04001063 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001064 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001065 {
1066 return error(validationError);
1067 }
1068
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001069 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001070 }
1071}
1072
1073GLuint CreateProgram(void)
1074{
1075 TRACE("()");
1076
1077 es2::Context *context = es2::getContext();
1078
1079 if(context)
1080 {
1081 return context->createProgram();
1082 }
1083
1084 return 0;
1085}
1086
1087GLuint CreateShader(GLenum type)
1088{
1089 TRACE("(GLenum type = 0x%X)", type);
1090
1091 es2::Context *context = es2::getContext();
1092
1093 if(context)
1094 {
1095 switch(type)
1096 {
1097 case GL_FRAGMENT_SHADER:
1098 case GL_VERTEX_SHADER:
1099 return context->createShader(type);
1100 default:
1101 return error(GL_INVALID_ENUM, 0);
1102 }
1103 }
1104
1105 return 0;
1106}
1107
1108void CullFace(GLenum mode)
1109{
1110 TRACE("(GLenum mode = 0x%X)", mode);
1111
1112 switch(mode)
1113 {
1114 case GL_FRONT:
1115 case GL_BACK:
1116 case GL_FRONT_AND_BACK:
1117 {
1118 es2::Context *context = es2::getContext();
1119
1120 if(context)
1121 {
1122 context->setCullMode(mode);
1123 }
1124 }
1125 break;
1126 default:
1127 return error(GL_INVALID_ENUM);
1128 }
1129}
1130
1131void DeleteBuffers(GLsizei n, const GLuint* buffers)
1132{
1133 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1134
1135 if(n < 0)
1136 {
1137 return error(GL_INVALID_VALUE);
1138 }
1139
1140 es2::Context *context = es2::getContext();
1141
1142 if(context)
1143 {
1144 for(int i = 0; i < n; i++)
1145 {
1146 context->deleteBuffer(buffers[i]);
1147 }
1148 }
1149}
1150
1151void DeleteFencesNV(GLsizei n, const GLuint* fences)
1152{
1153 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1154
1155 if(n < 0)
1156 {
1157 return error(GL_INVALID_VALUE);
1158 }
1159
1160 es2::Context *context = es2::getContext();
1161
1162 if(context)
1163 {
1164 for(int i = 0; i < n; i++)
1165 {
1166 context->deleteFence(fences[i]);
1167 }
1168 }
1169}
1170
1171void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1172{
1173 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1174
1175 if(n < 0)
1176 {
1177 return error(GL_INVALID_VALUE);
1178 }
1179
1180 es2::Context *context = es2::getContext();
1181
1182 if(context)
1183 {
1184 for(int i = 0; i < n; i++)
1185 {
1186 if(framebuffers[i] != 0)
1187 {
1188 context->deleteFramebuffer(framebuffers[i]);
1189 }
1190 }
1191 }
1192}
1193
1194void DeleteProgram(GLuint program)
1195{
1196 TRACE("(GLuint program = %d)", program);
1197
1198 if(program == 0)
1199 {
1200 return;
1201 }
1202
1203 es2::Context *context = es2::getContext();
1204
1205 if(context)
1206 {
1207 if(!context->getProgram(program))
1208 {
1209 if(context->getShader(program))
1210 {
1211 return error(GL_INVALID_OPERATION);
1212 }
1213 else
1214 {
1215 return error(GL_INVALID_VALUE);
1216 }
1217 }
1218
1219 context->deleteProgram(program);
1220 }
1221}
1222
1223void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1224{
1225 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1226
1227 if(n < 0)
1228 {
1229 return error(GL_INVALID_VALUE);
1230 }
1231
1232 es2::Context *context = es2::getContext();
1233
1234 if(context)
1235 {
1236 for(int i = 0; i < n; i++)
1237 {
1238 context->deleteQuery(ids[i]);
1239 }
1240 }
1241}
1242
1243void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1244{
1245 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1246
1247 if(n < 0)
1248 {
1249 return error(GL_INVALID_VALUE);
1250 }
1251
1252 es2::Context *context = es2::getContext();
1253
1254 if(context)
1255 {
1256 for(int i = 0; i < n; i++)
1257 {
1258 context->deleteRenderbuffer(renderbuffers[i]);
1259 }
1260 }
1261}
1262
1263void DeleteShader(GLuint shader)
1264{
1265 TRACE("(GLuint shader = %d)", shader);
1266
1267 if(shader == 0)
1268 {
1269 return;
1270 }
1271
1272 es2::Context *context = es2::getContext();
1273
1274 if(context)
1275 {
1276 if(!context->getShader(shader))
1277 {
1278 if(context->getProgram(shader))
1279 {
1280 return error(GL_INVALID_OPERATION);
1281 }
1282 else
1283 {
1284 return error(GL_INVALID_VALUE);
1285 }
1286 }
1287
1288 context->deleteShader(shader);
1289 }
1290}
1291
1292void DeleteTextures(GLsizei n, const GLuint* textures)
1293{
1294 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1295
1296 if(n < 0)
1297 {
1298 return error(GL_INVALID_VALUE);
1299 }
1300
1301 es2::Context *context = es2::getContext();
1302
1303 if(context)
1304 {
1305 for(int i = 0; i < n; i++)
1306 {
1307 if(textures[i] != 0)
1308 {
1309 context->deleteTexture(textures[i]);
1310 }
1311 }
1312 }
1313}
1314
1315void DepthFunc(GLenum func)
1316{
1317 TRACE("(GLenum func = 0x%X)", func);
1318
1319 switch(func)
1320 {
1321 case GL_NEVER:
1322 case GL_ALWAYS:
1323 case GL_LESS:
1324 case GL_LEQUAL:
1325 case GL_EQUAL:
1326 case GL_GREATER:
1327 case GL_GEQUAL:
1328 case GL_NOTEQUAL:
1329 break;
1330 default:
1331 return error(GL_INVALID_ENUM);
1332 }
1333
1334 es2::Context *context = es2::getContext();
1335
1336 if(context)
1337 {
1338 context->setDepthFunc(func);
1339 }
1340}
1341
1342void DepthMask(GLboolean flag)
1343{
1344 TRACE("(GLboolean flag = %d)", flag);
1345
1346 es2::Context *context = es2::getContext();
1347
1348 if(context)
1349 {
1350 context->setDepthMask(flag != GL_FALSE);
1351 }
1352}
1353
1354void DepthRangef(GLclampf zNear, GLclampf zFar)
1355{
1356 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1357
1358 es2::Context *context = es2::getContext();
1359
1360 if(context)
1361 {
1362 context->setDepthRange(zNear, zFar);
1363 }
1364}
1365
1366void DetachShader(GLuint program, GLuint shader)
1367{
1368 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1369
1370 es2::Context *context = es2::getContext();
1371
1372 if(context)
1373 {
1374
1375 es2::Program *programObject = context->getProgram(program);
1376 es2::Shader *shaderObject = context->getShader(shader);
1377
1378 if(!programObject)
1379 {
1380 es2::Shader *shaderByProgramHandle;
1381 shaderByProgramHandle = context->getShader(program);
1382 if(!shaderByProgramHandle)
1383 {
1384 return error(GL_INVALID_VALUE);
1385 }
1386 else
1387 {
1388 return error(GL_INVALID_OPERATION);
1389 }
1390 }
1391
1392 if(!shaderObject)
1393 {
1394 es2::Program *programByShaderHandle = context->getProgram(shader);
1395 if(!programByShaderHandle)
1396 {
1397 return error(GL_INVALID_VALUE);
1398 }
1399 else
1400 {
1401 return error(GL_INVALID_OPERATION);
1402 }
1403 }
1404
1405 if(!programObject->detachShader(shaderObject))
1406 {
1407 return error(GL_INVALID_OPERATION);
1408 }
1409 }
1410}
1411
1412void Disable(GLenum cap)
1413{
1414 TRACE("(GLenum cap = 0x%X)", cap);
1415
1416 es2::Context *context = es2::getContext();
1417
1418 if(context)
1419 {
1420 switch(cap)
1421 {
1422 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1423 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1424 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1425 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1426 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1427 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1428 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1429 case GL_BLEND: context->setBlendEnabled(false); break;
1430 case GL_DITHER: context->setDitherEnabled(false); break;
1431 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1432 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1433 default:
1434 return error(GL_INVALID_ENUM);
1435 }
1436 }
1437}
1438
1439void DisableVertexAttribArray(GLuint index)
1440{
1441 TRACE("(GLuint index = %d)", index);
1442
1443 if(index >= es2::MAX_VERTEX_ATTRIBS)
1444 {
1445 return error(GL_INVALID_VALUE);
1446 }
1447
1448 es2::Context *context = es2::getContext();
1449
1450 if(context)
1451 {
1452 context->setVertexAttribArrayEnabled(index, false);
1453 }
1454}
1455
1456void DrawArrays(GLenum mode, GLint first, GLsizei count)
1457{
1458 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1459
1460 switch(mode)
1461 {
1462 case GL_POINTS:
1463 case GL_LINES:
1464 case GL_LINE_LOOP:
1465 case GL_LINE_STRIP:
1466 case GL_TRIANGLES:
1467 case GL_TRIANGLE_FAN:
1468 case GL_TRIANGLE_STRIP:
1469 break;
1470 default:
1471 return error(GL_INVALID_ENUM);
1472 }
1473
1474 if(count < 0 || first < 0)
1475 {
1476 return error(GL_INVALID_VALUE);
1477 }
1478
1479 es2::Context *context = es2::getContext();
1480
1481 if(context)
1482 {
1483 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1484 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1485 {
1486 return error(GL_INVALID_OPERATION);
1487 }
1488
1489 context->drawArrays(mode, first, count);
1490 }
1491}
1492
1493void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1494{
1495 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1496 mode, count, type, indices);
1497
1498 switch(mode)
1499 {
1500 case GL_POINTS:
1501 case GL_LINES:
1502 case GL_LINE_LOOP:
1503 case GL_LINE_STRIP:
1504 case GL_TRIANGLES:
1505 case GL_TRIANGLE_FAN:
1506 case GL_TRIANGLE_STRIP:
1507 break;
1508 default:
1509 return error(GL_INVALID_ENUM);
1510 }
1511
1512 if(count < 0)
1513 {
1514 return error(GL_INVALID_VALUE);
1515 }
1516
1517 es2::Context *context = es2::getContext();
1518
1519 if(context)
1520 {
1521 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1522 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1523 {
1524 return error(GL_INVALID_OPERATION);
1525 }
1526
1527 switch(type)
1528 {
1529 case GL_UNSIGNED_BYTE:
1530 case GL_UNSIGNED_SHORT:
1531 case GL_UNSIGNED_INT:
1532 break;
1533 default:
1534 return error(GL_INVALID_ENUM);
1535 }
1536
1537 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1538 }
1539}
1540
1541void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1542{
1543 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1544 mode, first, count, instanceCount);
1545
1546 switch(mode)
1547 {
1548 case GL_POINTS:
1549 case GL_LINES:
1550 case GL_LINE_LOOP:
1551 case GL_LINE_STRIP:
1552 case GL_TRIANGLES:
1553 case GL_TRIANGLE_FAN:
1554 case GL_TRIANGLE_STRIP:
1555 break;
1556 default:
1557 return error(GL_INVALID_ENUM);
1558 }
1559
1560 if(count < 0 || instanceCount < 0)
1561 {
1562 return error(GL_INVALID_VALUE);
1563 }
1564
1565 es2::Context *context = es2::getContext();
1566
1567 if(context)
1568 {
1569 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1570 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1571 {
1572 return error(GL_INVALID_OPERATION);
1573 }
1574
1575 context->drawArrays(mode, first, count, instanceCount);
1576 }
1577}
1578
1579void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1580{
1581 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1582 mode, count, type, indices, instanceCount);
1583
1584 switch(mode)
1585 {
1586 case GL_POINTS:
1587 case GL_LINES:
1588 case GL_LINE_LOOP:
1589 case GL_LINE_STRIP:
1590 case GL_TRIANGLES:
1591 case GL_TRIANGLE_FAN:
1592 case GL_TRIANGLE_STRIP:
1593 break;
1594 default:
1595 return error(GL_INVALID_ENUM);
1596 }
1597
1598 switch(type)
1599 {
1600 case GL_UNSIGNED_BYTE:
1601 case GL_UNSIGNED_SHORT:
1602 case GL_UNSIGNED_INT:
1603 break;
1604 default:
1605 return error(GL_INVALID_ENUM);
1606 }
1607
1608 if(count < 0 || instanceCount < 0)
1609 {
1610 return error(GL_INVALID_VALUE);
1611 }
1612
1613 es2::Context *context = es2::getContext();
1614
1615 if(context)
1616 {
1617 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1618 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1619 {
1620 return error(GL_INVALID_OPERATION);
1621 }
1622
1623 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1624 }
1625}
1626
1627void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1628{
1629 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1630
1631 es2::Context *context = es2::getContext();
1632
1633 if(context)
1634 {
1635 if(index >= es2::MAX_VERTEX_ATTRIBS)
1636 {
1637 return error(GL_INVALID_VALUE);
1638 }
1639
1640 context->setVertexAttribDivisor(index, divisor);
1641 }
1642}
1643
1644void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1645{
1646 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1647 mode, first, count, instanceCount);
1648
1649 switch(mode)
1650 {
1651 case GL_POINTS:
1652 case GL_LINES:
1653 case GL_LINE_LOOP:
1654 case GL_LINE_STRIP:
1655 case GL_TRIANGLES:
1656 case GL_TRIANGLE_FAN:
1657 case GL_TRIANGLE_STRIP:
1658 break;
1659 default:
1660 return error(GL_INVALID_ENUM);
1661 }
1662
1663 if(count < 0 || instanceCount < 0)
1664 {
1665 return error(GL_INVALID_VALUE);
1666 }
1667
1668 es2::Context *context = es2::getContext();
1669
1670 if(context)
1671 {
1672 if(!context->hasZeroDivisor())
1673 {
1674 return error(GL_INVALID_OPERATION);
1675 }
1676
1677 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1678 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1679 {
1680 return error(GL_INVALID_OPERATION);
1681 }
1682
1683 context->drawArrays(mode, first, count, instanceCount);
1684 }
1685}
1686
1687void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1688{
1689 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1690 mode, count, type, indices, instanceCount);
1691
1692 switch(mode)
1693 {
1694 case GL_POINTS:
1695 case GL_LINES:
1696 case GL_LINE_LOOP:
1697 case GL_LINE_STRIP:
1698 case GL_TRIANGLES:
1699 case GL_TRIANGLE_FAN:
1700 case GL_TRIANGLE_STRIP:
1701 break;
1702 default:
1703 return error(GL_INVALID_ENUM);
1704 }
1705
1706 switch(type)
1707 {
1708 case GL_UNSIGNED_BYTE:
1709 case GL_UNSIGNED_SHORT:
1710 case GL_UNSIGNED_INT:
1711 break;
1712 default:
1713 return error(GL_INVALID_ENUM);
1714 }
1715
1716 if(count < 0 || instanceCount < 0)
1717 {
1718 return error(GL_INVALID_VALUE);
1719 }
1720
1721 es2::Context *context = es2::getContext();
1722
1723 if(context)
1724 {
1725 if(!context->hasZeroDivisor())
1726 {
1727 return error(GL_INVALID_OPERATION);
1728 }
1729
1730 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1731 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1732 {
1733 return error(GL_INVALID_OPERATION);
1734 }
1735
1736 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1737 }
1738}
1739
1740void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1741{
1742 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1743
1744 es2::Context *context = es2::getContext();
1745
1746 if(context)
1747 {
1748 if(index >= MAX_VERTEX_ATTRIBS)
1749 {
1750 return error(GL_INVALID_VALUE);
1751 }
1752
1753 context->setVertexAttribDivisor(index, divisor);
1754 }
1755}
1756
1757void Enable(GLenum cap)
1758{
1759 TRACE("(GLenum cap = 0x%X)", cap);
1760
1761 es2::Context *context = es2::getContext();
1762
1763 if(context)
1764 {
1765 switch(cap)
1766 {
1767 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1768 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1769 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1770 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1771 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1772 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1773 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1774 case GL_BLEND: context->setBlendEnabled(true); break;
1775 case GL_DITHER: context->setDitherEnabled(true); break;
1776 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1777 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1778 default:
1779 return error(GL_INVALID_ENUM);
1780 }
1781 }
1782}
1783
1784void EnableVertexAttribArray(GLuint index)
1785{
1786 TRACE("(GLuint index = %d)", index);
1787
1788 if(index >= es2::MAX_VERTEX_ATTRIBS)
1789 {
1790 return error(GL_INVALID_VALUE);
1791 }
1792
1793 es2::Context *context = es2::getContext();
1794
1795 if(context)
1796 {
1797 context->setVertexAttribArrayEnabled(index, true);
1798 }
1799}
1800
1801void EndQueryEXT(GLenum target)
1802{
1803 TRACE("GLenum target = 0x%X)", target);
1804
1805 switch(target)
1806 {
1807 case GL_ANY_SAMPLES_PASSED_EXT:
1808 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1809 break;
1810 default:
1811 return error(GL_INVALID_ENUM);
1812 }
1813
1814 es2::Context *context = es2::getContext();
1815
1816 if(context)
1817 {
1818 context->endQuery(target);
1819 }
1820}
1821
1822void FinishFenceNV(GLuint fence)
1823{
1824 TRACE("(GLuint fence = %d)", fence);
1825
1826 es2::Context *context = es2::getContext();
1827
1828 if(context)
1829 {
1830 es2::Fence *fenceObject = context->getFence(fence);
1831
1832 if(!fenceObject)
1833 {
1834 return error(GL_INVALID_OPERATION);
1835 }
1836
1837 fenceObject->finishFence();
1838 }
1839}
1840
1841void Finish(void)
1842{
1843 TRACE("()");
1844
1845 es2::Context *context = es2::getContext();
1846
1847 if(context)
1848 {
1849 context->finish();
1850 }
1851}
1852
1853void Flush(void)
1854{
1855 TRACE("()");
1856
1857 es2::Context *context = es2::getContext();
1858
1859 if(context)
1860 {
1861 context->flush();
1862 }
1863}
1864
1865void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1866{
1867 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1868 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1869
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001870 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001871 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1872 {
1873 return error(GL_INVALID_ENUM);
1874 }
1875
1876 es2::Context *context = es2::getContext();
1877
1878 if(context)
1879 {
1880 es2::Framebuffer *framebuffer = nullptr;
1881 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001882 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001883 {
1884 framebuffer = context->getReadFramebuffer();
1885 framebufferName = context->getReadFramebufferName();
1886 }
1887 else
1888 {
1889 framebuffer = context->getDrawFramebuffer();
1890 framebufferName = context->getDrawFramebufferName();
1891 }
1892
1893 if(!framebuffer || framebufferName == 0)
1894 {
1895 return error(GL_INVALID_OPERATION);
1896 }
1897
1898 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1899 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1900 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1901 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1902 if(renderbuffer != 0)
1903 {
1904 if(!context->getRenderbuffer(renderbuffer))
1905 {
1906 return error(GL_INVALID_OPERATION);
1907 }
1908 }
1909
Nicolas Capens0bac2852016-05-07 06:09:58 -04001910 switch(attachment)
1911 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001912 case GL_DEPTH_ATTACHMENT:
1913 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1914 break;
1915 case GL_STENCIL_ATTACHMENT:
1916 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1917 break;
1918 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001919 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1920 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1921 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001922 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001923 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1924 {
1925 return error(GL_INVALID_ENUM);
1926 }
1927 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1928 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001929 }
1930 }
1931}
1932
1933void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1934{
1935 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1936 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1937
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001938 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001939 {
1940 return error(GL_INVALID_ENUM);
1941 }
1942
1943 es2::Context *context = es2::getContext();
1944
1945 if(context)
1946 {
1947 if(texture == 0)
1948 {
1949 textarget = GL_NONE;
1950 }
1951 else
1952 {
1953 es2::Texture *tex = context->getTexture(texture);
1954
1955 if(!tex)
1956 {
1957 return error(GL_INVALID_OPERATION);
1958 }
1959
1960 switch(textarget)
1961 {
1962 case GL_TEXTURE_2D:
1963 if(tex->getTarget() != GL_TEXTURE_2D)
1964 {
1965 return error(GL_INVALID_OPERATION);
1966 }
1967 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001968 case GL_TEXTURE_RECTANGLE_ARB:
1969 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1970 {
1971 return error(GL_INVALID_OPERATION);
1972 }
1973 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001974 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1975 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1976 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1977 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1978 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1979 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1980 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1981 {
1982 return error(GL_INVALID_OPERATION);
1983 }
1984 break;
1985 default:
1986 return error(GL_INVALID_ENUM);
1987 }
1988
Nicolas Capens83463112018-06-12 23:55:16 -04001989 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001990 {
1991 return error(GL_INVALID_VALUE);
1992 }
1993
1994 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1995 {
1996 return error(GL_INVALID_VALUE);
1997 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001998
1999 if(tex->isCompressed(textarget, level))
2000 {
2001 return error(GL_INVALID_OPERATION);
2002 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002003 }
2004
2005 es2::Framebuffer *framebuffer = nullptr;
2006 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002007 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002008 {
2009 framebuffer = context->getReadFramebuffer();
2010 framebufferName = context->getReadFramebufferName();
2011 }
2012 else
2013 {
2014 framebuffer = context->getDrawFramebuffer();
2015 framebufferName = context->getDrawFramebufferName();
2016 }
2017
2018 if(framebufferName == 0 || !framebuffer)
2019 {
2020 return error(GL_INVALID_OPERATION);
2021 }
2022
2023 switch(attachment)
2024 {
Nicolas Capens83463112018-06-12 23:55:16 -04002025 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2026 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2027 case GL_DEPTH_STENCIL_ATTACHMENT:
2028 framebuffer->setDepthbuffer(textarget, texture, level);
2029 framebuffer->setStencilbuffer(textarget, texture, level);
2030 break;
2031 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002032 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2033 {
2034 return error(GL_INVALID_ENUM);
2035 }
2036 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2037 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002038 }
2039 }
2040}
2041
2042void FrontFace(GLenum mode)
2043{
2044 TRACE("(GLenum mode = 0x%X)", mode);
2045
2046 switch(mode)
2047 {
2048 case GL_CW:
2049 case GL_CCW:
2050 {
2051 es2::Context *context = es2::getContext();
2052
2053 if(context)
2054 {
2055 context->setFrontFace(mode);
2056 }
2057 }
2058 break;
2059 default:
2060 return error(GL_INVALID_ENUM);
2061 }
2062}
2063
2064void GenBuffers(GLsizei n, GLuint* buffers)
2065{
2066 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2067
2068 if(n < 0)
2069 {
2070 return error(GL_INVALID_VALUE);
2071 }
2072
2073 es2::Context *context = es2::getContext();
2074
2075 if(context)
2076 {
2077 for(int i = 0; i < n; i++)
2078 {
2079 buffers[i] = context->createBuffer();
2080 }
2081 }
2082}
2083
2084void GenerateMipmap(GLenum target)
2085{
2086 TRACE("(GLenum target = 0x%X)", target);
2087
2088 es2::Context *context = es2::getContext();
2089
2090 if(context)
2091 {
2092 es2::Texture *texture = nullptr;
2093
Nicolas Capens0bac2852016-05-07 06:09:58 -04002094 switch(target)
2095 {
2096 case GL_TEXTURE_2D:
2097 texture = context->getTexture2D();
2098 break;
2099 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002100 {
2101 TextureCubeMap *cube = context->getTextureCubeMap();
2102 texture = cube;
2103
2104 if(!cube->isCubeComplete())
2105 {
2106 return error(GL_INVALID_OPERATION);
2107 }
2108 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002109 break;
2110 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002111 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002112 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002113 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002114 texture = context->getTexture3D();
2115 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002116 case GL_TEXTURE_RECTANGLE_ARB:
2117 texture = context->getTexture2DRect();
2118 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002119 default:
2120 return error(GL_INVALID_ENUM);
2121 }
2122
Nicolas Capens83463112018-06-12 23:55:16 -04002123 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002124 {
2125 return error(GL_INVALID_OPERATION);
2126 }
2127
Nicolas Capens0bac2852016-05-07 06:09:58 -04002128 texture->generateMipmaps();
2129 }
2130}
2131
2132void GenFencesNV(GLsizei n, GLuint* fences)
2133{
2134 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2135
2136 if(n < 0)
2137 {
2138 return error(GL_INVALID_VALUE);
2139 }
2140
2141 es2::Context *context = es2::getContext();
2142
2143 if(context)
2144 {
2145 for(int i = 0; i < n; i++)
2146 {
2147 fences[i] = context->createFence();
2148 }
2149 }
2150}
2151
2152void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2153{
2154 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2155
2156 if(n < 0)
2157 {
2158 return error(GL_INVALID_VALUE);
2159 }
2160
2161 es2::Context *context = es2::getContext();
2162
2163 if(context)
2164 {
2165 for(int i = 0; i < n; i++)
2166 {
2167 framebuffers[i] = context->createFramebuffer();
2168 }
2169 }
2170}
2171
2172void GenQueriesEXT(GLsizei n, GLuint* ids)
2173{
2174 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2175
2176 if(n < 0)
2177 {
2178 return error(GL_INVALID_VALUE);
2179 }
2180
2181 es2::Context *context = es2::getContext();
2182
2183 if(context)
2184 {
2185 for(int i = 0; i < n; i++)
2186 {
2187 ids[i] = context->createQuery();
2188 }
2189 }
2190}
2191
2192void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2193{
2194 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2195
2196 if(n < 0)
2197 {
2198 return error(GL_INVALID_VALUE);
2199 }
2200
2201 es2::Context *context = es2::getContext();
2202
2203 if(context)
2204 {
2205 for(int i = 0; i < n; i++)
2206 {
2207 renderbuffers[i] = context->createRenderbuffer();
2208 }
2209 }
2210}
2211
2212void GenTextures(GLsizei n, GLuint* textures)
2213{
2214 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2215
2216 if(n < 0)
2217 {
2218 return error(GL_INVALID_VALUE);
2219 }
2220
2221 es2::Context *context = es2::getContext();
2222
2223 if(context)
2224 {
2225 for(int i = 0; i < n; i++)
2226 {
2227 textures[i] = context->createTexture();
2228 }
2229 }
2230}
2231
2232void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2233{
2234 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2235 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2236 program, index, bufsize, length, size, type, name);
2237
2238 if(bufsize < 0)
2239 {
2240 return error(GL_INVALID_VALUE);
2241 }
2242
2243 es2::Context *context = es2::getContext();
2244
2245 if(context)
2246 {
2247 es2::Program *programObject = context->getProgram(program);
2248
2249 if(!programObject)
2250 {
2251 if(context->getShader(program))
2252 {
2253 return error(GL_INVALID_OPERATION);
2254 }
2255 else
2256 {
2257 return error(GL_INVALID_VALUE);
2258 }
2259 }
2260
2261 if(index >= programObject->getActiveAttributeCount())
2262 {
2263 return error(GL_INVALID_VALUE);
2264 }
2265
2266 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2267 }
2268}
2269
2270void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2271{
2272 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2273 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2274 program, index, bufsize, length, size, type, name);
2275
2276 if(bufsize < 0)
2277 {
2278 return error(GL_INVALID_VALUE);
2279 }
2280
2281 es2::Context *context = es2::getContext();
2282
2283 if(context)
2284 {
2285 es2::Program *programObject = context->getProgram(program);
2286
2287 if(!programObject)
2288 {
2289 if(context->getShader(program))
2290 {
2291 return error(GL_INVALID_OPERATION);
2292 }
2293 else
2294 {
2295 return error(GL_INVALID_VALUE);
2296 }
2297 }
2298
2299 if(index >= programObject->getActiveUniformCount())
2300 {
2301 return error(GL_INVALID_VALUE);
2302 }
2303
2304 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2305 }
2306}
2307
2308void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2309{
2310 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2311 program, maxcount, count, shaders);
2312
2313 if(maxcount < 0)
2314 {
2315 return error(GL_INVALID_VALUE);
2316 }
2317
2318 es2::Context *context = es2::getContext();
2319
2320 if(context)
2321 {
2322 es2::Program *programObject = context->getProgram(program);
2323
2324 if(!programObject)
2325 {
2326 if(context->getShader(program))
2327 {
2328 return error(GL_INVALID_OPERATION);
2329 }
2330 else
2331 {
2332 return error(GL_INVALID_VALUE);
2333 }
2334 }
2335
2336 return programObject->getAttachedShaders(maxcount, count, shaders);
2337 }
2338}
2339
2340int GetAttribLocation(GLuint program, const GLchar* name)
2341{
2342 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2343
2344 es2::Context *context = es2::getContext();
2345
2346 if(context)
2347 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002348 es2::Program *programObject = context->getProgram(program);
2349
2350 if(!programObject)
2351 {
2352 if(context->getShader(program))
2353 {
2354 return error(GL_INVALID_OPERATION, -1);
2355 }
2356 else
2357 {
2358 return error(GL_INVALID_VALUE, -1);
2359 }
2360 }
2361
2362 if(!programObject->isLinked())
2363 {
2364 return error(GL_INVALID_OPERATION, -1);
2365 }
2366
2367 return programObject->getAttributeLocation(name);
2368 }
2369
2370 return -1;
2371}
2372
2373void GetBooleanv(GLenum pname, GLboolean* params)
2374{
2375 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2376
2377 es2::Context *context = es2::getContext();
2378
2379 if(context)
2380 {
2381 if(!(context->getBooleanv(pname, params)))
2382 {
2383 GLenum nativeType;
2384 unsigned int numParams = 0;
2385 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2386 return error(GL_INVALID_ENUM);
2387
2388 if(numParams == 0)
2389 return; // it is known that the pname is valid, but there are no parameters to return
2390
2391 if(nativeType == GL_FLOAT)
2392 {
2393 GLfloat *floatParams = nullptr;
2394 floatParams = new GLfloat[numParams];
2395
2396 context->getFloatv(pname, floatParams);
2397
2398 for(unsigned int i = 0; i < numParams; ++i)
2399 {
2400 if(floatParams[i] == 0.0f)
2401 params[i] = GL_FALSE;
2402 else
2403 params[i] = GL_TRUE;
2404 }
2405
2406 delete [] floatParams;
2407 }
2408 else if(nativeType == GL_INT)
2409 {
2410 GLint *intParams = nullptr;
2411 intParams = new GLint[numParams];
2412
2413 context->getIntegerv(pname, intParams);
2414
2415 for(unsigned int i = 0; i < numParams; ++i)
2416 {
2417 if(intParams[i] == 0)
2418 params[i] = GL_FALSE;
2419 else
2420 params[i] = GL_TRUE;
2421 }
2422
2423 delete [] intParams;
2424 }
2425 }
2426 }
2427}
2428
2429void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2430{
2431 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2432
2433 es2::Context *context = es2::getContext();
2434
2435 if(context)
2436 {
2437 es2::Buffer *buffer;
2438 if(!context->getBuffer(target, &buffer))
2439 {
2440 return error(GL_INVALID_ENUM);
2441 }
2442
2443 if(!buffer)
2444 {
2445 // A null buffer means that "0" is bound to the requested buffer target
2446 return error(GL_INVALID_OPERATION);
2447 }
2448
Nicolas Capens0bac2852016-05-07 06:09:58 -04002449 switch(pname)
2450 {
2451 case GL_BUFFER_USAGE:
2452 *params = buffer->usage();
2453 break;
2454 case GL_BUFFER_SIZE:
2455 *params = (GLint)buffer->size();
2456 break;
2457 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002458 *params = buffer->access();
2459 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002460 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002461 *params = buffer->isMapped();
2462 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002463 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002464 *params = (GLint)buffer->length();
2465 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002466 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002467 *params = (GLint)buffer->offset();
2468 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002469 default:
2470 return error(GL_INVALID_ENUM);
2471 }
2472 }
2473}
2474
2475GLenum GetError(void)
2476{
2477 TRACE("()");
2478
2479 es2::Context *context = es2::getContext();
2480
2481 if(context)
2482 {
2483 return context->getError();
2484 }
2485
2486 return GL_NO_ERROR;
2487}
2488
2489void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2490{
2491 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2492
2493 es2::Context *context = es2::getContext();
2494
2495 if(context)
2496 {
2497 es2::Fence *fenceObject = context->getFence(fence);
2498
2499 if(!fenceObject)
2500 {
2501 return error(GL_INVALID_OPERATION);
2502 }
2503
2504 fenceObject->getFenceiv(pname, params);
2505 }
2506}
2507
2508void GetFloatv(GLenum pname, GLfloat* params)
2509{
2510 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2511
2512 es2::Context *context = es2::getContext();
2513
2514 if(context)
2515 {
2516 if(!(context->getFloatv(pname, params)))
2517 {
2518 GLenum nativeType;
2519 unsigned int numParams = 0;
2520 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2521 return error(GL_INVALID_ENUM);
2522
2523 if(numParams == 0)
2524 return; // it is known that the pname is valid, but that there are no parameters to return.
2525
2526 if(nativeType == GL_BOOL)
2527 {
2528 GLboolean *boolParams = nullptr;
2529 boolParams = new GLboolean[numParams];
2530
2531 context->getBooleanv(pname, boolParams);
2532
2533 for(unsigned int i = 0; i < numParams; ++i)
2534 {
2535 if(boolParams[i] == GL_FALSE)
2536 params[i] = 0.0f;
2537 else
2538 params[i] = 1.0f;
2539 }
2540
2541 delete [] boolParams;
2542 }
2543 else if(nativeType == GL_INT)
2544 {
2545 GLint *intParams = nullptr;
2546 intParams = new GLint[numParams];
2547
2548 context->getIntegerv(pname, intParams);
2549
2550 for(unsigned int i = 0; i < numParams; ++i)
2551 {
2552 params[i] = (GLfloat)intParams[i];
2553 }
2554
2555 delete [] intParams;
2556 }
2557 }
2558 }
2559}
2560
2561void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2562{
2563 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2564 target, attachment, pname, params);
2565
2566 es2::Context *context = es2::getContext();
2567
2568 if(context)
2569 {
2570 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2571 {
2572 return error(GL_INVALID_ENUM);
2573 }
2574
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002575 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002576
Nicolas Capens0bac2852016-05-07 06:09:58 -04002577 if(target == GL_READ_FRAMEBUFFER)
2578 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002579 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002580 }
2581 else
2582 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002583 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002584 }
2585
Nicolas Capens0bac2852016-05-07 06:09:58 -04002586 switch(attachment)
2587 {
2588 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002589 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002590 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002591 if(framebufferName != 0)
2592 {
2593 return error(GL_INVALID_OPERATION);
2594 }
2595 break;
2596 case GL_DEPTH_ATTACHMENT:
2597 case GL_STENCIL_ATTACHMENT:
2598 if(framebufferName == 0)
2599 {
2600 return error(GL_INVALID_OPERATION);
2601 }
2602 break;
2603 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002604 if(framebufferName == 0)
2605 {
2606 return error(GL_INVALID_OPERATION);
2607 }
2608 break;
2609 default:
2610 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2611 {
2612 if(framebufferName == 0)
2613 {
2614 return error(GL_INVALID_OPERATION);
2615 }
2616 }
2617 else return error(GL_INVALID_ENUM);
2618 }
2619
2620 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2621
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002622 if(!framebuffer)
2623 {
2624 return error(GL_INVALID_OPERATION);
2625 }
2626
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002627 GLenum attachmentType;
2628 GLuint attachmentHandle;
2629 GLint attachmentLayer;
2630 Renderbuffer *renderbuffer = nullptr;
2631 switch(attachment)
2632 {
2633 case GL_BACK:
2634 attachmentType = framebuffer->getColorbufferType(0);
2635 attachmentHandle = framebuffer->getColorbufferName(0);
2636 attachmentLayer = framebuffer->getColorbufferLayer(0);
2637 renderbuffer = framebuffer->getColorbuffer(0);
2638 break;
2639 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002640 case GL_DEPTH_ATTACHMENT:
2641 attachmentType = framebuffer->getDepthbufferType();
2642 attachmentHandle = framebuffer->getDepthbufferName();
2643 attachmentLayer = framebuffer->getDepthbufferLayer();
2644 renderbuffer = framebuffer->getDepthbuffer();
2645 break;
2646 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002647 case GL_STENCIL_ATTACHMENT:
2648 attachmentType = framebuffer->getStencilbufferType();
2649 attachmentHandle = framebuffer->getStencilbufferName();
2650 attachmentLayer = framebuffer->getStencilbufferLayer();
2651 renderbuffer = framebuffer->getStencilbuffer();
2652 break;
2653 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002654 attachmentType = framebuffer->getDepthbufferType();
2655 attachmentHandle = framebuffer->getDepthbufferName();
2656 attachmentLayer = framebuffer->getDepthbufferLayer();
2657 renderbuffer = framebuffer->getDepthbuffer();
2658
2659 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002660 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002661 // Different attachments to DEPTH and STENCIL, query fails
2662 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002663 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002664 break;
2665 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002666 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2667 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2668 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2669 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2670 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2671 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002672 }
2673
2674 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002675 if(framebufferName == 0)
2676 {
2677 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2678 }
2679 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002680 {
2681 attachmentObjectType = attachmentType;
2682 }
2683 else if(es2::IsTextureTarget(attachmentType))
2684 {
2685 attachmentObjectType = GL_TEXTURE;
2686 }
2687 else UNREACHABLE(attachmentType);
2688
2689 if(attachmentObjectType != GL_NONE)
2690 {
2691 switch(pname)
2692 {
2693 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2694 *params = attachmentObjectType;
2695 break;
2696 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002697 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002698 {
2699 *params = attachmentHandle;
2700 }
2701 else
2702 {
2703 return error(GL_INVALID_ENUM);
2704 }
2705 break;
2706 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2707 if(attachmentObjectType == GL_TEXTURE)
2708 {
Nicolas Capens83463112018-06-12 23:55:16 -04002709 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002710 }
2711 else
2712 {
2713 return error(GL_INVALID_ENUM);
2714 }
2715 break;
2716 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2717 if(attachmentObjectType == GL_TEXTURE)
2718 {
2719 if(es2::IsCubemapTextureTarget(attachmentType))
2720 {
2721 *params = attachmentType;
2722 }
2723 else
2724 {
2725 *params = 0;
2726 }
2727 }
2728 else
2729 {
2730 return error(GL_INVALID_ENUM);
2731 }
2732 break;
2733 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002734 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002735 break;
2736 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002737 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002738 break;
2739 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002740 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002741 break;
2742 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002743 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002744 break;
2745 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002746 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002747 break;
2748 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002749 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002750 break;
2751 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002752 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002753 break;
2754 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002755 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2756 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002757 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002758 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002759 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002760
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002761 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002762 break;
2763 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002764 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002765 break;
2766 default:
2767 return error(GL_INVALID_ENUM);
2768 }
2769 }
2770 else
2771 {
2772 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2773 // is NONE, then querying any other pname will generate INVALID_ENUM.
2774
2775 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2776 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2777 // INVALID_OPERATION for all other pnames
2778
2779 switch(pname)
2780 {
2781 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2782 *params = GL_NONE;
2783 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002784 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002785 *params = 0;
2786 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002787 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002788 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002789 }
2790 }
2791 }
2792}
2793
2794GLenum GetGraphicsResetStatusEXT(void)
2795{
2796 TRACE("()");
2797
2798 return GL_NO_ERROR;
2799}
2800
2801void GetIntegerv(GLenum pname, GLint* params)
2802{
2803 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2804
2805 es2::Context *context = es2::getContext();
2806
2807 if(!context)
2808 {
2809 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2810 #ifdef __ANDROID__
2811 ALOGI("expected_badness glGetIntegerv() called without current context.");
2812 #else
2813 ERR("glGetIntegerv() called without current context.");
2814 #endif
2815
2816 // This is not spec compliant! When there is no current GL context, functions should
2817 // have no side effects. Google Maps queries these values before creating a context,
2818 // so we need this as a bug-compatible workaround.
2819 switch(pname)
2820 {
2821 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2822 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2823 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2824 case GL_STENCIL_BITS: *params = 8; return;
2825 case GL_ALIASED_LINE_WIDTH_RANGE:
2826 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2827 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2828 return;
2829 }
2830 }
2831
2832 if(context)
2833 {
2834 if(!(context->getIntegerv(pname, params)))
2835 {
2836 GLenum nativeType;
2837 unsigned int numParams = 0;
2838 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2839 return error(GL_INVALID_ENUM);
2840
2841 if(numParams == 0)
2842 return; // it is known that pname is valid, but there are no parameters to return
2843
2844 if(nativeType == GL_BOOL)
2845 {
2846 GLboolean *boolParams = nullptr;
2847 boolParams = new GLboolean[numParams];
2848
2849 context->getBooleanv(pname, boolParams);
2850
2851 for(unsigned int i = 0; i < numParams; ++i)
2852 {
2853 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2854 }
2855
2856 delete [] boolParams;
2857 }
2858 else if(nativeType == GL_FLOAT)
2859 {
2860 GLfloat *floatParams = nullptr;
2861 floatParams = new GLfloat[numParams];
2862
2863 context->getFloatv(pname, floatParams);
2864
2865 for(unsigned int i = 0; i < numParams; ++i)
2866 {
2867 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2868 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002869 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002870 }
2871 else
2872 {
2873 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2874 }
2875 }
2876
2877 delete [] floatParams;
2878 }
2879 }
2880 }
2881}
2882
2883void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2884{
2885 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2886
2887 es2::Context *context = es2::getContext();
2888
2889 if(context)
2890 {
2891 es2::Program *programObject = context->getProgram(program);
2892
2893 if(!programObject)
2894 {
2895 if(context->getShader(program))
2896 {
2897 return error(GL_INVALID_OPERATION);
2898 }
2899 else
2900 {
2901 return error(GL_INVALID_VALUE);
2902 }
2903 }
2904
Nicolas Capens0bac2852016-05-07 06:09:58 -04002905 switch(pname)
2906 {
2907 case GL_DELETE_STATUS:
2908 *params = programObject->isFlaggedForDeletion();
2909 return;
2910 case GL_LINK_STATUS:
2911 *params = programObject->isLinked();
2912 return;
2913 case GL_VALIDATE_STATUS:
2914 *params = programObject->isValidated();
2915 return;
2916 case GL_INFO_LOG_LENGTH:
2917 *params = (GLint)programObject->getInfoLogLength();
2918 return;
2919 case GL_ATTACHED_SHADERS:
2920 *params = programObject->getAttachedShadersCount();
2921 return;
2922 case GL_ACTIVE_ATTRIBUTES:
2923 *params = (GLint)programObject->getActiveAttributeCount();
2924 return;
2925 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2926 *params = programObject->getActiveAttributeMaxLength();
2927 return;
2928 case GL_ACTIVE_UNIFORMS:
2929 *params = (GLint)programObject->getActiveUniformCount();
2930 return;
2931 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2932 *params = programObject->getActiveUniformMaxLength();
2933 return;
2934 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002935 *params = (GLint)programObject->getActiveUniformBlockCount();
2936 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002937 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002938 *params = programObject->getActiveUniformBlockMaxLength();
2939 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002940 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002941 *params = programObject->getTransformFeedbackBufferMode();
2942 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002943 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002944 *params = programObject->getTransformFeedbackVaryingCount();
2945 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002946 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002947 *params = programObject->getTransformFeedbackVaryingMaxLength();
2948 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002949 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002950 *params = programObject->getBinaryRetrievableHint();
2951 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002952 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002953 *params = programObject->getBinaryLength();
2954 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002955 default:
2956 return error(GL_INVALID_ENUM);
2957 }
2958 }
2959}
2960
2961void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2962{
2963 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2964 program, bufsize, length, infolog);
2965
2966 if(bufsize < 0)
2967 {
2968 return error(GL_INVALID_VALUE);
2969 }
2970
2971 es2::Context *context = es2::getContext();
2972
2973 if(context)
2974 {
2975 es2::Program *programObject = context->getProgram(program);
2976
2977 if(!programObject)
2978 {
2979 if(context->getShader(program))
2980 {
2981 return error(GL_INVALID_OPERATION);
2982 }
2983 else
2984 {
2985 return error(GL_INVALID_VALUE);
2986 }
2987 }
2988
2989 programObject->getInfoLog(bufsize, length, infolog);
2990 }
2991}
2992
2993void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2994{
2995 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2996
2997 switch(pname)
2998 {
2999 case GL_CURRENT_QUERY_EXT:
3000 break;
3001 default:
3002 return error(GL_INVALID_ENUM);
3003 }
3004
3005 es2::Context *context = es2::getContext();
3006
3007 if(context)
3008 {
3009 params[0] = context->getActiveQuery(target);
3010 }
3011}
3012
3013void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3014{
3015 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3016
3017 switch(pname)
3018 {
3019 case GL_QUERY_RESULT_EXT:
3020 case GL_QUERY_RESULT_AVAILABLE_EXT:
3021 break;
3022 default:
3023 return error(GL_INVALID_ENUM);
3024 }
3025
3026 es2::Context *context = es2::getContext();
3027
3028 if(context)
3029 {
3030 es2::Query *queryObject = context->getQuery(name);
3031
3032 if(!queryObject)
3033 {
3034 return error(GL_INVALID_OPERATION);
3035 }
3036
3037 if(context->getActiveQuery(queryObject->getType()) == name)
3038 {
3039 return error(GL_INVALID_OPERATION);
3040 }
3041
3042 switch(pname)
3043 {
3044 case GL_QUERY_RESULT_EXT:
3045 params[0] = queryObject->getResult();
3046 break;
3047 case GL_QUERY_RESULT_AVAILABLE_EXT:
3048 params[0] = queryObject->isResultAvailable();
3049 break;
3050 default:
3051 ASSERT(false);
3052 }
3053 }
3054}
3055
3056void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3057{
3058 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3059
3060 es2::Context *context = es2::getContext();
3061
3062 if(context)
3063 {
3064 if(target != GL_RENDERBUFFER)
3065 {
3066 return error(GL_INVALID_ENUM);
3067 }
3068
3069 if(context->getRenderbufferName() == 0)
3070 {
3071 return error(GL_INVALID_OPERATION);
3072 }
3073
3074 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3075
3076 switch(pname)
3077 {
3078 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3079 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003080 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3081 {
3082 GLint internalformat = renderbuffer->getFormat();
3083 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3084 }
3085 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003086 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3087 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3088 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3089 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3090 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3091 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003092 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003093 default:
3094 return error(GL_INVALID_ENUM);
3095 }
3096 }
3097}
3098
3099void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3100{
3101 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3102
3103 es2::Context *context = es2::getContext();
3104
3105 if(context)
3106 {
3107 es2::Shader *shaderObject = context->getShader(shader);
3108
3109 if(!shaderObject)
3110 {
3111 if(context->getProgram(shader))
3112 {
3113 return error(GL_INVALID_OPERATION);
3114 }
3115 else
3116 {
3117 return error(GL_INVALID_VALUE);
3118 }
3119 }
3120
3121 switch(pname)
3122 {
3123 case GL_SHADER_TYPE:
3124 *params = shaderObject->getType();
3125 return;
3126 case GL_DELETE_STATUS:
3127 *params = shaderObject->isFlaggedForDeletion();
3128 return;
3129 case GL_COMPILE_STATUS:
3130 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3131 return;
3132 case GL_INFO_LOG_LENGTH:
3133 *params = (GLint)shaderObject->getInfoLogLength();
3134 return;
3135 case GL_SHADER_SOURCE_LENGTH:
3136 *params = (GLint)shaderObject->getSourceLength();
3137 return;
3138 default:
3139 return error(GL_INVALID_ENUM);
3140 }
3141 }
3142}
3143
3144void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3145{
3146 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3147 shader, bufsize, length, infolog);
3148
3149 if(bufsize < 0)
3150 {
3151 return error(GL_INVALID_VALUE);
3152 }
3153
3154 es2::Context *context = es2::getContext();
3155
3156 if(context)
3157 {
3158 es2::Shader *shaderObject = context->getShader(shader);
3159
3160 if(!shaderObject)
3161 {
3162 if(context->getProgram(shader))
3163 {
3164 return error(GL_INVALID_OPERATION);
3165 }
3166 else
3167 {
3168 return error(GL_INVALID_VALUE);
3169 }
3170 }
3171
3172 shaderObject->getInfoLog(bufsize, length, infolog);
3173 }
3174}
3175
3176void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3177{
3178 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3179 shadertype, precisiontype, range, precision);
3180
3181 switch(shadertype)
3182 {
3183 case GL_VERTEX_SHADER:
3184 case GL_FRAGMENT_SHADER:
3185 break;
3186 default:
3187 return error(GL_INVALID_ENUM);
3188 }
3189
3190 switch(precisiontype)
3191 {
3192 case GL_LOW_FLOAT:
3193 case GL_MEDIUM_FLOAT:
3194 case GL_HIGH_FLOAT:
3195 // IEEE 754 single-precision
3196 range[0] = 127;
3197 range[1] = 127;
3198 *precision = 23;
3199 break;
3200 case GL_LOW_INT:
3201 case GL_MEDIUM_INT:
3202 case GL_HIGH_INT:
3203 // Full integer precision is supported
3204 range[0] = 31;
3205 range[1] = 30;
3206 *precision = 0;
3207 break;
3208 default:
3209 return error(GL_INVALID_ENUM);
3210 }
3211}
3212
3213void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3214{
3215 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3216 shader, bufsize, length, source);
3217
3218 if(bufsize < 0)
3219 {
3220 return error(GL_INVALID_VALUE);
3221 }
3222
3223 es2::Context *context = es2::getContext();
3224
3225 if(context)
3226 {
3227 es2::Shader *shaderObject = context->getShader(shader);
3228
3229 if(!shaderObject)
3230 {
3231 if(context->getProgram(shader))
3232 {
3233 return error(GL_INVALID_OPERATION);
3234 }
3235 else
3236 {
3237 return error(GL_INVALID_VALUE);
3238 }
3239 }
3240
3241 shaderObject->getSource(bufsize, length, source);
3242 }
3243}
3244
3245const GLubyte* GetString(GLenum name)
3246{
3247 TRACE("(GLenum name = 0x%X)", name);
3248
3249 switch(name)
3250 {
3251 case GL_VENDOR:
3252 return (GLubyte*)"Google Inc.";
3253 case GL_RENDERER:
3254 return (GLubyte*)"Google SwiftShader";
3255 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003256 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003257 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003258 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003259 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003260 {
3261 es2::Context *context = es2::getContext();
3262 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3263 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003264 default:
3265 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3266 }
3267}
3268
3269void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3270{
3271 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3272
3273 es2::Context *context = es2::getContext();
3274
3275 if(context)
3276 {
3277 es2::Texture *texture;
3278
Nicolas Capens0bac2852016-05-07 06:09:58 -04003279 switch(target)
3280 {
Nicolas Capens83463112018-06-12 23:55:16 -04003281 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3282 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3283 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3284 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3285 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3286 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003287 default:
3288 return error(GL_INVALID_ENUM);
3289 }
3290
3291 switch(pname)
3292 {
3293 case GL_TEXTURE_MAG_FILTER:
3294 *params = (GLfloat)texture->getMagFilter();
3295 break;
3296 case GL_TEXTURE_MIN_FILTER:
3297 *params = (GLfloat)texture->getMinFilter();
3298 break;
3299 case GL_TEXTURE_WRAP_S:
3300 *params = (GLfloat)texture->getWrapS();
3301 break;
3302 case GL_TEXTURE_WRAP_T:
3303 *params = (GLfloat)texture->getWrapT();
3304 break;
3305 case GL_TEXTURE_WRAP_R_OES:
3306 *params = (GLfloat)texture->getWrapR();
3307 break;
3308 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3309 *params = texture->getMaxAnisotropy();
3310 break;
3311 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3312 *params = (GLfloat)1;
3313 break;
3314 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003315 *params = (GLfloat)texture->getBaseLevel();
3316 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003317 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003318 *params = (GLfloat)texture->getCompareFunc();
3319 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003320 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003321 *params = (GLfloat)texture->getCompareMode();
3322 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003323 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003324 *params = (GLfloat)texture->getImmutableFormat();
3325 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003326 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003327 *params = (GLfloat)texture->getImmutableLevels();
3328 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003329 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003330 *params = (GLfloat)texture->getMaxLevel();
3331 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003332 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003333 *params = texture->getMaxLOD();
3334 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003335 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003336 *params = texture->getMinLOD();
3337 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003338 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003339 *params = (GLfloat)texture->getSwizzleR();
3340 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003341 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003342 *params = (GLfloat)texture->getSwizzleG();
3343 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003344 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003345 *params = (GLfloat)texture->getSwizzleB();
3346 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003347 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003348 *params = (GLfloat)texture->getSwizzleA();
3349 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003350 default:
3351 return error(GL_INVALID_ENUM);
3352 }
3353 }
3354}
3355
3356void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3357{
3358 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3359
3360 es2::Context *context = es2::getContext();
3361
3362 if(context)
3363 {
3364 es2::Texture *texture;
3365
Nicolas Capens0bac2852016-05-07 06:09:58 -04003366 switch(target)
3367 {
Nicolas Capens83463112018-06-12 23:55:16 -04003368 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3369 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3370 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3371 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3372 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3373 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003374 default:
3375 return error(GL_INVALID_ENUM);
3376 }
3377
3378 switch(pname)
3379 {
3380 case GL_TEXTURE_MAG_FILTER:
3381 *params = texture->getMagFilter();
3382 break;
3383 case GL_TEXTURE_MIN_FILTER:
3384 *params = texture->getMinFilter();
3385 break;
3386 case GL_TEXTURE_WRAP_S:
3387 *params = texture->getWrapS();
3388 break;
3389 case GL_TEXTURE_WRAP_T:
3390 *params = texture->getWrapT();
3391 break;
3392 case GL_TEXTURE_WRAP_R_OES:
3393 *params = texture->getWrapR();
3394 break;
3395 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3396 *params = (GLint)texture->getMaxAnisotropy();
3397 break;
3398 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3399 *params = 1;
3400 break;
3401 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003402 *params = texture->getBaseLevel();
3403 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003404 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003405 *params = (GLint)texture->getCompareFunc();
3406 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003407 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003408 *params = (GLint)texture->getCompareMode();
3409 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003410 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003411 *params = (GLint)texture->getImmutableFormat();
3412 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003413 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003414 *params = (GLint)texture->getImmutableLevels();
3415 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003416 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003417 *params = texture->getMaxLevel();
3418 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003419 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003420 *params = (GLint)roundf(texture->getMaxLOD());
3421 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003422 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003423 *params = (GLint)roundf(texture->getMinLOD());
3424 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003425 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003426 *params = (GLint)texture->getSwizzleR();
3427 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003428 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003429 *params = (GLint)texture->getSwizzleG();
3430 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003431 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003432 *params = (GLint)texture->getSwizzleB();
3433 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003434 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003435 *params = (GLint)texture->getSwizzleA();
3436 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003437 default:
3438 return error(GL_INVALID_ENUM);
3439 }
3440 }
3441}
3442
3443void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3444{
3445 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3446 program, location, bufSize, params);
3447
3448 if(bufSize < 0)
3449 {
3450 return error(GL_INVALID_VALUE);
3451 }
3452
3453 es2::Context *context = es2::getContext();
3454
3455 if(context)
3456 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003457 es2::Program *programObject = context->getProgram(program);
3458
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003459 if(!programObject)
3460 {
3461 if(context->getShader(program))
3462 {
3463 return error(GL_INVALID_OPERATION);
3464 }
3465 else
3466 {
3467 return error(GL_INVALID_VALUE);
3468 }
3469 }
3470
3471 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003472 {
3473 return error(GL_INVALID_OPERATION);
3474 }
3475
3476 if(!programObject->getUniformfv(location, &bufSize, params))
3477 {
3478 return error(GL_INVALID_OPERATION);
3479 }
3480 }
3481}
3482
3483void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3484{
3485 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3486
3487 es2::Context *context = es2::getContext();
3488
3489 if(context)
3490 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003491 es2::Program *programObject = context->getProgram(program);
3492
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003493 if(!programObject)
3494 {
3495 if(context->getShader(program))
3496 {
3497 return error(GL_INVALID_OPERATION);
3498 }
3499 else
3500 {
3501 return error(GL_INVALID_VALUE);
3502 }
3503 }
3504
3505 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003506 {
3507 return error(GL_INVALID_OPERATION);
3508 }
3509
3510 if(!programObject->getUniformfv(location, nullptr, params))
3511 {
3512 return error(GL_INVALID_OPERATION);
3513 }
3514 }
3515}
3516
3517void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3518{
3519 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3520 program, location, bufSize, params);
3521
3522 if(bufSize < 0)
3523 {
3524 return error(GL_INVALID_VALUE);
3525 }
3526
3527 es2::Context *context = es2::getContext();
3528
3529 if(context)
3530 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003531 es2::Program *programObject = context->getProgram(program);
3532
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003533 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003534 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003535 if(context->getShader(program))
3536 {
3537 return error(GL_INVALID_OPERATION);
3538 }
3539 else
3540 {
3541 return error(GL_INVALID_VALUE);
3542 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003543 }
3544
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003545 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003546 {
3547 return error(GL_INVALID_OPERATION);
3548 }
3549
3550 if(!programObject->getUniformiv(location, &bufSize, params))
3551 {
3552 return error(GL_INVALID_OPERATION);
3553 }
3554 }
3555}
3556
3557void GetUniformiv(GLuint program, GLint location, GLint* params)
3558{
3559 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3560
3561 es2::Context *context = es2::getContext();
3562
3563 if(context)
3564 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003565 es2::Program *programObject = context->getProgram(program);
3566
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003567 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003568 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003569 if(context->getShader(program))
3570 {
3571 return error(GL_INVALID_OPERATION);
3572 }
3573 else
3574 {
3575 return error(GL_INVALID_VALUE);
3576 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003577 }
3578
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003579 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003580 {
3581 return error(GL_INVALID_OPERATION);
3582 }
3583
3584 if(!programObject->getUniformiv(location, nullptr, params))
3585 {
3586 return error(GL_INVALID_OPERATION);
3587 }
3588 }
3589}
3590
3591int GetUniformLocation(GLuint program, const GLchar* name)
3592{
3593 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3594
3595 es2::Context *context = es2::getContext();
3596
3597 if(strstr(name, "gl_") == name)
3598 {
3599 return -1;
3600 }
3601
3602 if(context)
3603 {
3604 es2::Program *programObject = context->getProgram(program);
3605
3606 if(!programObject)
3607 {
3608 if(context->getShader(program))
3609 {
3610 return error(GL_INVALID_OPERATION, -1);
3611 }
3612 else
3613 {
3614 return error(GL_INVALID_VALUE, -1);
3615 }
3616 }
3617
3618 if(!programObject->isLinked())
3619 {
3620 return error(GL_INVALID_OPERATION, -1);
3621 }
3622
3623 return programObject->getUniformLocation(name);
3624 }
3625
3626 return -1;
3627}
3628
3629void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3630{
3631 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3632
3633 es2::Context *context = es2::getContext();
3634
3635 if(context)
3636 {
3637 if(index >= es2::MAX_VERTEX_ATTRIBS)
3638 {
3639 return error(GL_INVALID_VALUE);
3640 }
3641
3642 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3643
Nicolas Capens0bac2852016-05-07 06:09:58 -04003644 switch(pname)
3645 {
3646 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3647 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3648 break;
3649 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3650 *params = (GLfloat)attribState.mSize;
3651 break;
3652 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3653 *params = (GLfloat)attribState.mStride;
3654 break;
3655 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3656 *params = (GLfloat)attribState.mType;
3657 break;
3658 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3659 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3660 break;
3661 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3662 *params = (GLfloat)attribState.mBoundBuffer.name();
3663 break;
3664 case GL_CURRENT_VERTEX_ATTRIB:
3665 {
3666 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3667 for(int i = 0; i < 4; ++i)
3668 {
3669 params[i] = attrib.getCurrentValueF(i);
3670 }
3671 }
3672 break;
3673 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003674 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3675 break;
3676 default:
3677 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003678 }
3679 }
3680}
3681
3682void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3683{
3684 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3685
3686 es2::Context *context = es2::getContext();
3687
3688 if(context)
3689 {
3690 if(index >= es2::MAX_VERTEX_ATTRIBS)
3691 {
3692 return error(GL_INVALID_VALUE);
3693 }
3694
3695 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3696
Nicolas Capens0bac2852016-05-07 06:09:58 -04003697 switch(pname)
3698 {
3699 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3700 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3701 break;
3702 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3703 *params = attribState.mSize;
3704 break;
3705 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3706 *params = attribState.mStride;
3707 break;
3708 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3709 *params = attribState.mType;
3710 break;
3711 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3712 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3713 break;
3714 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3715 *params = attribState.mBoundBuffer.name();
3716 break;
3717 case GL_CURRENT_VERTEX_ATTRIB:
3718 {
3719 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3720 for(int i = 0; i < 4; ++i)
3721 {
3722 float currentValue = attrib.getCurrentValueF(i);
3723 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3724 }
3725 }
3726 break;
3727 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003728 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3729 break;
3730 default:
3731 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003732 }
3733 }
3734}
3735
3736void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3737{
3738 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3739
3740 es2::Context *context = es2::getContext();
3741
3742 if(context)
3743 {
3744 if(index >= es2::MAX_VERTEX_ATTRIBS)
3745 {
3746 return error(GL_INVALID_VALUE);
3747 }
3748
3749 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3750 {
3751 return error(GL_INVALID_ENUM);
3752 }
3753
3754 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3755 }
3756}
3757
3758void Hint(GLenum target, GLenum mode)
3759{
3760 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3761
3762 switch(mode)
3763 {
3764 case GL_FASTEST:
3765 case GL_NICEST:
3766 case GL_DONT_CARE:
3767 break;
3768 default:
3769 return error(GL_INVALID_ENUM);
3770 }
3771
3772 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003773
3774 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003775 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003776 switch(target)
3777 {
3778 case GL_GENERATE_MIPMAP_HINT:
3779 context->setGenerateMipmapHint(mode);
3780 break;
3781 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3782 context->setFragmentShaderDerivativeHint(mode);
3783 break;
3784 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3785 context->setTextureFilteringHint(mode);
3786 break;
3787 default:
3788 return error(GL_INVALID_ENUM);
3789 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003790 }
3791}
3792
3793GLboolean IsBuffer(GLuint buffer)
3794{
3795 TRACE("(GLuint buffer = %d)", buffer);
3796
3797 es2::Context *context = es2::getContext();
3798
3799 if(context && buffer)
3800 {
3801 es2::Buffer *bufferObject = context->getBuffer(buffer);
3802
3803 if(bufferObject)
3804 {
3805 return GL_TRUE;
3806 }
3807 }
3808
3809 return GL_FALSE;
3810}
3811
3812GLboolean IsEnabled(GLenum cap)
3813{
3814 TRACE("(GLenum cap = 0x%X)", cap);
3815
3816 es2::Context *context = es2::getContext();
3817
3818 if(context)
3819 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003820 switch(cap)
3821 {
3822 case GL_CULL_FACE: return context->isCullFaceEnabled();
3823 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3824 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3825 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3826 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3827 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3828 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3829 case GL_BLEND: return context->isBlendEnabled();
3830 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003831 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3832 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003833 default:
3834 return error(GL_INVALID_ENUM, false);
3835 }
3836 }
3837
3838 return false;
3839}
3840
3841GLboolean IsFenceNV(GLuint fence)
3842{
3843 TRACE("(GLuint fence = %d)", fence);
3844
3845 es2::Context *context = es2::getContext();
3846
3847 if(context)
3848 {
3849 es2::Fence *fenceObject = context->getFence(fence);
3850
3851 if(!fenceObject)
3852 {
3853 return GL_FALSE;
3854 }
3855
3856 return fenceObject->isFence();
3857 }
3858
3859 return GL_FALSE;
3860}
3861
3862GLboolean IsFramebuffer(GLuint framebuffer)
3863{
3864 TRACE("(GLuint framebuffer = %d)", framebuffer);
3865
3866 es2::Context *context = es2::getContext();
3867
3868 if(context && framebuffer)
3869 {
3870 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3871
3872 if(framebufferObject)
3873 {
3874 return GL_TRUE;
3875 }
3876 }
3877
3878 return GL_FALSE;
3879}
3880
3881GLboolean IsProgram(GLuint program)
3882{
3883 TRACE("(GLuint program = %d)", program);
3884
3885 es2::Context *context = es2::getContext();
3886
3887 if(context && program)
3888 {
3889 es2::Program *programObject = context->getProgram(program);
3890
3891 if(programObject)
3892 {
3893 return GL_TRUE;
3894 }
3895 }
3896
3897 return GL_FALSE;
3898}
3899
3900GLboolean IsQueryEXT(GLuint name)
3901{
3902 TRACE("(GLuint name = %d)", name);
3903
3904 if(name == 0)
3905 {
3906 return GL_FALSE;
3907 }
3908
3909 es2::Context *context = es2::getContext();
3910
3911 if(context)
3912 {
3913 es2::Query *queryObject = context->getQuery(name);
3914
3915 if(queryObject)
3916 {
3917 return GL_TRUE;
3918 }
3919 }
3920
3921 return GL_FALSE;
3922}
3923
3924GLboolean IsRenderbuffer(GLuint renderbuffer)
3925{
3926 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3927
3928 es2::Context *context = es2::getContext();
3929
3930 if(context && renderbuffer)
3931 {
3932 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3933
3934 if(renderbufferObject)
3935 {
3936 return GL_TRUE;
3937 }
3938 }
3939
3940 return GL_FALSE;
3941}
3942
3943GLboolean IsShader(GLuint shader)
3944{
3945 TRACE("(GLuint shader = %d)", shader);
3946
3947 es2::Context *context = es2::getContext();
3948
3949 if(context && shader)
3950 {
3951 es2::Shader *shaderObject = context->getShader(shader);
3952
3953 if(shaderObject)
3954 {
3955 return GL_TRUE;
3956 }
3957 }
3958
3959 return GL_FALSE;
3960}
3961
3962GLboolean IsTexture(GLuint texture)
3963{
3964 TRACE("(GLuint texture = %d)", texture);
3965
3966 es2::Context *context = es2::getContext();
3967
3968 if(context && texture)
3969 {
3970 es2::Texture *textureObject = context->getTexture(texture);
3971
3972 if(textureObject)
3973 {
3974 return GL_TRUE;
3975 }
3976 }
3977
3978 return GL_FALSE;
3979}
3980
3981void LineWidth(GLfloat width)
3982{
3983 TRACE("(GLfloat width = %f)", width);
3984
3985 if(width <= 0.0f)
3986 {
3987 return error(GL_INVALID_VALUE);
3988 }
3989
3990 es2::Context *context = es2::getContext();
3991
3992 if(context)
3993 {
3994 context->setLineWidth(width);
3995 }
3996}
3997
3998void LinkProgram(GLuint program)
3999{
4000 TRACE("(GLuint program = %d)", program);
4001
4002 es2::Context *context = es2::getContext();
4003
4004 if(context)
4005 {
4006 es2::Program *programObject = context->getProgram(program);
4007
4008 if(!programObject)
4009 {
4010 if(context->getShader(program))
4011 {
4012 return error(GL_INVALID_OPERATION);
4013 }
4014 else
4015 {
4016 return error(GL_INVALID_VALUE);
4017 }
4018 }
4019
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004020 if(programObject == context->getCurrentProgram())
4021 {
4022 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4023 if(transformFeedback && transformFeedback->isActive())
4024 {
4025 return error(GL_INVALID_OPERATION);
4026 }
4027 }
4028
Nicolas Capens0bac2852016-05-07 06:09:58 -04004029 programObject->link();
4030 }
4031}
4032
4033void PixelStorei(GLenum pname, GLint param)
4034{
4035 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4036
4037 es2::Context *context = es2::getContext();
4038
4039 if(context)
4040 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004041 switch(pname)
4042 {
4043 case GL_UNPACK_ALIGNMENT:
4044 if(param != 1 && param != 2 && param != 4 && param != 8)
4045 {
4046 return error(GL_INVALID_VALUE);
4047 }
4048 context->setUnpackAlignment(param);
4049 break;
4050 case GL_PACK_ALIGNMENT:
4051 if(param != 1 && param != 2 && param != 4 && param != 8)
4052 {
4053 return error(GL_INVALID_VALUE);
4054 }
4055 context->setPackAlignment(param);
4056 break;
4057 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004058 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004059 {
Nicolas Capens83463112018-06-12 23:55:16 -04004060 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004061 }
Nicolas Capens83463112018-06-12 23:55:16 -04004062 context->setPackRowLength(param);
4063 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004065 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004066 {
Nicolas Capens83463112018-06-12 23:55:16 -04004067 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004068 }
Nicolas Capens83463112018-06-12 23:55:16 -04004069 context->setPackSkipPixels(param);
4070 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004072 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004073 {
Nicolas Capens83463112018-06-12 23:55:16 -04004074 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004075 }
Nicolas Capens83463112018-06-12 23:55:16 -04004076 context->setPackSkipRows(param);
4077 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004079 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004080 {
Nicolas Capens83463112018-06-12 23:55:16 -04004081 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004082 }
Nicolas Capens83463112018-06-12 23:55:16 -04004083 context->setUnpackRowLength(param);
4084 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004086 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004087 {
Nicolas Capens83463112018-06-12 23:55:16 -04004088 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004089 }
Nicolas Capens83463112018-06-12 23:55:16 -04004090 context->setUnpackImageHeight(param);
4091 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004093 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004094 {
Nicolas Capens83463112018-06-12 23:55:16 -04004095 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004096 }
Nicolas Capens83463112018-06-12 23:55:16 -04004097 context->setUnpackSkipPixels(param);
4098 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004099 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004100 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004101 {
Nicolas Capens83463112018-06-12 23:55:16 -04004102 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004103 }
Nicolas Capens83463112018-06-12 23:55:16 -04004104 context->setUnpackSkipRows(param);
4105 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004106 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004107 if(param < 0)
4108 {
4109 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004110 }
Nicolas Capens83463112018-06-12 23:55:16 -04004111 context->setUnpackSkipImages(param);
4112 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004113 default:
4114 return error(GL_INVALID_ENUM);
4115 }
4116 }
4117}
4118
4119void PolygonOffset(GLfloat factor, GLfloat units)
4120{
4121 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4122
4123 es2::Context *context = es2::getContext();
4124
4125 if(context)
4126 {
4127 context->setPolygonOffsetParams(factor, units);
4128 }
4129}
4130
4131void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4132 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4133{
4134 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4135 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4136 x, y, width, height, format, type, bufSize, data);
4137
4138 if(width < 0 || height < 0 || bufSize < 0)
4139 {
4140 return error(GL_INVALID_VALUE);
4141 }
4142
4143 es2::Context *context = es2::getContext();
4144
4145 if(context)
4146 {
4147 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4148 }
4149}
4150
4151void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4152{
4153 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4154 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4155 x, y, width, height, format, type, pixels);
4156
4157 if(width < 0 || height < 0)
4158 {
4159 return error(GL_INVALID_VALUE);
4160 }
4161
4162 es2::Context *context = es2::getContext();
4163
4164 if(context)
4165 {
4166 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4167 }
4168}
4169
4170void ReleaseShaderCompiler(void)
4171{
4172 TRACE("()");
4173
4174 es2::Shader::releaseCompiler();
4175}
4176
Nicolas Capens400667e2017-03-29 14:40:14 -04004177void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004178{
4179 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4180 target, samples, internalformat, width, height);
4181
4182 switch(target)
4183 {
4184 case GL_RENDERBUFFER:
4185 break;
4186 default:
4187 return error(GL_INVALID_ENUM);
4188 }
4189
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004190 if(width < 0 || height < 0 || samples < 0 ||
4191 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4192 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004193 {
4194 return error(GL_INVALID_VALUE);
4195 }
4196
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004197 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004198 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004199 {
4200 return error(GL_INVALID_OPERATION);
4201 }
4202
Nicolas Capens0bac2852016-05-07 06:09:58 -04004203 es2::Context *context = es2::getContext();
4204
4205 if(context)
4206 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004207 GLuint handle = context->getRenderbufferName();
4208 if(handle == 0)
4209 {
4210 return error(GL_INVALID_OPERATION);
4211 }
4212
Nicolas Capens83463112018-06-12 23:55:16 -04004213 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004214 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004215 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004216 }
Nicolas Capens83463112018-06-12 23:55:16 -04004217 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004218 {
4219 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4220 }
Nicolas Capens83463112018-06-12 23:55:16 -04004221 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004222 {
4223 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4224 }
Nicolas Capens83463112018-06-12 23:55:16 -04004225 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004226 {
4227 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4228 }
4229 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004230 }
4231}
4232
Nicolas Capens400667e2017-03-29 14:40:14 -04004233void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4234{
4235 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4236}
4237
Nicolas Capens0bac2852016-05-07 06:09:58 -04004238void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4239{
Nicolas Capens400667e2017-03-29 14:40:14 -04004240 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004241}
4242
4243void SampleCoverage(GLclampf value, GLboolean invert)
4244{
4245 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4246
4247 es2::Context* context = es2::getContext();
4248
4249 if(context)
4250 {
4251 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4252 }
4253}
4254
4255void SetFenceNV(GLuint fence, GLenum condition)
4256{
4257 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4258
4259 if(condition != GL_ALL_COMPLETED_NV)
4260 {
4261 return error(GL_INVALID_ENUM);
4262 }
4263
4264 es2::Context *context = es2::getContext();
4265
4266 if(context)
4267 {
4268 es2::Fence *fenceObject = context->getFence(fence);
4269
4270 if(!fenceObject)
4271 {
4272 return error(GL_INVALID_OPERATION);
4273 }
4274
4275 fenceObject->setFence(condition);
4276 }
4277}
4278
4279void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4280{
4281 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4282
4283 if(width < 0 || height < 0)
4284 {
4285 return error(GL_INVALID_VALUE);
4286 }
4287
4288 es2::Context* context = es2::getContext();
4289
4290 if(context)
4291 {
4292 context->setScissorParams(x, y, width, height);
4293 }
4294}
4295
4296void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4297{
4298 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4299 "const GLvoid* binary = %p, GLsizei length = %d)",
4300 n, shaders, binaryformat, binary, length);
4301
4302 // No binary shader formats are supported.
4303 return error(GL_INVALID_ENUM);
4304}
4305
4306void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4307{
4308 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4309 shader, count, string, length);
4310
4311 if(count < 0)
4312 {
4313 return error(GL_INVALID_VALUE);
4314 }
4315
4316 es2::Context *context = es2::getContext();
4317
4318 if(context)
4319 {
4320 es2::Shader *shaderObject = context->getShader(shader);
4321
4322 if(!shaderObject)
4323 {
4324 if(context->getProgram(shader))
4325 {
4326 return error(GL_INVALID_OPERATION);
4327 }
4328 else
4329 {
4330 return error(GL_INVALID_VALUE);
4331 }
4332 }
4333
4334 shaderObject->setSource(count, string, length);
4335 }
4336}
4337
4338void StencilFunc(GLenum func, GLint ref, GLuint mask)
4339{
4340 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4341}
4342
4343void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4344{
4345 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4346
4347 switch(face)
4348 {
4349 case GL_FRONT:
4350 case GL_BACK:
4351 case GL_FRONT_AND_BACK:
4352 break;
4353 default:
4354 return error(GL_INVALID_ENUM);
4355 }
4356
4357 switch(func)
4358 {
4359 case GL_NEVER:
4360 case GL_ALWAYS:
4361 case GL_LESS:
4362 case GL_LEQUAL:
4363 case GL_EQUAL:
4364 case GL_GEQUAL:
4365 case GL_GREATER:
4366 case GL_NOTEQUAL:
4367 break;
4368 default:
4369 return error(GL_INVALID_ENUM);
4370 }
4371
4372 es2::Context *context = es2::getContext();
4373
4374 if(context)
4375 {
4376 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4377 {
4378 context->setStencilParams(func, ref, mask);
4379 }
4380
4381 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4382 {
4383 context->setStencilBackParams(func, ref, mask);
4384 }
4385 }
4386}
4387
4388void StencilMask(GLuint mask)
4389{
4390 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4391}
4392
4393void StencilMaskSeparate(GLenum face, GLuint mask)
4394{
4395 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4396
4397 switch(face)
4398 {
4399 case GL_FRONT:
4400 case GL_BACK:
4401 case GL_FRONT_AND_BACK:
4402 break;
4403 default:
4404 return error(GL_INVALID_ENUM);
4405 }
4406
4407 es2::Context *context = es2::getContext();
4408
4409 if(context)
4410 {
4411 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4412 {
4413 context->setStencilWritemask(mask);
4414 }
4415
4416 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4417 {
4418 context->setStencilBackWritemask(mask);
4419 }
4420 }
4421}
4422
4423void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4424{
4425 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4426}
4427
4428void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4429{
4430 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4431 face, fail, zfail, zpass);
4432
4433 switch(face)
4434 {
4435 case GL_FRONT:
4436 case GL_BACK:
4437 case GL_FRONT_AND_BACK:
4438 break;
4439 default:
4440 return error(GL_INVALID_ENUM);
4441 }
4442
4443 switch(fail)
4444 {
4445 case GL_ZERO:
4446 case GL_KEEP:
4447 case GL_REPLACE:
4448 case GL_INCR:
4449 case GL_DECR:
4450 case GL_INVERT:
4451 case GL_INCR_WRAP:
4452 case GL_DECR_WRAP:
4453 break;
4454 default:
4455 return error(GL_INVALID_ENUM);
4456 }
4457
4458 switch(zfail)
4459 {
4460 case GL_ZERO:
4461 case GL_KEEP:
4462 case GL_REPLACE:
4463 case GL_INCR:
4464 case GL_DECR:
4465 case GL_INVERT:
4466 case GL_INCR_WRAP:
4467 case GL_DECR_WRAP:
4468 break;
4469 default:
4470 return error(GL_INVALID_ENUM);
4471 }
4472
4473 switch(zpass)
4474 {
4475 case GL_ZERO:
4476 case GL_KEEP:
4477 case GL_REPLACE:
4478 case GL_INCR:
4479 case GL_DECR:
4480 case GL_INVERT:
4481 case GL_INCR_WRAP:
4482 case GL_DECR_WRAP:
4483 break;
4484 default:
4485 return error(GL_INVALID_ENUM);
4486 }
4487
4488 es2::Context *context = es2::getContext();
4489
4490 if(context)
4491 {
4492 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4493 {
4494 context->setStencilOperations(fail, zfail, zpass);
4495 }
4496
4497 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4498 {
4499 context->setStencilBackOperations(fail, zfail, zpass);
4500 }
4501 }
4502}
4503
4504GLboolean TestFenceNV(GLuint fence)
4505{
4506 TRACE("(GLuint fence = %d)", fence);
4507
4508 es2::Context *context = es2::getContext();
4509
4510 if(context)
4511 {
4512 es2::Fence *fenceObject = context->getFence(fence);
4513
4514 if(!fenceObject)
4515 {
4516 return error(GL_INVALID_OPERATION, GL_TRUE);
4517 }
4518
4519 return fenceObject->testFence();
4520 }
4521
4522 return GL_TRUE;
4523}
4524
4525void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004526 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004527{
4528 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004529 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4530 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004531
4532 if(!validImageSize(level, width, height))
4533 {
4534 return error(GL_INVALID_VALUE);
4535 }
4536
4537 es2::Context *context = es2::getContext();
4538
4539 if(context)
4540 {
Nicolas Capens83463112018-06-12 23:55:16 -04004541 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004542 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4543 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4544 {
4545 internalformat = GL_BGRA_EXT;
4546 }
4547
Nicolas Capens83463112018-06-12 23:55:16 -04004548 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004549 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004550 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004551 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004552 }
4553
4554 if(border != 0)
4555 {
4556 return error(GL_INVALID_VALUE);
4557 }
4558
4559 switch(target)
4560 {
Alexis Hetu46768622018-01-16 22:09:28 -05004561 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004562 if(level != 0)
4563 {
4564 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4565 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004566 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004567 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004568 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4569 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4570 {
4571 return error(GL_INVALID_VALUE);
4572 }
4573 break;
4574 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4575 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4576 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4577 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4578 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4579 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4580 if(width != height)
4581 {
4582 return error(GL_INVALID_VALUE);
4583 }
4584
4585 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4586 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4587 {
4588 return error(GL_INVALID_VALUE);
4589 }
4590 break;
4591 default:
4592 return error(GL_INVALID_ENUM);
4593 }
4594
Nicolas Capens5555af42017-12-14 13:14:03 -05004595 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004596 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004597 {
4598 return error(validationError);
4599 }
4600
Nicolas Capens894858a2018-03-22 00:55:23 -04004601 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4602
Alexis Hetu46768622018-01-16 22:09:28 -05004603 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004604 {
Alexis Hetu46768622018-01-16 22:09:28 -05004605 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004606
4607 if(!texture)
4608 {
4609 return error(GL_INVALID_OPERATION);
4610 }
4611
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004612 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004613 }
4614 else
4615 {
4616 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4617
4618 if(!texture)
4619 {
4620 return error(GL_INVALID_OPERATION);
4621 }
4622
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004623 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004624 }
4625 }
4626}
4627
4628void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4629{
4630 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4631
4632 es2::Context *context = es2::getContext();
4633
4634 if(context)
4635 {
4636 es2::Texture *texture;
4637
Nicolas Capens0bac2852016-05-07 06:09:58 -04004638 switch(target)
4639 {
Nicolas Capens83463112018-06-12 23:55:16 -04004640 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4641 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4642 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4643 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4644 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4645 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004646 default:
4647 return error(GL_INVALID_ENUM);
4648 }
4649
4650 switch(pname)
4651 {
4652 case GL_TEXTURE_WRAP_S:
4653 if(!texture->setWrapS((GLenum)param))
4654 {
4655 return error(GL_INVALID_ENUM);
4656 }
4657 break;
4658 case GL_TEXTURE_WRAP_T:
4659 if(!texture->setWrapT((GLenum)param))
4660 {
4661 return error(GL_INVALID_ENUM);
4662 }
4663 break;
4664 case GL_TEXTURE_WRAP_R_OES:
4665 if(!texture->setWrapR((GLenum)param))
4666 {
4667 return error(GL_INVALID_ENUM);
4668 }
4669 break;
4670 case GL_TEXTURE_MIN_FILTER:
4671 if(!texture->setMinFilter((GLenum)param))
4672 {
4673 return error(GL_INVALID_ENUM);
4674 }
4675 break;
4676 case GL_TEXTURE_MAG_FILTER:
4677 if(!texture->setMagFilter((GLenum)param))
4678 {
4679 return error(GL_INVALID_ENUM);
4680 }
4681 break;
4682 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4683 if(!texture->setMaxAnisotropy(param))
4684 {
4685 return error(GL_INVALID_VALUE);
4686 }
4687 break;
4688 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004689 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004690 {
4691 return error(GL_INVALID_VALUE);
4692 }
4693 break;
4694 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004695 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004696 {
4697 return error(GL_INVALID_VALUE);
4698 }
4699 break;
4700 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004701 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004702 {
4703 return error(GL_INVALID_VALUE);
4704 }
4705 break;
4706 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004707 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004708 {
4709 return error(GL_INVALID_VALUE);
4710 }
4711 break;
4712 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004713 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004714 {
4715 return error(GL_INVALID_VALUE);
4716 }
4717 break;
4718 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004719 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004720 {
4721 return error(GL_INVALID_VALUE);
4722 }
4723 break;
4724 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004725 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004726 {
4727 return error(GL_INVALID_VALUE);
4728 }
4729 break;
4730 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004731 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004732 {
4733 return error(GL_INVALID_VALUE);
4734 }
4735 break;
4736 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004737 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004738 {
4739 return error(GL_INVALID_VALUE);
4740 }
4741 break;
4742 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004743 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004744 {
4745 return error(GL_INVALID_VALUE);
4746 }
4747 break;
4748 default:
4749 return error(GL_INVALID_ENUM);
4750 }
4751 }
4752}
4753
4754void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4755{
4756 glTexParameterf(target, pname, *params);
4757}
4758
4759void TexParameteri(GLenum target, GLenum pname, GLint param)
4760{
4761 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4762
4763 es2::Context *context = es2::getContext();
4764
4765 if(context)
4766 {
4767 es2::Texture *texture;
4768
Nicolas Capens0bac2852016-05-07 06:09:58 -04004769 switch(target)
4770 {
Nicolas Capens83463112018-06-12 23:55:16 -04004771 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4772 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4773 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4774 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4775 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4776 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004777 default:
4778 return error(GL_INVALID_ENUM);
4779 }
4780
4781 switch(pname)
4782 {
4783 case GL_TEXTURE_WRAP_S:
4784 if(!texture->setWrapS((GLenum)param))
4785 {
4786 return error(GL_INVALID_ENUM);
4787 }
4788 break;
4789 case GL_TEXTURE_WRAP_T:
4790 if(!texture->setWrapT((GLenum)param))
4791 {
4792 return error(GL_INVALID_ENUM);
4793 }
4794 break;
4795 case GL_TEXTURE_WRAP_R_OES:
4796 if(!texture->setWrapR((GLenum)param))
4797 {
4798 return error(GL_INVALID_ENUM);
4799 }
4800 break;
4801 case GL_TEXTURE_MIN_FILTER:
4802 if(!texture->setMinFilter((GLenum)param))
4803 {
4804 return error(GL_INVALID_ENUM);
4805 }
4806 break;
4807 case GL_TEXTURE_MAG_FILTER:
4808 if(!texture->setMagFilter((GLenum)param))
4809 {
4810 return error(GL_INVALID_ENUM);
4811 }
4812 break;
4813 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4814 if(!texture->setMaxAnisotropy((GLfloat)param))
4815 {
4816 return error(GL_INVALID_VALUE);
4817 }
4818 break;
4819 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004820 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4821 {
4822 return error(GL_INVALID_OPERATION); // Base level has to be 0
4823 }
Nicolas Capens83463112018-06-12 23:55:16 -04004824 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004825 {
4826 return error(GL_INVALID_VALUE);
4827 }
4828 break;
4829 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004830 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004831 {
4832 return error(GL_INVALID_VALUE);
4833 }
4834 break;
4835 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004836 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004837 {
4838 return error(GL_INVALID_VALUE);
4839 }
4840 break;
4841 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004842 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004843 {
4844 return error(GL_INVALID_VALUE);
4845 }
4846 break;
4847 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004848 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004849 {
4850 return error(GL_INVALID_VALUE);
4851 }
4852 break;
4853 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004854 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004855 {
4856 return error(GL_INVALID_VALUE);
4857 }
4858 break;
4859 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004860 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004861 {
4862 return error(GL_INVALID_VALUE);
4863 }
4864 break;
4865 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004866 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004867 {
4868 return error(GL_INVALID_VALUE);
4869 }
4870 break;
4871 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004872 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004873 {
4874 return error(GL_INVALID_VALUE);
4875 }
4876 break;
4877 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004878 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004879 {
4880 return error(GL_INVALID_VALUE);
4881 }
4882 break;
4883 default:
4884 return error(GL_INVALID_ENUM);
4885 }
4886 }
4887}
4888
4889void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4890{
4891 glTexParameteri(target, pname, *params);
4892}
4893
4894void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004895 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004896{
4897 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4898 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004899 "const GLvoid* data = %p)",
4900 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004901
4902 if(!es2::IsTextureTarget(target))
4903 {
4904 return error(GL_INVALID_ENUM);
4905 }
4906
4907 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4908 {
4909 return error(GL_INVALID_VALUE);
4910 }
4911
4912 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4913 {
4914 return error(GL_INVALID_VALUE);
4915 }
4916
4917 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4918 {
4919 return error(GL_INVALID_VALUE);
4920 }
4921
Nicolas Capens0bac2852016-05-07 06:09:58 -04004922 es2::Context *context = es2::getContext();
4923
4924 if(context)
4925 {
Alexis Hetu46768622018-01-16 22:09:28 -05004926 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004927 {
Alexis Hetu46768622018-01-16 22:09:28 -05004928 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004929
Nicolas Capens83463112018-06-12 23:55:16 -04004930 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004931 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004932 {
4933 return error(validationError);
4934 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004935
Nicolas Capens5555af42017-12-14 13:14:03 -05004936 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004937 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004938 {
4939 return error(validationError);
4940 }
4941
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004942 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004943 }
4944 else if(es2::IsCubemapTextureTarget(target))
4945 {
4946 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4947
Nicolas Capens83463112018-06-12 23:55:16 -04004948 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004949 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004950 {
4951 return error(validationError);
4952 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004953
Nicolas Capens5555af42017-12-14 13:14:03 -05004954 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004955 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004956 {
4957 return error(validationError);
4958 }
4959
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004960 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004961 }
4962 else UNREACHABLE(target);
4963 }
4964}
4965
4966void Uniform1f(GLint location, GLfloat x)
4967{
4968 glUniform1fv(location, 1, &x);
4969}
4970
4971void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4972{
4973 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4974
4975 if(count < 0)
4976 {
4977 return error(GL_INVALID_VALUE);
4978 }
4979
Nicolas Capens0bac2852016-05-07 06:09:58 -04004980 es2::Context *context = es2::getContext();
4981
4982 if(context)
4983 {
4984 es2::Program *program = context->getCurrentProgram();
4985
4986 if(!program)
4987 {
4988 return error(GL_INVALID_OPERATION);
4989 }
4990
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004991 if(location == -1)
4992 {
4993 return;
4994 }
4995
Nicolas Capens0bac2852016-05-07 06:09:58 -04004996 if(!program->setUniform1fv(location, count, v))
4997 {
4998 return error(GL_INVALID_OPERATION);
4999 }
5000 }
5001}
5002
5003void Uniform1i(GLint location, GLint x)
5004{
5005 glUniform1iv(location, 1, &x);
5006}
5007
5008void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5009{
5010 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5011
5012 if(count < 0)
5013 {
5014 return error(GL_INVALID_VALUE);
5015 }
5016
Nicolas Capens0bac2852016-05-07 06:09:58 -04005017 es2::Context *context = es2::getContext();
5018
5019 if(context)
5020 {
5021 es2::Program *program = context->getCurrentProgram();
5022
5023 if(!program)
5024 {
5025 return error(GL_INVALID_OPERATION);
5026 }
5027
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005028 if(location == -1)
5029 {
5030 return;
5031 }
5032
Nicolas Capens0bac2852016-05-07 06:09:58 -04005033 if(!program->setUniform1iv(location, count, v))
5034 {
5035 return error(GL_INVALID_OPERATION);
5036 }
5037 }
5038}
5039
5040void Uniform2f(GLint location, GLfloat x, GLfloat y)
5041{
5042 GLfloat xy[2] = {x, y};
5043
5044 glUniform2fv(location, 1, (GLfloat*)&xy);
5045}
5046
5047void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5048{
5049 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5050
5051 if(count < 0)
5052 {
5053 return error(GL_INVALID_VALUE);
5054 }
5055
Nicolas Capens0bac2852016-05-07 06:09:58 -04005056 es2::Context *context = es2::getContext();
5057
5058 if(context)
5059 {
5060 es2::Program *program = context->getCurrentProgram();
5061
5062 if(!program)
5063 {
5064 return error(GL_INVALID_OPERATION);
5065 }
5066
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005067 if(location == -1)
5068 {
5069 return;
5070 }
5071
Nicolas Capens0bac2852016-05-07 06:09:58 -04005072 if(!program->setUniform2fv(location, count, v))
5073 {
5074 return error(GL_INVALID_OPERATION);
5075 }
5076 }
5077}
5078
5079void Uniform2i(GLint location, GLint x, GLint y)
5080{
5081 GLint xy[4] = {x, y};
5082
5083 glUniform2iv(location, 1, (GLint*)&xy);
5084}
5085
5086void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5087{
5088 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5089
5090 if(count < 0)
5091 {
5092 return error(GL_INVALID_VALUE);
5093 }
5094
Nicolas Capens0bac2852016-05-07 06:09:58 -04005095 es2::Context *context = es2::getContext();
5096
5097 if(context)
5098 {
5099 es2::Program *program = context->getCurrentProgram();
5100
5101 if(!program)
5102 {
5103 return error(GL_INVALID_OPERATION);
5104 }
5105
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005106 if(location == -1)
5107 {
5108 return;
5109 }
5110
Nicolas Capens0bac2852016-05-07 06:09:58 -04005111 if(!program->setUniform2iv(location, count, v))
5112 {
5113 return error(GL_INVALID_OPERATION);
5114 }
5115 }
5116}
5117
5118void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5119{
5120 GLfloat xyz[3] = {x, y, z};
5121
5122 glUniform3fv(location, 1, (GLfloat*)&xyz);
5123}
5124
5125void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5126{
5127 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5128
5129 if(count < 0)
5130 {
5131 return error(GL_INVALID_VALUE);
5132 }
5133
Nicolas Capens0bac2852016-05-07 06:09:58 -04005134 es2::Context *context = es2::getContext();
5135
5136 if(context)
5137 {
5138 es2::Program *program = context->getCurrentProgram();
5139
5140 if(!program)
5141 {
5142 return error(GL_INVALID_OPERATION);
5143 }
5144
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005145 if(location == -1)
5146 {
5147 return;
5148 }
5149
Nicolas Capens0bac2852016-05-07 06:09:58 -04005150 if(!program->setUniform3fv(location, count, v))
5151 {
5152 return error(GL_INVALID_OPERATION);
5153 }
5154 }
5155}
5156
5157void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5158{
5159 GLint xyz[3] = {x, y, z};
5160
5161 glUniform3iv(location, 1, (GLint*)&xyz);
5162}
5163
5164void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5165{
5166 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5167
5168 if(count < 0)
5169 {
5170 return error(GL_INVALID_VALUE);
5171 }
5172
Nicolas Capens0bac2852016-05-07 06:09:58 -04005173 es2::Context *context = es2::getContext();
5174
5175 if(context)
5176 {
5177 es2::Program *program = context->getCurrentProgram();
5178
5179 if(!program)
5180 {
5181 return error(GL_INVALID_OPERATION);
5182 }
5183
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005184 if(location == -1)
5185 {
5186 return;
5187 }
5188
Nicolas Capens0bac2852016-05-07 06:09:58 -04005189 if(!program->setUniform3iv(location, count, v))
5190 {
5191 return error(GL_INVALID_OPERATION);
5192 }
5193 }
5194}
5195
5196void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5197{
5198 GLfloat xyzw[4] = {x, y, z, w};
5199
5200 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5201}
5202
5203void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5204{
5205 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5206
5207 if(count < 0)
5208 {
5209 return error(GL_INVALID_VALUE);
5210 }
5211
Nicolas Capens0bac2852016-05-07 06:09:58 -04005212 es2::Context *context = es2::getContext();
5213
5214 if(context)
5215 {
5216 es2::Program *program = context->getCurrentProgram();
5217
5218 if(!program)
5219 {
5220 return error(GL_INVALID_OPERATION);
5221 }
5222
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005223 if(location == -1)
5224 {
5225 return;
5226 }
5227
Nicolas Capens0bac2852016-05-07 06:09:58 -04005228 if(!program->setUniform4fv(location, count, v))
5229 {
5230 return error(GL_INVALID_OPERATION);
5231 }
5232 }
5233}
5234
5235void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5236{
5237 GLint xyzw[4] = {x, y, z, w};
5238
5239 glUniform4iv(location, 1, (GLint*)&xyzw);
5240}
5241
5242void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5243{
5244 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5245
5246 if(count < 0)
5247 {
5248 return error(GL_INVALID_VALUE);
5249 }
5250
Nicolas Capens0bac2852016-05-07 06:09:58 -04005251 es2::Context *context = es2::getContext();
5252
5253 if(context)
5254 {
5255 es2::Program *program = context->getCurrentProgram();
5256
5257 if(!program)
5258 {
5259 return error(GL_INVALID_OPERATION);
5260 }
5261
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005262 if(location == -1)
5263 {
5264 return;
5265 }
5266
Nicolas Capens0bac2852016-05-07 06:09:58 -04005267 if(!program->setUniform4iv(location, count, v))
5268 {
5269 return error(GL_INVALID_OPERATION);
5270 }
5271 }
5272}
5273
5274void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5275{
5276 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5277 location, count, transpose, value);
5278
5279 if(count < 0)
5280 {
5281 return error(GL_INVALID_VALUE);
5282 }
5283
Nicolas Capens0bac2852016-05-07 06:09:58 -04005284 es2::Context *context = es2::getContext();
5285
5286 if(context)
5287 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005288 es2::Program *program = context->getCurrentProgram();
5289
5290 if(!program)
5291 {
5292 return error(GL_INVALID_OPERATION);
5293 }
5294
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005295 if(location == -1)
5296 {
5297 return;
5298 }
5299
Nicolas Capens0bac2852016-05-07 06:09:58 -04005300 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5301 {
5302 return error(GL_INVALID_OPERATION);
5303 }
5304 }
5305}
5306
5307void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5308{
5309 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5310 location, count, transpose, value);
5311
5312 if(count < 0)
5313 {
5314 return error(GL_INVALID_VALUE);
5315 }
5316
Nicolas Capens0bac2852016-05-07 06:09:58 -04005317 es2::Context *context = es2::getContext();
5318
5319 if(context)
5320 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005321 es2::Program *program = context->getCurrentProgram();
5322
5323 if(!program)
5324 {
5325 return error(GL_INVALID_OPERATION);
5326 }
5327
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005328 if(location == -1)
5329 {
5330 return;
5331 }
5332
Nicolas Capens0bac2852016-05-07 06:09:58 -04005333 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5334 {
5335 return error(GL_INVALID_OPERATION);
5336 }
5337 }
5338}
5339
5340void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5341{
5342 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5343 location, count, transpose, value);
5344
5345 if(count < 0)
5346 {
5347 return error(GL_INVALID_VALUE);
5348 }
5349
Nicolas Capens0bac2852016-05-07 06:09:58 -04005350 es2::Context *context = es2::getContext();
5351
5352 if(context)
5353 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005354 es2::Program *program = context->getCurrentProgram();
5355
5356 if(!program)
5357 {
5358 return error(GL_INVALID_OPERATION);
5359 }
5360
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005361 if(location == -1)
5362 {
5363 return;
5364 }
5365
Nicolas Capens0bac2852016-05-07 06:09:58 -04005366 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5367 {
5368 return error(GL_INVALID_OPERATION);
5369 }
5370 }
5371}
5372
5373void UseProgram(GLuint program)
5374{
5375 TRACE("(GLuint program = %d)", program);
5376
5377 es2::Context *context = es2::getContext();
5378
5379 if(context)
5380 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005381 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5382 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5383 {
5384 return error(GL_INVALID_OPERATION);
5385 }
5386
Nicolas Capens0bac2852016-05-07 06:09:58 -04005387 es2::Program *programObject = context->getProgram(program);
5388
5389 if(!programObject && program != 0)
5390 {
5391 if(context->getShader(program))
5392 {
5393 return error(GL_INVALID_OPERATION);
5394 }
5395 else
5396 {
5397 return error(GL_INVALID_VALUE);
5398 }
5399 }
5400
5401 if(program != 0 && !programObject->isLinked())
5402 {
5403 return error(GL_INVALID_OPERATION);
5404 }
5405
5406 context->useProgram(program);
5407 }
5408}
5409
5410void ValidateProgram(GLuint program)
5411{
5412 TRACE("(GLuint program = %d)", program);
5413
5414 es2::Context *context = es2::getContext();
5415
5416 if(context)
5417 {
5418 es2::Program *programObject = context->getProgram(program);
5419
5420 if(!programObject)
5421 {
5422 if(context->getShader(program))
5423 {
5424 return error(GL_INVALID_OPERATION);
5425 }
5426 else
5427 {
5428 return error(GL_INVALID_VALUE);
5429 }
5430 }
5431
Ben Vanik1fd3b282017-07-10 14:08:12 -07005432 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005433 }
5434}
5435
5436void VertexAttrib1f(GLuint index, GLfloat x)
5437{
5438 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5439
5440 if(index >= es2::MAX_VERTEX_ATTRIBS)
5441 {
5442 return error(GL_INVALID_VALUE);
5443 }
5444
5445 es2::Context *context = es2::getContext();
5446
5447 if(context)
5448 {
5449 GLfloat vals[4] = { x, 0, 0, 1 };
5450 context->setVertexAttrib(index, vals);
5451 }
5452}
5453
5454void VertexAttrib1fv(GLuint index, const GLfloat* values)
5455{
5456 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5457
5458 if(index >= es2::MAX_VERTEX_ATTRIBS)
5459 {
5460 return error(GL_INVALID_VALUE);
5461 }
5462
5463 es2::Context *context = es2::getContext();
5464
5465 if(context)
5466 {
5467 GLfloat vals[4] = { values[0], 0, 0, 1 };
5468 context->setVertexAttrib(index, vals);
5469 }
5470}
5471
5472void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5473{
5474 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5475
5476 if(index >= es2::MAX_VERTEX_ATTRIBS)
5477 {
5478 return error(GL_INVALID_VALUE);
5479 }
5480
5481 es2::Context *context = es2::getContext();
5482
5483 if(context)
5484 {
5485 GLfloat vals[4] = { x, y, 0, 1 };
5486 context->setVertexAttrib(index, vals);
5487 }
5488}
5489
5490void VertexAttrib2fv(GLuint index, const GLfloat* values)
5491{
5492 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5493
5494 if(index >= es2::MAX_VERTEX_ATTRIBS)
5495 {
5496 return error(GL_INVALID_VALUE);
5497 }
5498
5499 es2::Context *context = es2::getContext();
5500
5501 if(context)
5502 {
5503 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5504 context->setVertexAttrib(index, vals);
5505 }
5506}
5507
5508void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5509{
5510 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5511
5512 if(index >= es2::MAX_VERTEX_ATTRIBS)
5513 {
5514 return error(GL_INVALID_VALUE);
5515 }
5516
5517 es2::Context *context = es2::getContext();
5518
5519 if(context)
5520 {
5521 GLfloat vals[4] = { x, y, z, 1 };
5522 context->setVertexAttrib(index, vals);
5523 }
5524}
5525
5526void VertexAttrib3fv(GLuint index, const GLfloat* values)
5527{
5528 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5529
5530 if(index >= es2::MAX_VERTEX_ATTRIBS)
5531 {
5532 return error(GL_INVALID_VALUE);
5533 }
5534
5535 es2::Context *context = es2::getContext();
5536
5537 if(context)
5538 {
5539 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5540 context->setVertexAttrib(index, vals);
5541 }
5542}
5543
5544void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5545{
5546 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5547
5548 if(index >= es2::MAX_VERTEX_ATTRIBS)
5549 {
5550 return error(GL_INVALID_VALUE);
5551 }
5552
5553 es2::Context *context = es2::getContext();
5554
5555 if(context)
5556 {
5557 GLfloat vals[4] = { x, y, z, w };
5558 context->setVertexAttrib(index, vals);
5559 }
5560}
5561
5562void VertexAttrib4fv(GLuint index, const GLfloat* values)
5563{
5564 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5565
5566 if(index >= es2::MAX_VERTEX_ATTRIBS)
5567 {
5568 return error(GL_INVALID_VALUE);
5569 }
5570
5571 es2::Context *context = es2::getContext();
5572
5573 if(context)
5574 {
5575 context->setVertexAttrib(index, values);
5576 }
5577}
5578
5579void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5580{
5581 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5582 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5583 index, size, type, normalized, stride, ptr);
5584
5585 if(index >= es2::MAX_VERTEX_ATTRIBS)
5586 {
5587 return error(GL_INVALID_VALUE);
5588 }
5589
5590 if(size < 1 || size > 4)
5591 {
5592 return error(GL_INVALID_VALUE);
5593 }
5594
Nicolas Capens0bac2852016-05-07 06:09:58 -04005595 switch(type)
5596 {
5597 case GL_BYTE:
5598 case GL_UNSIGNED_BYTE:
5599 case GL_SHORT:
5600 case GL_UNSIGNED_SHORT:
5601 case GL_FIXED:
5602 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005603 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005604 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005605 break;
5606 case GL_INT_2_10_10_10_REV:
5607 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005608 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005609 {
Nicolas Capens83463112018-06-12 23:55:16 -04005610 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005611 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005612 case GL_INT:
5613 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005614 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005615 default:
5616 return error(GL_INVALID_ENUM);
5617 }
5618
5619 if(stride < 0)
5620 {
5621 return error(GL_INVALID_VALUE);
5622 }
5623
5624 es2::Context *context = es2::getContext();
5625
5626 if(context)
5627 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005628 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5629 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5630 {
5631 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5632 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5633 return error(GL_INVALID_OPERATION);
5634 }
5635
Alexis Hetu6f284032017-12-11 15:19:36 -05005636 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005637 }
5638}
5639
5640void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5641{
5642 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5643
5644 if(width < 0 || height < 0)
5645 {
5646 return error(GL_INVALID_VALUE);
5647 }
5648
5649 es2::Context *context = es2::getContext();
5650
5651 if(context)
5652 {
5653 context->setViewportParams(x, y, width, height);
5654 }
5655}
5656
Alexis Hetub9dda642016-10-06 11:25:32 -04005657static 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 -04005658{
5659 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5660 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5661 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5662 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5663
5664 switch(filter)
5665 {
5666 case GL_NEAREST:
5667 break;
5668 default:
5669 return error(GL_INVALID_ENUM);
5670 }
5671
5672 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5673 {
5674 return error(GL_INVALID_VALUE);
5675 }
5676
5677 es2::Context *context = es2::getContext();
5678
5679 if(context)
5680 {
5681 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5682 {
5683 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5684 return error(GL_INVALID_OPERATION);
5685 }
5686
Alexis Hetub9dda642016-10-06 11:25:32 -04005687 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005688 }
5689}
5690
Alexis Hetub9dda642016-10-06 11:25:32 -04005691void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5692{
5693 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5694}
5695
Nicolas Capens0bac2852016-05-07 06:09:58 -04005696void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5697 GLbitfield mask, GLenum filter)
5698{
5699 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5700 {
5701 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5702 return error(GL_INVALID_OPERATION);
5703 }
5704
Alexis Hetub9dda642016-10-06 11:25:32 -04005705 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005706}
5707
5708void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005709 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005710{
5711 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5712 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005713 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5714 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005715
5716 switch(target)
5717 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005718 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005719 switch(format)
5720 {
5721 case GL_DEPTH_COMPONENT:
5722 case GL_DEPTH_STENCIL_OES:
5723 return error(GL_INVALID_OPERATION);
5724 default:
5725 break;
5726 }
5727 break;
5728 default:
5729 return error(GL_INVALID_ENUM);
5730 }
5731
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005732 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005733 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005734 return error(GL_INVALID_OPERATION);
5735 }
5736
Nicolas Capens83463112018-06-12 23:55:16 -04005737 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005738 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005739 {
5740 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005741 }
5742
5743 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5744 {
5745 return error(GL_INVALID_VALUE);
5746 }
5747
Nicolas Capensefdf1032018-05-08 16:03:16 -04005748 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005749 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5750 {
5751 return error(GL_INVALID_VALUE);
5752 }
5753
5754 if(border != 0)
5755 {
5756 return error(GL_INVALID_VALUE);
5757 }
5758
5759 es2::Context *context = es2::getContext();
5760
5761 if(context)
5762 {
5763 es2::Texture3D *texture = context->getTexture3D();
5764
5765 if(!texture)
5766 {
5767 return error(GL_INVALID_OPERATION);
5768 }
5769
Nicolas Capens2fc90512018-01-23 22:24:22 +00005770 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005771 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005772 {
5773 return error(validationError);
5774 }
5775
Nicolas Capens894858a2018-03-22 00:55:23 -04005776 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005777 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005778 }
5779}
5780
Alexis Hetu53f48092016-06-17 14:08:06 -04005781void 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 -04005782{
5783 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5784 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005785 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5786 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005787
5788 switch(target)
5789 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005790 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005791 break;
5792 default:
5793 return error(GL_INVALID_ENUM);
5794 }
5795
Nicolas Capens0bac2852016-05-07 06:09:58 -04005796 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5797 {
5798 return error(GL_INVALID_VALUE);
5799 }
5800
5801 if((width < 0) || (height < 0) || (depth < 0))
5802 {
5803 return error(GL_INVALID_VALUE);
5804 }
5805
5806 es2::Context *context = es2::getContext();
5807
5808 if(context)
5809 {
5810 es2::Texture3D *texture = context->getTexture3D();
5811
Nicolas Capens83463112018-06-12 23:55:16 -04005812 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005813 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005814 {
5815 return error(validationError);
5816 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005817
Nicolas Capens5555af42017-12-14 13:14:03 -05005818 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005819 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005820 {
5821 return error(validationError);
5822 }
5823
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005824 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005825 }
5826}
5827
5828void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5829{
5830 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5831 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5832 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5833
5834 switch(target)
5835 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005836 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005837 break;
5838 default:
5839 return error(GL_INVALID_ENUM);
5840 }
5841
5842 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5843 {
5844 return error(GL_INVALID_VALUE);
5845 }
5846
5847 es2::Context *context = es2::getContext();
5848
5849 if(context)
5850 {
5851 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5852
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005853 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005854 {
5855 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5856 }
5857
5858 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5859
5860 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5861 {
5862 return error(GL_INVALID_OPERATION);
5863 }
5864
5865 es2::Texture3D *texture = context->getTexture3D();
5866
Nicolas Capens83463112018-06-12 23:55:16 -04005867 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 -05005868 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005869 {
5870 return error(validationError);
5871 }
5872
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005873 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005874 }
5875}
5876
5877void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5878{
5879 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5880 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5881 target, level, internalformat, width, height, depth, border, imageSize, data);
5882
5883 switch(target)
5884 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005885 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005886 break;
5887 default:
5888 return error(GL_INVALID_ENUM);
5889 }
5890
5891 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5892 {
5893 return error(GL_INVALID_VALUE);
5894 }
5895
Nicolas Capensefdf1032018-05-08 16:03:16 -04005896 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005897 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5898 {
5899 return error(GL_INVALID_VALUE);
5900 }
5901
Nicolas Capens83463112018-06-12 23:55:16 -04005902 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005903 {
Nicolas Capens03589982018-02-01 17:28:32 -05005904 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005905 }
5906
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005907 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005908 {
5909 return error(GL_INVALID_VALUE);
5910 }
5911
5912 es2::Context *context = es2::getContext();
5913
5914 if(context)
5915 {
5916 es2::Texture3D *texture = context->getTexture3D();
5917
5918 if(!texture)
5919 {
5920 return error(GL_INVALID_OPERATION);
5921 }
5922
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005923 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005924
Nicolas Capense65f5642018-02-26 17:47:06 -05005925 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005926 {
5927 return error(validationError);
5928 }
5929
Nicolas Capens0bac2852016-05-07 06:09:58 -04005930 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5931 }
5932}
5933
5934void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5935{
5936 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5937 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5938 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5939 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5940
5941 switch(target)
5942 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005943 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005944 break;
5945 default:
5946 return error(GL_INVALID_ENUM);
5947 }
5948
5949 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5950 {
5951 return error(GL_INVALID_VALUE);
5952 }
5953
5954 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5955 {
5956 return error(GL_INVALID_VALUE);
5957 }
5958
Nicolas Capens83463112018-06-12 23:55:16 -04005959 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005960 {
Nicolas Capens03589982018-02-01 17:28:32 -05005961 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005962 }
5963
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005964 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005965 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005966 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005967 }
5968
5969 es2::Context *context = es2::getContext();
5970
5971 if(context)
5972 {
5973 es2::Texture3D *texture = context->getTexture3D();
5974
5975 if(!texture)
5976 {
5977 return error(GL_INVALID_OPERATION);
5978 }
5979
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005980 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005981 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005982 {
5983 return error(validationError);
5984 }
5985
5986 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005987 }
5988}
5989
5990void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5991{
5992 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5993 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5994
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005995 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005996 {
5997 return error(GL_INVALID_ENUM);
5998 }
5999
6000 es2::Context *context = es2::getContext();
6001
6002 if(context)
6003 {
6004 if(texture == 0)
6005 {
6006 textarget = GL_NONE;
6007 }
6008 else
6009 {
6010 es2::Texture *tex = context->getTexture(texture);
6011
6012 if(!tex)
6013 {
6014 return error(GL_INVALID_OPERATION);
6015 }
6016
6017 if(tex->isCompressed(textarget, level))
6018 {
6019 return error(GL_INVALID_OPERATION);
6020 }
6021
6022 switch(textarget)
6023 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006024 case GL_TEXTURE_3D:
6025 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006026 {
6027 return error(GL_INVALID_OPERATION);
6028 }
6029 break;
6030 default:
6031 return error(GL_INVALID_ENUM);
6032 }
6033
6034 if(level != 0)
6035 {
6036 return error(GL_INVALID_VALUE);
6037 }
6038 }
6039
6040 es2::Framebuffer *framebuffer = nullptr;
6041 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006042 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006043 {
6044 framebuffer = context->getReadFramebuffer();
6045 framebufferName = context->getReadFramebufferName();
6046 }
6047 else
6048 {
6049 framebuffer = context->getDrawFramebuffer();
6050 framebufferName = context->getDrawFramebufferName();
6051 }
6052
6053 if(framebufferName == 0 || !framebuffer)
6054 {
6055 return error(GL_INVALID_OPERATION);
6056 }
6057
Nicolas Capens0bac2852016-05-07 06:09:58 -04006058 switch(attachment)
6059 {
Nicolas Capens83463112018-06-12 23:55:16 -04006060 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6061 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6062 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006063 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6064 {
6065 return error(GL_INVALID_ENUM);
6066 }
6067 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6068 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006069 }
6070 }
6071}
6072
6073void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6074{
6075 if(egl::getClientVersion() == 1)
6076 {
6077 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6078 }
6079
6080 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6081
6082 switch(target)
6083 {
6084 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006085 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006086 case GL_TEXTURE_EXTERNAL_OES:
6087 break;
6088 default:
6089 return error(GL_INVALID_ENUM);
6090 }
6091
Nicolas Capens0bac2852016-05-07 06:09:58 -04006092 es2::Context *context = es2::getContext();
6093
6094 if(context)
6095 {
Alexis Hetu46768622018-01-16 22:09:28 -05006096 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006097
6098 if(!texture)
6099 {
6100 return error(GL_INVALID_OPERATION);
6101 }
6102
Nicolas Capens58df2f62016-06-07 14:48:56 -04006103 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006104
Nicolas Capens58df2f62016-06-07 14:48:56 -04006105 if(!eglImage)
6106 {
6107 return error(GL_INVALID_OPERATION);
6108 }
6109
6110 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006111 }
6112}
6113
6114void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6115{
6116 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6117
6118 UNIMPLEMENTED();
6119}
6120
6121GLboolean IsRenderbufferOES(GLuint renderbuffer)
6122{
6123 return IsRenderbuffer(renderbuffer);
6124}
6125
6126void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6127{
6128 BindRenderbuffer(target, renderbuffer);
6129}
6130
6131void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6132{
6133 DeleteRenderbuffers(n, renderbuffers);
6134}
6135
6136void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6137{
6138 GenRenderbuffers(n, renderbuffers);
6139}
6140
6141void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6142{
6143 RenderbufferStorage(target, internalformat, width, height);
6144}
6145
6146void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6147{
6148 GetRenderbufferParameteriv(target, pname, params);
6149}
6150
6151GLboolean IsFramebufferOES(GLuint framebuffer)
6152{
6153 return IsFramebuffer(framebuffer);
6154}
6155
6156void BindFramebufferOES(GLenum target, GLuint framebuffer)
6157{
6158 BindFramebuffer(target, framebuffer);
6159}
6160
6161void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6162{
6163 DeleteFramebuffers(n, framebuffers);
6164}
6165
6166void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6167{
6168 GenFramebuffers(n, framebuffers);
6169}
6170
6171GLenum CheckFramebufferStatusOES(GLenum target)
6172{
6173 return CheckFramebufferStatus(target);
6174}
6175
6176void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6177{
6178 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6179}
6180
6181void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6182{
6183 FramebufferTexture2D(target, attachment, textarget, texture, level);
6184}
6185
6186void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6187{
6188 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6189}
6190
6191void GenerateMipmapOES(GLenum target)
6192{
6193 GenerateMipmap(target);
6194}
6195
6196void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6197{
6198 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6199
6200 if(n < 0 || n > MAX_DRAW_BUFFERS)
6201 {
6202 return error(GL_INVALID_VALUE);
6203 }
6204
6205 es2::Context *context = es2::getContext();
6206
6207 if(context)
6208 {
6209 GLuint drawFramebufferName = context->getDrawFramebufferName();
6210
6211 if((drawFramebufferName == 0) && (n != 1))
6212 {
6213 return error(GL_INVALID_OPERATION);
6214 }
6215
6216 for(unsigned int i = 0; i < (unsigned)n; i++)
6217 {
6218 switch(bufs[i])
6219 {
6220 case GL_BACK:
6221 if(drawFramebufferName != 0)
6222 {
6223 return error(GL_INVALID_OPERATION);
6224 }
6225 break;
6226 case GL_NONE:
6227 break;
6228 case GL_COLOR_ATTACHMENT0_EXT:
6229 case GL_COLOR_ATTACHMENT1_EXT:
6230 case GL_COLOR_ATTACHMENT2_EXT:
6231 case GL_COLOR_ATTACHMENT3_EXT:
6232 case GL_COLOR_ATTACHMENT4_EXT:
6233 case GL_COLOR_ATTACHMENT5_EXT:
6234 case GL_COLOR_ATTACHMENT6_EXT:
6235 case GL_COLOR_ATTACHMENT7_EXT:
6236 case GL_COLOR_ATTACHMENT8_EXT:
6237 case GL_COLOR_ATTACHMENT9_EXT:
6238 case GL_COLOR_ATTACHMENT10_EXT:
6239 case GL_COLOR_ATTACHMENT11_EXT:
6240 case GL_COLOR_ATTACHMENT12_EXT:
6241 case GL_COLOR_ATTACHMENT13_EXT:
6242 case GL_COLOR_ATTACHMENT14_EXT:
6243 case GL_COLOR_ATTACHMENT15_EXT:
6244 {
6245 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6246
6247 if(index >= MAX_COLOR_ATTACHMENTS)
6248 {
6249 return error(GL_INVALID_OPERATION);
6250 }
6251
6252 if(index != i)
6253 {
6254 return error(GL_INVALID_OPERATION);
6255 }
6256
6257 if(drawFramebufferName == 0)
6258 {
6259 return error(GL_INVALID_OPERATION);
6260 }
6261 }
6262 break;
6263 default:
6264 return error(GL_INVALID_ENUM);
6265 }
6266 }
6267
6268 context->setFramebufferDrawBuffers(n, bufs);
6269 }
6270}
6271
6272}
6273
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006274extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006275{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006276 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006277 {
6278 const char *name;
6279 __eglMustCastToProperFunctionPointerType address;
6280 };
6281
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006282 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006283 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006284 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6285
6286 FUNCTION(glActiveTexture),
6287 FUNCTION(glAttachShader),
6288 FUNCTION(glBeginQuery),
6289 FUNCTION(glBeginQueryEXT),
6290 FUNCTION(glBeginTransformFeedback),
6291 FUNCTION(glBindAttribLocation),
6292 FUNCTION(glBindBuffer),
6293 FUNCTION(glBindBufferBase),
6294 FUNCTION(glBindBufferRange),
6295 FUNCTION(glBindFramebuffer),
6296 FUNCTION(glBindFramebufferOES),
6297 FUNCTION(glBindRenderbuffer),
6298 FUNCTION(glBindRenderbufferOES),
6299 FUNCTION(glBindSampler),
6300 FUNCTION(glBindTexture),
6301 FUNCTION(glBindTransformFeedback),
6302 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006303 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006304 FUNCTION(glBlendColor),
6305 FUNCTION(glBlendEquation),
6306 FUNCTION(glBlendEquationSeparate),
6307 FUNCTION(glBlendFunc),
6308 FUNCTION(glBlendFuncSeparate),
6309 FUNCTION(glBlitFramebuffer),
6310 FUNCTION(glBlitFramebufferANGLE),
6311 FUNCTION(glBufferData),
6312 FUNCTION(glBufferSubData),
6313 FUNCTION(glCheckFramebufferStatus),
6314 FUNCTION(glCheckFramebufferStatusOES),
6315 FUNCTION(glClear),
6316 FUNCTION(glClearBufferfi),
6317 FUNCTION(glClearBufferfv),
6318 FUNCTION(glClearBufferiv),
6319 FUNCTION(glClearBufferuiv),
6320 FUNCTION(glClearColor),
6321 FUNCTION(glClearDepthf),
6322 FUNCTION(glClearStencil),
6323 FUNCTION(glClientWaitSync),
6324 FUNCTION(glColorMask),
6325 FUNCTION(glCompileShader),
6326 FUNCTION(glCompressedTexImage2D),
6327 FUNCTION(glCompressedTexImage3D),
6328 FUNCTION(glCompressedTexSubImage2D),
6329 FUNCTION(glCompressedTexSubImage3D),
6330 FUNCTION(glCopyBufferSubData),
6331 FUNCTION(glCopyTexImage2D),
6332 FUNCTION(glCopyTexSubImage2D),
6333 FUNCTION(glCopyTexSubImage3D),
6334 FUNCTION(glCreateProgram),
6335 FUNCTION(glCreateShader),
6336 FUNCTION(glCullFace),
6337 FUNCTION(glDeleteBuffers),
6338 FUNCTION(glDeleteFencesNV),
6339 FUNCTION(glDeleteFramebuffers),
6340 FUNCTION(glDeleteFramebuffersOES),
6341 FUNCTION(glDeleteProgram),
6342 FUNCTION(glDeleteQueries),
6343 FUNCTION(glDeleteQueriesEXT),
6344 FUNCTION(glDeleteRenderbuffers),
6345 FUNCTION(glDeleteRenderbuffersOES),
6346 FUNCTION(glDeleteSamplers),
6347 FUNCTION(glDeleteShader),
6348 FUNCTION(glDeleteSync),
6349 FUNCTION(glDeleteTextures),
6350 FUNCTION(glDeleteTransformFeedbacks),
6351 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006352 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006353 FUNCTION(glDepthFunc),
Nicolas Capens659d89e2018-06-22 13:57:37 -04006354 //FUNCTION(DepthFunc),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006355 FUNCTION(glDepthMask),
6356 FUNCTION(glDepthRangef),
6357 FUNCTION(glDetachShader),
6358 FUNCTION(glDisable),
6359 FUNCTION(glDisableVertexAttribArray),
6360 FUNCTION(glDrawArrays),
6361 FUNCTION(glDrawArraysInstanced),
6362 FUNCTION(glDrawBuffers),
6363 FUNCTION(glDrawBuffersEXT),
6364 FUNCTION(glDrawElements),
6365 FUNCTION(glDrawElementsInstanced),
6366 FUNCTION(glDrawRangeElements),
6367 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6368 FUNCTION(glEGLImageTargetTexture2DOES),
6369 FUNCTION(glEnable),
6370 FUNCTION(glEnableVertexAttribArray),
6371 FUNCTION(glEndQuery),
6372 FUNCTION(glEndQueryEXT),
6373 FUNCTION(glEndTransformFeedback),
6374 FUNCTION(glFenceSync),
6375 FUNCTION(glFinish),
6376 FUNCTION(glFinishFenceNV),
6377 FUNCTION(glFlush),
6378 FUNCTION(glFlushMappedBufferRange),
6379 FUNCTION(glFramebufferRenderbuffer),
6380 FUNCTION(glFramebufferRenderbufferOES),
6381 FUNCTION(glFramebufferTexture2D),
6382 FUNCTION(glFramebufferTexture2DOES),
6383 FUNCTION(glFramebufferTextureLayer),
6384 FUNCTION(glFrontFace),
6385 FUNCTION(glGenBuffers),
6386 FUNCTION(glGenFencesNV),
6387 FUNCTION(glGenFramebuffers),
6388 FUNCTION(glGenFramebuffersOES),
6389 FUNCTION(glGenQueries),
6390 FUNCTION(glGenQueriesEXT),
6391 FUNCTION(glGenRenderbuffers),
6392 FUNCTION(glGenRenderbuffersOES),
6393 FUNCTION(glGenSamplers),
6394 FUNCTION(glGenTextures),
6395 FUNCTION(glGenTransformFeedbacks),
6396 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006397 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006398 FUNCTION(glGenerateMipmap),
6399 FUNCTION(glGenerateMipmapOES),
6400 FUNCTION(glGetActiveAttrib),
6401 FUNCTION(glGetActiveUniform),
6402 FUNCTION(glGetActiveUniformBlockName),
6403 FUNCTION(glGetActiveUniformBlockiv),
6404 FUNCTION(glGetActiveUniformsiv),
6405 FUNCTION(glGetAttachedShaders),
6406 FUNCTION(glGetAttribLocation),
6407 FUNCTION(glGetBooleanv),
6408 FUNCTION(glGetBufferParameteri64v),
6409 FUNCTION(glGetBufferParameteriv),
6410 FUNCTION(glGetBufferPointerv),
6411 FUNCTION(glGetError),
6412 FUNCTION(glGetFenceivNV),
6413 FUNCTION(glGetFloatv),
6414 FUNCTION(glGetFragDataLocation),
6415 FUNCTION(glGetFramebufferAttachmentParameteriv),
6416 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6417 FUNCTION(glGetGraphicsResetStatusEXT),
6418 FUNCTION(glGetInteger64i_v),
6419 FUNCTION(glGetInteger64v),
6420 FUNCTION(glGetIntegeri_v),
6421 FUNCTION(glGetIntegerv),
6422 FUNCTION(glGetInternalformativ),
6423 FUNCTION(glGetProgramBinary),
6424 FUNCTION(glGetProgramInfoLog),
6425 FUNCTION(glGetProgramiv),
6426 FUNCTION(glGetQueryObjectuiv),
6427 FUNCTION(glGetQueryObjectuivEXT),
6428 FUNCTION(glGetQueryiv),
6429 FUNCTION(glGetQueryivEXT),
6430 FUNCTION(glGetRenderbufferParameteriv),
6431 FUNCTION(glGetRenderbufferParameterivOES),
6432 FUNCTION(glGetSamplerParameterfv),
6433 FUNCTION(glGetSamplerParameteriv),
6434 FUNCTION(glGetShaderInfoLog),
6435 FUNCTION(glGetShaderPrecisionFormat),
6436 FUNCTION(glGetShaderSource),
6437 FUNCTION(glGetShaderiv),
6438 FUNCTION(glGetString),
6439 FUNCTION(glGetStringi),
6440 FUNCTION(glGetSynciv),
6441 FUNCTION(glGetTexParameterfv),
6442 FUNCTION(glGetTexParameteriv),
6443 FUNCTION(glGetTransformFeedbackVarying),
6444 FUNCTION(glGetUniformBlockIndex),
6445 FUNCTION(glGetUniformIndices),
6446 FUNCTION(glGetUniformLocation),
6447 FUNCTION(glGetUniformfv),
6448 FUNCTION(glGetUniformiv),
6449 FUNCTION(glGetUniformuiv),
6450 FUNCTION(glGetVertexAttribIiv),
6451 FUNCTION(glGetVertexAttribIuiv),
6452 FUNCTION(glGetVertexAttribPointerv),
6453 FUNCTION(glGetVertexAttribfv),
6454 FUNCTION(glGetVertexAttribiv),
6455 FUNCTION(glGetnUniformfvEXT),
6456 FUNCTION(glGetnUniformivEXT),
6457 FUNCTION(glHint),
6458 FUNCTION(glInvalidateFramebuffer),
6459 FUNCTION(glInvalidateSubFramebuffer),
6460 FUNCTION(glIsBuffer),
6461 FUNCTION(glIsEnabled),
6462 FUNCTION(glIsFenceNV),
6463 FUNCTION(glIsFramebuffer),
6464 FUNCTION(glIsFramebufferOES),
6465 FUNCTION(glIsProgram),
6466 FUNCTION(glIsQuery),
6467 FUNCTION(glIsQueryEXT),
6468 FUNCTION(glIsRenderbuffer),
6469 FUNCTION(glIsRenderbufferOES),
6470 FUNCTION(glIsSampler),
6471 FUNCTION(glIsShader),
6472 FUNCTION(glIsSync),
6473 FUNCTION(glIsTexture),
6474 FUNCTION(glIsTransformFeedback),
6475 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006476 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006477 FUNCTION(glLineWidth),
6478 FUNCTION(glLinkProgram),
6479 FUNCTION(glMapBufferRange),
6480 FUNCTION(glPauseTransformFeedback),
6481 FUNCTION(glPixelStorei),
6482 FUNCTION(glPolygonOffset),
6483 FUNCTION(glProgramBinary),
6484 FUNCTION(glProgramParameteri),
6485 FUNCTION(glReadBuffer),
6486 FUNCTION(glReadPixels),
6487 FUNCTION(glReadnPixelsEXT),
6488 FUNCTION(glReleaseShaderCompiler),
6489 FUNCTION(glRenderbufferStorage),
6490 FUNCTION(glRenderbufferStorageMultisample),
6491 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6492 FUNCTION(glRenderbufferStorageOES),
6493 FUNCTION(glResumeTransformFeedback),
6494 FUNCTION(glSampleCoverage),
6495 FUNCTION(glSamplerParameterf),
6496 FUNCTION(glSamplerParameterfv),
6497 FUNCTION(glSamplerParameteri),
6498 FUNCTION(glSamplerParameteriv),
6499 FUNCTION(glScissor),
6500 FUNCTION(glSetFenceNV),
6501 FUNCTION(glShaderBinary),
6502 FUNCTION(glShaderSource),
6503 FUNCTION(glStencilFunc),
6504 FUNCTION(glStencilFuncSeparate),
6505 FUNCTION(glStencilMask),
6506 FUNCTION(glStencilMaskSeparate),
6507 FUNCTION(glStencilOp),
6508 FUNCTION(glStencilOpSeparate),
6509 FUNCTION(glTestFenceNV),
6510 FUNCTION(glTexImage2D),
6511 FUNCTION(glTexImage3D),
6512 FUNCTION(glTexImage3DOES),
6513 FUNCTION(glTexParameterf),
6514 FUNCTION(glTexParameterfv),
6515 FUNCTION(glTexParameteri),
6516 FUNCTION(glTexParameteriv),
6517 FUNCTION(glTexStorage2D),
6518 FUNCTION(glTexStorage3D),
6519 FUNCTION(glTexSubImage2D),
6520 FUNCTION(glTexSubImage3D),
6521 FUNCTION(glTransformFeedbackVaryings),
6522 FUNCTION(glUniform1f),
6523 FUNCTION(glUniform1fv),
6524 FUNCTION(glUniform1i),
6525 FUNCTION(glUniform1iv),
6526 FUNCTION(glUniform1ui),
6527 FUNCTION(glUniform1uiv),
6528 FUNCTION(glUniform2f),
6529 FUNCTION(glUniform2fv),
6530 FUNCTION(glUniform2i),
6531 FUNCTION(glUniform2iv),
6532 FUNCTION(glUniform2ui),
6533 FUNCTION(glUniform2uiv),
6534 FUNCTION(glUniform3f),
6535 FUNCTION(glUniform3fv),
6536 FUNCTION(glUniform3i),
6537 FUNCTION(glUniform3iv),
6538 FUNCTION(glUniform3ui),
6539 FUNCTION(glUniform3uiv),
6540 FUNCTION(glUniform4f),
6541 FUNCTION(glUniform4fv),
6542 FUNCTION(glUniform4i),
6543 FUNCTION(glUniform4iv),
6544 FUNCTION(glUniform4ui),
6545 FUNCTION(glUniform4uiv),
6546 FUNCTION(glUniformBlockBinding),
6547 FUNCTION(glUniformMatrix2fv),
6548 FUNCTION(glUniformMatrix2x3fv),
6549 FUNCTION(glUniformMatrix2x4fv),
6550 FUNCTION(glUniformMatrix3fv),
6551 FUNCTION(glUniformMatrix3x2fv),
6552 FUNCTION(glUniformMatrix3x4fv),
6553 FUNCTION(glUniformMatrix4fv),
6554 FUNCTION(glUniformMatrix4x2fv),
6555 FUNCTION(glUniformMatrix4x3fv),
6556 FUNCTION(glUnmapBuffer),
6557 FUNCTION(glUseProgram),
6558 FUNCTION(glValidateProgram),
6559 FUNCTION(glVertexAttrib1f),
6560 FUNCTION(glVertexAttrib1fv),
6561 FUNCTION(glVertexAttrib2f),
6562 FUNCTION(glVertexAttrib2fv),
6563 FUNCTION(glVertexAttrib3f),
6564 FUNCTION(glVertexAttrib3fv),
6565 FUNCTION(glVertexAttrib4f),
6566 FUNCTION(glVertexAttrib4fv),
6567 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006568 FUNCTION(glVertexAttribDivisorANGLE),
6569 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006570 FUNCTION(glVertexAttribI4i),
6571 FUNCTION(glVertexAttribI4iv),
6572 FUNCTION(glVertexAttribI4ui),
6573 FUNCTION(glVertexAttribI4uiv),
6574 FUNCTION(glVertexAttribIPointer),
6575 FUNCTION(glVertexAttribPointer),
6576 FUNCTION(glViewport),
6577 FUNCTION(glWaitSync),
6578
6579 #undef FUNCTION
6580 };
6581
6582 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6583 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6584
Nicolas Capens48908cb2018-01-08 13:07:14 -05006585 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6586 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6587 #ifndef NDEBUG
6588 for(size_t i = 0; i < numFunctions - 1; i++)
6589 {
6590 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6591 }
6592 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006593
6594 if(procname && strncmp("gl", procname, 2) == 0)
6595 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006596 struct CompareFunctor
6597 {
6598 bool operator()(const Function &a, const Function &b) const
6599 {
6600 return strcmp(a.name, b.name) < 0;
6601 }
6602 };
6603
6604 Function needle;
6605 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006606 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006607
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006608 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006609 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006610 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006611 }
6612 }
6613
6614 return nullptr;
6615}