blob: 7ae8126d13ca357dd8f1cd805ff556504b84459f [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
15
16#include "main.h"
17#include "mathutil.h"
18#include "utilities.h"
19#include "Buffer.h"
20#include "Context.h"
21#include "Fence.h"
22#include "Framebuffer.h"
23#include "Program.h"
24#include "Renderbuffer.h"
25#include "Shader.h"
26#include "Texture.h"
27#include "Query.h"
28#include "TransformFeedback.h"
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -050029#include "VertexArray.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040030#include "common/debug.h"
31#include "Common/Version.h"
32
33#include <GLES2/gl2.h>
34#include <GLES2/gl2ext.h>
35#include <GLES3/gl3.h>
36
Krzysztof Kosińskif919b862018-01-03 23:17:52 +010037#include <algorithm>
Nicolas Capens0bac2852016-05-07 06:09:58 -040038#include <limits>
39
Nicolas Capens58df2f62016-06-07 14:48:56 -040040#ifdef __ANDROID__
Nicolas Capens0bac2852016-05-07 06:09:58 -040041#include <cutils/log.h>
42#endif
43
44namespace es2
45{
46
47static bool validImageSize(GLint level, GLsizei width, GLsizei height)
48{
49 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
50 {
51 return false;
52 }
53
54 return true;
55}
56
Nicolas Capens0bac2852016-05-07 06:09:58 -040057void ActiveTexture(GLenum texture)
58{
59 TRACE("(GLenum texture = 0x%X)", texture);
60
61 es2::Context *context = es2::getContext();
62
63 if(context)
64 {
65 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
66 {
67 return error(GL_INVALID_ENUM);
68 }
69
70 context->setActiveSampler(texture - GL_TEXTURE0);
71 }
72}
73
74void AttachShader(GLuint program, GLuint shader)
75{
76 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
77
78 es2::Context *context = es2::getContext();
79
80 if(context)
81 {
82 es2::Program *programObject = context->getProgram(program);
83 es2::Shader *shaderObject = context->getShader(shader);
84
85 if(!programObject)
86 {
87 if(context->getShader(program))
88 {
89 return error(GL_INVALID_OPERATION);
90 }
91 else
92 {
93 return error(GL_INVALID_VALUE);
94 }
95 }
96
97 if(!shaderObject)
98 {
99 if(context->getProgram(shader))
100 {
101 return error(GL_INVALID_OPERATION);
102 }
103 else
104 {
105 return error(GL_INVALID_VALUE);
106 }
107 }
108
109 if(!programObject->attachShader(shaderObject))
110 {
111 return error(GL_INVALID_OPERATION);
112 }
113 }
114}
115
116void BeginQueryEXT(GLenum target, GLuint name)
117{
118 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
119
120 switch(target)
121 {
122 case GL_ANY_SAMPLES_PASSED_EXT:
123 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
124 break;
125 default:
126 return error(GL_INVALID_ENUM);
127 }
128
129 if(name == 0)
130 {
131 return error(GL_INVALID_OPERATION);
132 }
133
134 es2::Context *context = es2::getContext();
135
136 if(context)
137 {
138 context->beginQuery(target, name);
139 }
140}
141
142void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
143{
144 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
145
146 if(index >= es2::MAX_VERTEX_ATTRIBS)
147 {
148 return error(GL_INVALID_VALUE);
149 }
150
151 es2::Context *context = es2::getContext();
152
153 if(context)
154 {
155 es2::Program *programObject = context->getProgram(program);
156
157 if(!programObject)
158 {
159 if(context->getShader(program))
160 {
161 return error(GL_INVALID_OPERATION);
162 }
163 else
164 {
165 return error(GL_INVALID_VALUE);
166 }
167 }
168
169 if(strncmp(name, "gl_", 3) == 0)
170 {
171 return error(GL_INVALID_OPERATION);
172 }
173
174 programObject->bindAttributeLocation(index, name);
175 }
176}
177
178void BindBuffer(GLenum target, GLuint buffer)
179{
180 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
181
182 es2::Context *context = es2::getContext();
183
184 if(context)
185 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400186 switch(target)
187 {
188 case GL_ARRAY_BUFFER:
189 context->bindArrayBuffer(buffer);
190 return;
191 case GL_ELEMENT_ARRAY_BUFFER:
192 context->bindElementArrayBuffer(buffer);
193 return;
194 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400195 context->bindCopyReadBuffer(buffer);
196 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400197 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400198 context->bindCopyWriteBuffer(buffer);
199 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400201 context->bindPixelPackBuffer(buffer);
202 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400204 context->bindPixelUnpackBuffer(buffer);
205 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400207 context->bindTransformFeedbackBuffer(buffer);
208 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400209 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400210 context->bindGenericUniformBuffer(buffer);
211 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 default:
213 return error(GL_INVALID_ENUM);
214 }
215 }
216}
217
218void BindFramebuffer(GLenum target, GLuint framebuffer)
219{
220 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
221
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000222 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400223 {
224 return error(GL_INVALID_ENUM);
225 }
226
227 es2::Context *context = es2::getContext();
228
229 if(context)
230 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000231 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400232 {
233 context->bindReadFramebuffer(framebuffer);
234 }
235
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000236 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400237 {
238 context->bindDrawFramebuffer(framebuffer);
239 }
240 }
241}
242
243void BindRenderbuffer(GLenum target, GLuint renderbuffer)
244{
245 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
246
247 if(target != GL_RENDERBUFFER)
248 {
249 return error(GL_INVALID_ENUM);
250 }
251
252 es2::Context *context = es2::getContext();
253
254 if(context)
255 {
256 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
257 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
258 // If renderbuffer is not zero, then the resulting renderbuffer object
259 // is a new state vector, initialized with a zero-sized memory buffer.
260 context->bindRenderbuffer(renderbuffer);
261 }
262}
263
264void BindTexture(GLenum target, GLuint texture)
265{
266 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
267
268 es2::Context *context = es2::getContext();
269
270 if(context)
271 {
272 es2::Texture *textureObject = context->getTexture(texture);
273
274 if(textureObject && textureObject->getTarget() != target && texture != 0)
275 {
276 return error(GL_INVALID_OPERATION);
277 }
278
Nicolas Capens0bac2852016-05-07 06:09:58 -0400279 switch(target)
280 {
281 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500282 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400283 break;
284 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500285 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400286 break;
287 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500288 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400289 break;
290 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500291 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400292 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500293 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500294 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500296 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500297 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500298 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400299 default:
300 return error(GL_INVALID_ENUM);
301 }
302 }
303}
304
305void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
306{
307 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
308 red, green, blue, alpha);
309
310 es2::Context* context = es2::getContext();
311
312 if(context)
313 {
314 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
315 }
316}
317
318void BlendEquation(GLenum mode)
319{
320 glBlendEquationSeparate(mode, mode);
321}
322
323void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
324{
325 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
326
327 switch(modeRGB)
328 {
329 case GL_FUNC_ADD:
330 case GL_FUNC_SUBTRACT:
331 case GL_FUNC_REVERSE_SUBTRACT:
332 case GL_MIN_EXT:
333 case GL_MAX_EXT:
334 break;
335 default:
336 return error(GL_INVALID_ENUM);
337 }
338
339 switch(modeAlpha)
340 {
341 case GL_FUNC_ADD:
342 case GL_FUNC_SUBTRACT:
343 case GL_FUNC_REVERSE_SUBTRACT:
344 case GL_MIN_EXT:
345 case GL_MAX_EXT:
346 break;
347 default:
348 return error(GL_INVALID_ENUM);
349 }
350
351 es2::Context *context = es2::getContext();
352
353 if(context)
354 {
355 context->setBlendEquation(modeRGB, modeAlpha);
356 }
357}
358
359void BlendFunc(GLenum sfactor, GLenum dfactor)
360{
361 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
362}
363
364void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
365{
366 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
367 srcRGB, dstRGB, srcAlpha, dstAlpha);
368
Nicolas Capens0bac2852016-05-07 06:09:58 -0400369 switch(srcRGB)
370 {
371 case GL_ZERO:
372 case GL_ONE:
373 case GL_SRC_COLOR:
374 case GL_ONE_MINUS_SRC_COLOR:
375 case GL_DST_COLOR:
376 case GL_ONE_MINUS_DST_COLOR:
377 case GL_SRC_ALPHA:
378 case GL_ONE_MINUS_SRC_ALPHA:
379 case GL_DST_ALPHA:
380 case GL_ONE_MINUS_DST_ALPHA:
381 case GL_CONSTANT_COLOR:
382 case GL_ONE_MINUS_CONSTANT_COLOR:
383 case GL_CONSTANT_ALPHA:
384 case GL_ONE_MINUS_CONSTANT_ALPHA:
385 case GL_SRC_ALPHA_SATURATE:
386 break;
387 default:
388 return error(GL_INVALID_ENUM);
389 }
390
391 switch(dstRGB)
392 {
393 case GL_ZERO:
394 case GL_ONE:
395 case GL_SRC_COLOR:
396 case GL_ONE_MINUS_SRC_COLOR:
397 case GL_DST_COLOR:
398 case GL_ONE_MINUS_DST_COLOR:
399 case GL_SRC_ALPHA:
400 case GL_ONE_MINUS_SRC_ALPHA:
401 case GL_DST_ALPHA:
402 case GL_ONE_MINUS_DST_ALPHA:
403 case GL_CONSTANT_COLOR:
404 case GL_ONE_MINUS_CONSTANT_COLOR:
405 case GL_CONSTANT_ALPHA:
406 case GL_ONE_MINUS_CONSTANT_ALPHA:
407 break;
408 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400409 break;
410 default:
411 return error(GL_INVALID_ENUM);
412 }
413
414 switch(srcAlpha)
415 {
416 case GL_ZERO:
417 case GL_ONE:
418 case GL_SRC_COLOR:
419 case GL_ONE_MINUS_SRC_COLOR:
420 case GL_DST_COLOR:
421 case GL_ONE_MINUS_DST_COLOR:
422 case GL_SRC_ALPHA:
423 case GL_ONE_MINUS_SRC_ALPHA:
424 case GL_DST_ALPHA:
425 case GL_ONE_MINUS_DST_ALPHA:
426 case GL_CONSTANT_COLOR:
427 case GL_ONE_MINUS_CONSTANT_COLOR:
428 case GL_CONSTANT_ALPHA:
429 case GL_ONE_MINUS_CONSTANT_ALPHA:
430 case GL_SRC_ALPHA_SATURATE:
431 break;
432 default:
433 return error(GL_INVALID_ENUM);
434 }
435
436 switch(dstAlpha)
437 {
438 case GL_ZERO:
439 case GL_ONE:
440 case GL_SRC_COLOR:
441 case GL_ONE_MINUS_SRC_COLOR:
442 case GL_DST_COLOR:
443 case GL_ONE_MINUS_DST_COLOR:
444 case GL_SRC_ALPHA:
445 case GL_ONE_MINUS_SRC_ALPHA:
446 case GL_DST_ALPHA:
447 case GL_ONE_MINUS_DST_ALPHA:
448 case GL_CONSTANT_COLOR:
449 case GL_ONE_MINUS_CONSTANT_COLOR:
450 case GL_CONSTANT_ALPHA:
451 case GL_ONE_MINUS_CONSTANT_ALPHA:
452 break;
453 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400454 break;
455 default:
456 return error(GL_INVALID_ENUM);
457 }
458
459 es2::Context *context = es2::getContext();
460
461 if(context)
462 {
463 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
464 }
465}
466
467void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
468{
469 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
470
471 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
472 target, size, data, usage);
473
474 if(size < 0)
475 {
476 return error(GL_INVALID_VALUE);
477 }
478
Nicolas Capens0bac2852016-05-07 06:09:58 -0400479 switch(usage)
480 {
481 case GL_STREAM_DRAW:
482 case GL_STATIC_DRAW:
483 case GL_DYNAMIC_DRAW:
484 break;
485 case GL_STREAM_READ:
486 case GL_STREAM_COPY:
487 case GL_STATIC_READ:
488 case GL_STATIC_COPY:
489 case GL_DYNAMIC_READ:
490 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400491 break;
492 default:
493 return error(GL_INVALID_ENUM);
494 }
495
496 es2::Context *context = es2::getContext();
497
498 if(context)
499 {
500 es2::Buffer *buffer = nullptr;
501 if(!context->getBuffer(target, &buffer))
502 {
503 return error(GL_INVALID_ENUM);
504 }
505
506 if(!buffer)
507 {
508 // A null buffer means that "0" is bound to the requested buffer target
509 return error(GL_INVALID_OPERATION);
510 }
511
512 buffer->bufferData(data, size, usage);
513 }
514}
515
516void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
517{
518 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
519 offset = static_cast<GLint>(offset);
520
521 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
522 target, offset, size, data);
523
524 if(size < 0 || offset < 0)
525 {
526 return error(GL_INVALID_VALUE);
527 }
528
529 es2::Context *context = es2::getContext();
530
531 if(context)
532 {
533 es2::Buffer *buffer = nullptr;
534 if(!context->getBuffer(target, &buffer))
535 {
536 return error(GL_INVALID_ENUM);
537 }
538
539 if(!buffer)
540 {
541 // A null buffer means that "0" is bound to the requested buffer target
542 return error(GL_INVALID_OPERATION);
543 }
544
Alexis Hetu6e864492017-11-14 15:27:00 -0500545 if(buffer->isMapped())
546 {
547 // It is an invalid operation to update an already mapped buffer
548 return error(GL_INVALID_OPERATION);
549 }
550
Nicolas Capens0bac2852016-05-07 06:09:58 -0400551 if((size_t)size + offset > buffer->size())
552 {
553 return error(GL_INVALID_VALUE);
554 }
555
556 buffer->bufferSubData(data, size, offset);
557 }
558}
559
560GLenum CheckFramebufferStatus(GLenum target)
561{
562 TRACE("(GLenum target = 0x%X)", target);
563
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000564 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400565 {
566 return error(GL_INVALID_ENUM, 0);
567 }
568
569 es2::Context *context = es2::getContext();
570
571 if(context)
572 {
573 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000574 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400575 {
576 framebuffer = context->getReadFramebuffer();
577 }
578 else
579 {
580 framebuffer = context->getDrawFramebuffer();
581 }
582
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400583 if(!framebuffer)
584 {
585 return GL_FRAMEBUFFER_UNDEFINED_OES;
586 }
587
Nicolas Capens0bac2852016-05-07 06:09:58 -0400588 return framebuffer->completeness();
589 }
590
591 return 0;
592}
593
594void Clear(GLbitfield mask)
595{
596 TRACE("(GLbitfield mask = %X)", mask);
597
598 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
599 {
600 return error(GL_INVALID_VALUE);
601 }
602
603 es2::Context *context = es2::getContext();
604
605 if(context)
606 {
607 context->clear(mask);
608 }
609}
610
611void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
612{
613 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
614 red, green, blue, alpha);
615
616 es2::Context *context = es2::getContext();
617
618 if(context)
619 {
620 context->setClearColor(red, green, blue, alpha);
621 }
622}
623
624void ClearDepthf(GLclampf depth)
625{
626 TRACE("(GLclampf depth = %f)", depth);
627
628 es2::Context *context = es2::getContext();
629
630 if(context)
631 {
632 context->setClearDepth(depth);
633 }
634}
635
636void ClearStencil(GLint s)
637{
638 TRACE("(GLint s = %d)", s);
639
640 es2::Context *context = es2::getContext();
641
642 if(context)
643 {
644 context->setClearStencil(s);
645 }
646}
647
648void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
649{
650 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
651 red, green, blue, alpha);
652
653 es2::Context *context = es2::getContext();
654
655 if(context)
656 {
657 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
658 }
659}
660
661void CompileShader(GLuint shader)
662{
663 TRACE("(GLuint shader = %d)", shader);
664
665 es2::Context *context = es2::getContext();
666
667 if(context)
668 {
669 es2::Shader *shaderObject = context->getShader(shader);
670
671 if(!shaderObject)
672 {
673 if(context->getProgram(shader))
674 {
675 return error(GL_INVALID_OPERATION);
676 }
677 else
678 {
679 return error(GL_INVALID_VALUE);
680 }
681 }
682
683 shaderObject->compile();
684 }
685}
686
687void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
688 GLint border, GLsizei imageSize, const GLvoid* data)
689{
690 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
691 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
692 target, level, internalformat, width, height, border, imageSize, data);
693
694 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
695 {
696 return error(GL_INVALID_VALUE);
697 }
698
Nicolas Capens83463112018-06-12 23:55:16 -0400699 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400700 {
Nicolas Capens03589982018-02-01 17:28:32 -0500701 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400702 }
703
704 if(border != 0)
705 {
706 return error(GL_INVALID_VALUE);
707 }
708
709 es2::Context *context = es2::getContext();
710
711 if(context)
712 {
713 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
714 {
715 return error(GL_INVALID_VALUE);
716 }
717
718 switch(target)
719 {
720 case GL_TEXTURE_2D:
721 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
722 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
723 {
724 return error(GL_INVALID_VALUE);
725 }
726 break;
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
733 if(width != height)
734 {
735 return error(GL_INVALID_VALUE);
736 }
737
738 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
739 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
740 {
741 return error(GL_INVALID_VALUE);
742 }
743 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500744 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400745 default:
746 return error(GL_INVALID_ENUM);
747 }
748
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500749 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400750 {
751 return error(GL_INVALID_VALUE);
752 }
753
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500754 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500755 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500756 {
757 return error(validationError);
758 }
759
Alexis Hetu46768622018-01-16 22:09:28 -0500760 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400761 {
Alexis Hetu46768622018-01-16 22:09:28 -0500762 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400763
764 if(!texture)
765 {
766 return error(GL_INVALID_OPERATION);
767 }
768
769 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
770 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500771 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400772 {
773 es2::TextureCubeMap *texture = context->getTextureCubeMap();
774
775 if(!texture)
776 {
777 return error(GL_INVALID_OPERATION);
778 }
779
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500780 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400781 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500782 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400783 }
784}
785
786void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
787 GLenum format, GLsizei imageSize, const GLvoid* data)
788{
789 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
790 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
791 "GLsizei imageSize = %d, const GLvoid* data = %p)",
792 target, level, xoffset, yoffset, width, height, format, imageSize, data);
793
794 if(!es2::IsTextureTarget(target))
795 {
796 return error(GL_INVALID_ENUM);
797 }
798
799 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
800 {
801 return error(GL_INVALID_VALUE);
802 }
803
804 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
805 {
806 return error(GL_INVALID_VALUE);
807 }
808
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500809 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400810 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500811 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400812 }
813
814 es2::Context *context = es2::getContext();
815
816 if(context)
817 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400818 if(xoffset % 4 != 0 || yoffset % 4 != 0)
819 {
820 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
821 return error(GL_INVALID_OPERATION);
822 }
823
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500824 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500825 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500826 {
827 return error(validationError);
828 }
829
Alexis Hetu46768622018-01-16 22:09:28 -0500830 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400831 {
Alexis Hetu46768622018-01-16 22:09:28 -0500832 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400833
Nicolas Capens83463112018-06-12 23:55:16 -0400834 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500835 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400836 {
837 return error(validationError);
838 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500839
Nicolas Capenseab70762018-02-06 16:49:36 -0500840 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400841 }
842 else if(es2::IsCubemapTextureTarget(target))
843 {
844 es2::TextureCubeMap *texture = context->getTextureCubeMap();
845
Nicolas Capens83463112018-06-12 23:55:16 -0400846 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500847 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400848 {
849 return error(validationError);
850 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500851
Nicolas Capenseab70762018-02-06 16:49:36 -0500852 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400853 }
854 else UNREACHABLE(target);
855 }
856}
857
858void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
859{
860 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
861 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
862 target, level, internalformat, x, y, width, height, border);
863
864 if(!validImageSize(level, width, height))
865 {
866 return error(GL_INVALID_VALUE);
867 }
868
869 if(border != 0)
870 {
871 return error(GL_INVALID_VALUE);
872 }
873
874 es2::Context *context = es2::getContext();
875
876 if(context)
877 {
878 switch(target)
879 {
Alexis Hetu46768622018-01-16 22:09:28 -0500880 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500881 if(level != 0)
882 {
883 return error(GL_INVALID_VALUE);
884 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400885 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500886 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400887 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
888 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
889 {
890 return error(GL_INVALID_VALUE);
891 }
892 break;
893 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
894 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
895 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
896 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
897 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
898 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
899 if(width != height)
900 {
901 return error(GL_INVALID_VALUE);
902 }
903
904 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
905 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
906 {
907 return error(GL_INVALID_VALUE);
908 }
909 break;
910 default:
911 return error(GL_INVALID_ENUM);
912 }
913
914 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
915
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400916 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400917 {
918 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
919 }
920
921 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
922
923 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
924 {
925 return error(GL_INVALID_OPERATION);
926 }
927
928 GLenum colorbufferFormat = source->getFormat();
929
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500930 // Determine the sized internal format.
931 if(gl::IsUnsizedInternalFormat(internalformat))
932 {
933 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
934 {
935 internalformat = colorbufferFormat;
936 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400937 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500938 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400939 // TODO: Convert to the smallest format that fits all components.
940 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
941
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500942 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
943 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400944 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
945 {
946 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
947 }
948 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
949 {
950 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
951 }
952 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
953 {
954 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
955 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400956 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
957 {
958 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
959 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500960 else
961 {
962 UNIMPLEMENTED();
963
964 return error(GL_INVALID_OPERATION);
965 }
966 }
967
Nicolas Capens8f215a42018-02-02 13:25:53 -0500968 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400969 {
970 return;
971 }
972
Alexis Hetu46768622018-01-16 22:09:28 -0500973 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400974 {
Alexis Hetu46768622018-01-16 22:09:28 -0500975 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400976
977 if(!texture)
978 {
979 return error(GL_INVALID_OPERATION);
980 }
981
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500982 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400983 }
984 else if(es2::IsCubemapTextureTarget(target))
985 {
986 es2::TextureCubeMap *texture = context->getTextureCubeMap();
987
988 if(!texture)
989 {
990 return error(GL_INVALID_OPERATION);
991 }
992
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500993 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400994 }
995 else UNREACHABLE(target);
996 }
997}
998
999void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1000{
1001 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1002 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1003 target, level, xoffset, yoffset, x, y, width, height);
1004
1005 if(!es2::IsTextureTarget(target))
1006 {
1007 return error(GL_INVALID_ENUM);
1008 }
1009
1010 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1011 {
1012 return error(GL_INVALID_VALUE);
1013 }
1014
1015 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1016 {
1017 return error(GL_INVALID_VALUE);
1018 }
1019
1020 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1021 {
1022 return error(GL_INVALID_VALUE);
1023 }
1024
Nicolas Capens0bac2852016-05-07 06:09:58 -04001025 es2::Context *context = es2::getContext();
1026
1027 if(context)
1028 {
1029 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1030
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001031 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001032 {
1033 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1034 }
1035
1036 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1037
1038 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1039 {
1040 return error(GL_INVALID_OPERATION);
1041 }
1042
1043 es2::Texture *texture = nullptr;
1044
Alexis Hetu46768622018-01-16 22:09:28 -05001045 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001046 {
Alexis Hetu46768622018-01-16 22:09:28 -05001047 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001048 }
1049 else if(es2::IsCubemapTextureTarget(target))
1050 {
1051 texture = context->getTextureCubeMap();
1052 }
1053 else UNREACHABLE(target);
1054
Nicolas Capens83463112018-06-12 23:55:16 -04001055 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001056 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001057 {
1058 return error(validationError);
1059 }
1060
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001061 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001062 }
1063}
1064
1065GLuint CreateProgram(void)
1066{
1067 TRACE("()");
1068
1069 es2::Context *context = es2::getContext();
1070
1071 if(context)
1072 {
1073 return context->createProgram();
1074 }
1075
1076 return 0;
1077}
1078
1079GLuint CreateShader(GLenum type)
1080{
1081 TRACE("(GLenum type = 0x%X)", type);
1082
1083 es2::Context *context = es2::getContext();
1084
1085 if(context)
1086 {
1087 switch(type)
1088 {
1089 case GL_FRAGMENT_SHADER:
1090 case GL_VERTEX_SHADER:
1091 return context->createShader(type);
1092 default:
1093 return error(GL_INVALID_ENUM, 0);
1094 }
1095 }
1096
1097 return 0;
1098}
1099
1100void CullFace(GLenum mode)
1101{
1102 TRACE("(GLenum mode = 0x%X)", mode);
1103
1104 switch(mode)
1105 {
1106 case GL_FRONT:
1107 case GL_BACK:
1108 case GL_FRONT_AND_BACK:
1109 {
1110 es2::Context *context = es2::getContext();
1111
1112 if(context)
1113 {
1114 context->setCullMode(mode);
1115 }
1116 }
1117 break;
1118 default:
1119 return error(GL_INVALID_ENUM);
1120 }
1121}
1122
1123void DeleteBuffers(GLsizei n, const GLuint* buffers)
1124{
1125 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1126
1127 if(n < 0)
1128 {
1129 return error(GL_INVALID_VALUE);
1130 }
1131
1132 es2::Context *context = es2::getContext();
1133
1134 if(context)
1135 {
1136 for(int i = 0; i < n; i++)
1137 {
1138 context->deleteBuffer(buffers[i]);
1139 }
1140 }
1141}
1142
1143void DeleteFencesNV(GLsizei n, const GLuint* fences)
1144{
1145 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1146
1147 if(n < 0)
1148 {
1149 return error(GL_INVALID_VALUE);
1150 }
1151
1152 es2::Context *context = es2::getContext();
1153
1154 if(context)
1155 {
1156 for(int i = 0; i < n; i++)
1157 {
1158 context->deleteFence(fences[i]);
1159 }
1160 }
1161}
1162
1163void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1164{
1165 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1166
1167 if(n < 0)
1168 {
1169 return error(GL_INVALID_VALUE);
1170 }
1171
1172 es2::Context *context = es2::getContext();
1173
1174 if(context)
1175 {
1176 for(int i = 0; i < n; i++)
1177 {
1178 if(framebuffers[i] != 0)
1179 {
1180 context->deleteFramebuffer(framebuffers[i]);
1181 }
1182 }
1183 }
1184}
1185
1186void DeleteProgram(GLuint program)
1187{
1188 TRACE("(GLuint program = %d)", program);
1189
1190 if(program == 0)
1191 {
1192 return;
1193 }
1194
1195 es2::Context *context = es2::getContext();
1196
1197 if(context)
1198 {
1199 if(!context->getProgram(program))
1200 {
1201 if(context->getShader(program))
1202 {
1203 return error(GL_INVALID_OPERATION);
1204 }
1205 else
1206 {
1207 return error(GL_INVALID_VALUE);
1208 }
1209 }
1210
1211 context->deleteProgram(program);
1212 }
1213}
1214
1215void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1216{
1217 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1218
1219 if(n < 0)
1220 {
1221 return error(GL_INVALID_VALUE);
1222 }
1223
1224 es2::Context *context = es2::getContext();
1225
1226 if(context)
1227 {
1228 for(int i = 0; i < n; i++)
1229 {
1230 context->deleteQuery(ids[i]);
1231 }
1232 }
1233}
1234
1235void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1236{
1237 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1238
1239 if(n < 0)
1240 {
1241 return error(GL_INVALID_VALUE);
1242 }
1243
1244 es2::Context *context = es2::getContext();
1245
1246 if(context)
1247 {
1248 for(int i = 0; i < n; i++)
1249 {
1250 context->deleteRenderbuffer(renderbuffers[i]);
1251 }
1252 }
1253}
1254
1255void DeleteShader(GLuint shader)
1256{
1257 TRACE("(GLuint shader = %d)", shader);
1258
1259 if(shader == 0)
1260 {
1261 return;
1262 }
1263
1264 es2::Context *context = es2::getContext();
1265
1266 if(context)
1267 {
1268 if(!context->getShader(shader))
1269 {
1270 if(context->getProgram(shader))
1271 {
1272 return error(GL_INVALID_OPERATION);
1273 }
1274 else
1275 {
1276 return error(GL_INVALID_VALUE);
1277 }
1278 }
1279
1280 context->deleteShader(shader);
1281 }
1282}
1283
1284void DeleteTextures(GLsizei n, const GLuint* textures)
1285{
1286 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1287
1288 if(n < 0)
1289 {
1290 return error(GL_INVALID_VALUE);
1291 }
1292
1293 es2::Context *context = es2::getContext();
1294
1295 if(context)
1296 {
1297 for(int i = 0; i < n; i++)
1298 {
1299 if(textures[i] != 0)
1300 {
1301 context->deleteTexture(textures[i]);
1302 }
1303 }
1304 }
1305}
1306
1307void DepthFunc(GLenum func)
1308{
1309 TRACE("(GLenum func = 0x%X)", func);
1310
1311 switch(func)
1312 {
1313 case GL_NEVER:
1314 case GL_ALWAYS:
1315 case GL_LESS:
1316 case GL_LEQUAL:
1317 case GL_EQUAL:
1318 case GL_GREATER:
1319 case GL_GEQUAL:
1320 case GL_NOTEQUAL:
1321 break;
1322 default:
1323 return error(GL_INVALID_ENUM);
1324 }
1325
1326 es2::Context *context = es2::getContext();
1327
1328 if(context)
1329 {
1330 context->setDepthFunc(func);
1331 }
1332}
1333
1334void DepthMask(GLboolean flag)
1335{
1336 TRACE("(GLboolean flag = %d)", flag);
1337
1338 es2::Context *context = es2::getContext();
1339
1340 if(context)
1341 {
1342 context->setDepthMask(flag != GL_FALSE);
1343 }
1344}
1345
1346void DepthRangef(GLclampf zNear, GLclampf zFar)
1347{
1348 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1349
1350 es2::Context *context = es2::getContext();
1351
1352 if(context)
1353 {
1354 context->setDepthRange(zNear, zFar);
1355 }
1356}
1357
1358void DetachShader(GLuint program, GLuint shader)
1359{
1360 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1361
1362 es2::Context *context = es2::getContext();
1363
1364 if(context)
1365 {
1366
1367 es2::Program *programObject = context->getProgram(program);
1368 es2::Shader *shaderObject = context->getShader(shader);
1369
1370 if(!programObject)
1371 {
1372 es2::Shader *shaderByProgramHandle;
1373 shaderByProgramHandle = context->getShader(program);
1374 if(!shaderByProgramHandle)
1375 {
1376 return error(GL_INVALID_VALUE);
1377 }
1378 else
1379 {
1380 return error(GL_INVALID_OPERATION);
1381 }
1382 }
1383
1384 if(!shaderObject)
1385 {
1386 es2::Program *programByShaderHandle = context->getProgram(shader);
1387 if(!programByShaderHandle)
1388 {
1389 return error(GL_INVALID_VALUE);
1390 }
1391 else
1392 {
1393 return error(GL_INVALID_OPERATION);
1394 }
1395 }
1396
1397 if(!programObject->detachShader(shaderObject))
1398 {
1399 return error(GL_INVALID_OPERATION);
1400 }
1401 }
1402}
1403
1404void Disable(GLenum cap)
1405{
1406 TRACE("(GLenum cap = 0x%X)", cap);
1407
1408 es2::Context *context = es2::getContext();
1409
1410 if(context)
1411 {
1412 switch(cap)
1413 {
1414 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1415 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1416 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1417 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1418 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1419 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1420 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1421 case GL_BLEND: context->setBlendEnabled(false); break;
1422 case GL_DITHER: context->setDitherEnabled(false); break;
1423 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1424 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1425 default:
1426 return error(GL_INVALID_ENUM);
1427 }
1428 }
1429}
1430
1431void DisableVertexAttribArray(GLuint index)
1432{
1433 TRACE("(GLuint index = %d)", index);
1434
1435 if(index >= es2::MAX_VERTEX_ATTRIBS)
1436 {
1437 return error(GL_INVALID_VALUE);
1438 }
1439
1440 es2::Context *context = es2::getContext();
1441
1442 if(context)
1443 {
1444 context->setVertexAttribArrayEnabled(index, false);
1445 }
1446}
1447
1448void DrawArrays(GLenum mode, GLint first, GLsizei count)
1449{
1450 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1451
1452 switch(mode)
1453 {
1454 case GL_POINTS:
1455 case GL_LINES:
1456 case GL_LINE_LOOP:
1457 case GL_LINE_STRIP:
1458 case GL_TRIANGLES:
1459 case GL_TRIANGLE_FAN:
1460 case GL_TRIANGLE_STRIP:
1461 break;
1462 default:
1463 return error(GL_INVALID_ENUM);
1464 }
1465
1466 if(count < 0 || first < 0)
1467 {
1468 return error(GL_INVALID_VALUE);
1469 }
1470
1471 es2::Context *context = es2::getContext();
1472
1473 if(context)
1474 {
1475 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1476 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1477 {
1478 return error(GL_INVALID_OPERATION);
1479 }
1480
1481 context->drawArrays(mode, first, count);
1482 }
1483}
1484
1485void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1486{
1487 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1488 mode, count, type, indices);
1489
1490 switch(mode)
1491 {
1492 case GL_POINTS:
1493 case GL_LINES:
1494 case GL_LINE_LOOP:
1495 case GL_LINE_STRIP:
1496 case GL_TRIANGLES:
1497 case GL_TRIANGLE_FAN:
1498 case GL_TRIANGLE_STRIP:
1499 break;
1500 default:
1501 return error(GL_INVALID_ENUM);
1502 }
1503
1504 if(count < 0)
1505 {
1506 return error(GL_INVALID_VALUE);
1507 }
1508
1509 es2::Context *context = es2::getContext();
1510
1511 if(context)
1512 {
1513 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1514 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1515 {
1516 return error(GL_INVALID_OPERATION);
1517 }
1518
1519 switch(type)
1520 {
1521 case GL_UNSIGNED_BYTE:
1522 case GL_UNSIGNED_SHORT:
1523 case GL_UNSIGNED_INT:
1524 break;
1525 default:
1526 return error(GL_INVALID_ENUM);
1527 }
1528
1529 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1530 }
1531}
1532
1533void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1534{
1535 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1536 mode, first, count, instanceCount);
1537
1538 switch(mode)
1539 {
1540 case GL_POINTS:
1541 case GL_LINES:
1542 case GL_LINE_LOOP:
1543 case GL_LINE_STRIP:
1544 case GL_TRIANGLES:
1545 case GL_TRIANGLE_FAN:
1546 case GL_TRIANGLE_STRIP:
1547 break;
1548 default:
1549 return error(GL_INVALID_ENUM);
1550 }
1551
1552 if(count < 0 || instanceCount < 0)
1553 {
1554 return error(GL_INVALID_VALUE);
1555 }
1556
1557 es2::Context *context = es2::getContext();
1558
1559 if(context)
1560 {
1561 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1562 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1563 {
1564 return error(GL_INVALID_OPERATION);
1565 }
1566
1567 context->drawArrays(mode, first, count, instanceCount);
1568 }
1569}
1570
1571void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1572{
1573 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1574 mode, count, type, indices, instanceCount);
1575
1576 switch(mode)
1577 {
1578 case GL_POINTS:
1579 case GL_LINES:
1580 case GL_LINE_LOOP:
1581 case GL_LINE_STRIP:
1582 case GL_TRIANGLES:
1583 case GL_TRIANGLE_FAN:
1584 case GL_TRIANGLE_STRIP:
1585 break;
1586 default:
1587 return error(GL_INVALID_ENUM);
1588 }
1589
1590 switch(type)
1591 {
1592 case GL_UNSIGNED_BYTE:
1593 case GL_UNSIGNED_SHORT:
1594 case GL_UNSIGNED_INT:
1595 break;
1596 default:
1597 return error(GL_INVALID_ENUM);
1598 }
1599
1600 if(count < 0 || instanceCount < 0)
1601 {
1602 return error(GL_INVALID_VALUE);
1603 }
1604
1605 es2::Context *context = es2::getContext();
1606
1607 if(context)
1608 {
1609 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1610 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1611 {
1612 return error(GL_INVALID_OPERATION);
1613 }
1614
1615 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1616 }
1617}
1618
1619void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1620{
1621 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1622
1623 es2::Context *context = es2::getContext();
1624
1625 if(context)
1626 {
1627 if(index >= es2::MAX_VERTEX_ATTRIBS)
1628 {
1629 return error(GL_INVALID_VALUE);
1630 }
1631
1632 context->setVertexAttribDivisor(index, divisor);
1633 }
1634}
1635
1636void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1637{
1638 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1639 mode, first, count, instanceCount);
1640
1641 switch(mode)
1642 {
1643 case GL_POINTS:
1644 case GL_LINES:
1645 case GL_LINE_LOOP:
1646 case GL_LINE_STRIP:
1647 case GL_TRIANGLES:
1648 case GL_TRIANGLE_FAN:
1649 case GL_TRIANGLE_STRIP:
1650 break;
1651 default:
1652 return error(GL_INVALID_ENUM);
1653 }
1654
1655 if(count < 0 || instanceCount < 0)
1656 {
1657 return error(GL_INVALID_VALUE);
1658 }
1659
1660 es2::Context *context = es2::getContext();
1661
1662 if(context)
1663 {
1664 if(!context->hasZeroDivisor())
1665 {
1666 return error(GL_INVALID_OPERATION);
1667 }
1668
1669 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1670 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1671 {
1672 return error(GL_INVALID_OPERATION);
1673 }
1674
1675 context->drawArrays(mode, first, count, instanceCount);
1676 }
1677}
1678
1679void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1680{
1681 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1682 mode, count, type, indices, instanceCount);
1683
1684 switch(mode)
1685 {
1686 case GL_POINTS:
1687 case GL_LINES:
1688 case GL_LINE_LOOP:
1689 case GL_LINE_STRIP:
1690 case GL_TRIANGLES:
1691 case GL_TRIANGLE_FAN:
1692 case GL_TRIANGLE_STRIP:
1693 break;
1694 default:
1695 return error(GL_INVALID_ENUM);
1696 }
1697
1698 switch(type)
1699 {
1700 case GL_UNSIGNED_BYTE:
1701 case GL_UNSIGNED_SHORT:
1702 case GL_UNSIGNED_INT:
1703 break;
1704 default:
1705 return error(GL_INVALID_ENUM);
1706 }
1707
1708 if(count < 0 || instanceCount < 0)
1709 {
1710 return error(GL_INVALID_VALUE);
1711 }
1712
1713 es2::Context *context = es2::getContext();
1714
1715 if(context)
1716 {
1717 if(!context->hasZeroDivisor())
1718 {
1719 return error(GL_INVALID_OPERATION);
1720 }
1721
1722 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1723 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1724 {
1725 return error(GL_INVALID_OPERATION);
1726 }
1727
1728 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1729 }
1730}
1731
1732void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1733{
1734 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1735
1736 es2::Context *context = es2::getContext();
1737
1738 if(context)
1739 {
1740 if(index >= MAX_VERTEX_ATTRIBS)
1741 {
1742 return error(GL_INVALID_VALUE);
1743 }
1744
1745 context->setVertexAttribDivisor(index, divisor);
1746 }
1747}
1748
1749void Enable(GLenum cap)
1750{
1751 TRACE("(GLenum cap = 0x%X)", cap);
1752
1753 es2::Context *context = es2::getContext();
1754
1755 if(context)
1756 {
1757 switch(cap)
1758 {
1759 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1760 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1761 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1762 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1763 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1764 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1765 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1766 case GL_BLEND: context->setBlendEnabled(true); break;
1767 case GL_DITHER: context->setDitherEnabled(true); break;
1768 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1769 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1770 default:
1771 return error(GL_INVALID_ENUM);
1772 }
1773 }
1774}
1775
1776void EnableVertexAttribArray(GLuint index)
1777{
1778 TRACE("(GLuint index = %d)", index);
1779
1780 if(index >= es2::MAX_VERTEX_ATTRIBS)
1781 {
1782 return error(GL_INVALID_VALUE);
1783 }
1784
1785 es2::Context *context = es2::getContext();
1786
1787 if(context)
1788 {
1789 context->setVertexAttribArrayEnabled(index, true);
1790 }
1791}
1792
1793void EndQueryEXT(GLenum target)
1794{
1795 TRACE("GLenum target = 0x%X)", target);
1796
1797 switch(target)
1798 {
1799 case GL_ANY_SAMPLES_PASSED_EXT:
1800 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1801 break;
1802 default:
1803 return error(GL_INVALID_ENUM);
1804 }
1805
1806 es2::Context *context = es2::getContext();
1807
1808 if(context)
1809 {
1810 context->endQuery(target);
1811 }
1812}
1813
1814void FinishFenceNV(GLuint fence)
1815{
1816 TRACE("(GLuint fence = %d)", fence);
1817
1818 es2::Context *context = es2::getContext();
1819
1820 if(context)
1821 {
1822 es2::Fence *fenceObject = context->getFence(fence);
1823
1824 if(!fenceObject)
1825 {
1826 return error(GL_INVALID_OPERATION);
1827 }
1828
1829 fenceObject->finishFence();
1830 }
1831}
1832
1833void Finish(void)
1834{
1835 TRACE("()");
1836
1837 es2::Context *context = es2::getContext();
1838
1839 if(context)
1840 {
1841 context->finish();
1842 }
1843}
1844
1845void Flush(void)
1846{
1847 TRACE("()");
1848
1849 es2::Context *context = es2::getContext();
1850
1851 if(context)
1852 {
1853 context->flush();
1854 }
1855}
1856
1857void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1858{
1859 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1860 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1861
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001862 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001863 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1864 {
1865 return error(GL_INVALID_ENUM);
1866 }
1867
1868 es2::Context *context = es2::getContext();
1869
1870 if(context)
1871 {
1872 es2::Framebuffer *framebuffer = nullptr;
1873 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001874 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001875 {
1876 framebuffer = context->getReadFramebuffer();
1877 framebufferName = context->getReadFramebufferName();
1878 }
1879 else
1880 {
1881 framebuffer = context->getDrawFramebuffer();
1882 framebufferName = context->getDrawFramebufferName();
1883 }
1884
1885 if(!framebuffer || framebufferName == 0)
1886 {
1887 return error(GL_INVALID_OPERATION);
1888 }
1889
1890 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1891 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1892 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1893 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1894 if(renderbuffer != 0)
1895 {
1896 if(!context->getRenderbuffer(renderbuffer))
1897 {
1898 return error(GL_INVALID_OPERATION);
1899 }
1900 }
1901
Nicolas Capens0bac2852016-05-07 06:09:58 -04001902 switch(attachment)
1903 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001904 case GL_DEPTH_ATTACHMENT:
1905 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1906 break;
1907 case GL_STENCIL_ATTACHMENT:
1908 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1909 break;
1910 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001911 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1912 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1913 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001914 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001915 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1916 {
1917 return error(GL_INVALID_ENUM);
1918 }
1919 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1920 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001921 }
1922 }
1923}
1924
1925void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1926{
1927 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1928 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1929
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001930 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001931 {
1932 return error(GL_INVALID_ENUM);
1933 }
1934
1935 es2::Context *context = es2::getContext();
1936
1937 if(context)
1938 {
1939 if(texture == 0)
1940 {
1941 textarget = GL_NONE;
1942 }
1943 else
1944 {
1945 es2::Texture *tex = context->getTexture(texture);
1946
1947 if(!tex)
1948 {
1949 return error(GL_INVALID_OPERATION);
1950 }
1951
1952 switch(textarget)
1953 {
1954 case GL_TEXTURE_2D:
1955 if(tex->getTarget() != GL_TEXTURE_2D)
1956 {
1957 return error(GL_INVALID_OPERATION);
1958 }
1959 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001960 case GL_TEXTURE_RECTANGLE_ARB:
1961 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1962 {
1963 return error(GL_INVALID_OPERATION);
1964 }
1965 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001966 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1970 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1971 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1972 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1973 {
1974 return error(GL_INVALID_OPERATION);
1975 }
1976 break;
1977 default:
1978 return error(GL_INVALID_ENUM);
1979 }
1980
Nicolas Capens83463112018-06-12 23:55:16 -04001981 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001982 {
1983 return error(GL_INVALID_VALUE);
1984 }
1985
1986 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1987 {
1988 return error(GL_INVALID_VALUE);
1989 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001990
1991 if(tex->isCompressed(textarget, level))
1992 {
1993 return error(GL_INVALID_OPERATION);
1994 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001995 }
1996
1997 es2::Framebuffer *framebuffer = nullptr;
1998 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001999 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002000 {
2001 framebuffer = context->getReadFramebuffer();
2002 framebufferName = context->getReadFramebufferName();
2003 }
2004 else
2005 {
2006 framebuffer = context->getDrawFramebuffer();
2007 framebufferName = context->getDrawFramebufferName();
2008 }
2009
2010 if(framebufferName == 0 || !framebuffer)
2011 {
2012 return error(GL_INVALID_OPERATION);
2013 }
2014
2015 switch(attachment)
2016 {
Nicolas Capens83463112018-06-12 23:55:16 -04002017 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2018 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2019 case GL_DEPTH_STENCIL_ATTACHMENT:
2020 framebuffer->setDepthbuffer(textarget, texture, level);
2021 framebuffer->setStencilbuffer(textarget, texture, level);
2022 break;
2023 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002024 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2025 {
2026 return error(GL_INVALID_ENUM);
2027 }
2028 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2029 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002030 }
2031 }
2032}
2033
2034void FrontFace(GLenum mode)
2035{
2036 TRACE("(GLenum mode = 0x%X)", mode);
2037
2038 switch(mode)
2039 {
2040 case GL_CW:
2041 case GL_CCW:
2042 {
2043 es2::Context *context = es2::getContext();
2044
2045 if(context)
2046 {
2047 context->setFrontFace(mode);
2048 }
2049 }
2050 break;
2051 default:
2052 return error(GL_INVALID_ENUM);
2053 }
2054}
2055
2056void GenBuffers(GLsizei n, GLuint* buffers)
2057{
2058 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2059
2060 if(n < 0)
2061 {
2062 return error(GL_INVALID_VALUE);
2063 }
2064
2065 es2::Context *context = es2::getContext();
2066
2067 if(context)
2068 {
2069 for(int i = 0; i < n; i++)
2070 {
2071 buffers[i] = context->createBuffer();
2072 }
2073 }
2074}
2075
2076void GenerateMipmap(GLenum target)
2077{
2078 TRACE("(GLenum target = 0x%X)", target);
2079
2080 es2::Context *context = es2::getContext();
2081
2082 if(context)
2083 {
2084 es2::Texture *texture = nullptr;
2085
Nicolas Capens0bac2852016-05-07 06:09:58 -04002086 switch(target)
2087 {
2088 case GL_TEXTURE_2D:
2089 texture = context->getTexture2D();
2090 break;
2091 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002092 {
2093 TextureCubeMap *cube = context->getTextureCubeMap();
2094 texture = cube;
2095
2096 if(!cube->isCubeComplete())
2097 {
2098 return error(GL_INVALID_OPERATION);
2099 }
2100 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002101 break;
2102 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002103 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002104 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002105 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002106 texture = context->getTexture3D();
2107 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002108 case GL_TEXTURE_RECTANGLE_ARB:
2109 texture = context->getTexture2DRect();
2110 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002111 default:
2112 return error(GL_INVALID_ENUM);
2113 }
2114
Nicolas Capens83463112018-06-12 23:55:16 -04002115 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002116 {
2117 return error(GL_INVALID_OPERATION);
2118 }
2119
Nicolas Capens0bac2852016-05-07 06:09:58 -04002120 texture->generateMipmaps();
2121 }
2122}
2123
2124void GenFencesNV(GLsizei n, GLuint* fences)
2125{
2126 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2127
2128 if(n < 0)
2129 {
2130 return error(GL_INVALID_VALUE);
2131 }
2132
2133 es2::Context *context = es2::getContext();
2134
2135 if(context)
2136 {
2137 for(int i = 0; i < n; i++)
2138 {
2139 fences[i] = context->createFence();
2140 }
2141 }
2142}
2143
2144void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2145{
2146 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2147
2148 if(n < 0)
2149 {
2150 return error(GL_INVALID_VALUE);
2151 }
2152
2153 es2::Context *context = es2::getContext();
2154
2155 if(context)
2156 {
2157 for(int i = 0; i < n; i++)
2158 {
2159 framebuffers[i] = context->createFramebuffer();
2160 }
2161 }
2162}
2163
2164void GenQueriesEXT(GLsizei n, GLuint* ids)
2165{
2166 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2167
2168 if(n < 0)
2169 {
2170 return error(GL_INVALID_VALUE);
2171 }
2172
2173 es2::Context *context = es2::getContext();
2174
2175 if(context)
2176 {
2177 for(int i = 0; i < n; i++)
2178 {
2179 ids[i] = context->createQuery();
2180 }
2181 }
2182}
2183
2184void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2185{
2186 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2187
2188 if(n < 0)
2189 {
2190 return error(GL_INVALID_VALUE);
2191 }
2192
2193 es2::Context *context = es2::getContext();
2194
2195 if(context)
2196 {
2197 for(int i = 0; i < n; i++)
2198 {
2199 renderbuffers[i] = context->createRenderbuffer();
2200 }
2201 }
2202}
2203
2204void GenTextures(GLsizei n, GLuint* textures)
2205{
2206 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2207
2208 if(n < 0)
2209 {
2210 return error(GL_INVALID_VALUE);
2211 }
2212
2213 es2::Context *context = es2::getContext();
2214
2215 if(context)
2216 {
2217 for(int i = 0; i < n; i++)
2218 {
2219 textures[i] = context->createTexture();
2220 }
2221 }
2222}
2223
2224void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2225{
2226 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2227 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2228 program, index, bufsize, length, size, type, name);
2229
2230 if(bufsize < 0)
2231 {
2232 return error(GL_INVALID_VALUE);
2233 }
2234
2235 es2::Context *context = es2::getContext();
2236
2237 if(context)
2238 {
2239 es2::Program *programObject = context->getProgram(program);
2240
2241 if(!programObject)
2242 {
2243 if(context->getShader(program))
2244 {
2245 return error(GL_INVALID_OPERATION);
2246 }
2247 else
2248 {
2249 return error(GL_INVALID_VALUE);
2250 }
2251 }
2252
2253 if(index >= programObject->getActiveAttributeCount())
2254 {
2255 return error(GL_INVALID_VALUE);
2256 }
2257
2258 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2259 }
2260}
2261
2262void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2263{
2264 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2265 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2266 program, index, bufsize, length, size, type, name);
2267
2268 if(bufsize < 0)
2269 {
2270 return error(GL_INVALID_VALUE);
2271 }
2272
2273 es2::Context *context = es2::getContext();
2274
2275 if(context)
2276 {
2277 es2::Program *programObject = context->getProgram(program);
2278
2279 if(!programObject)
2280 {
2281 if(context->getShader(program))
2282 {
2283 return error(GL_INVALID_OPERATION);
2284 }
2285 else
2286 {
2287 return error(GL_INVALID_VALUE);
2288 }
2289 }
2290
2291 if(index >= programObject->getActiveUniformCount())
2292 {
2293 return error(GL_INVALID_VALUE);
2294 }
2295
2296 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2297 }
2298}
2299
2300void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2301{
2302 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2303 program, maxcount, count, shaders);
2304
2305 if(maxcount < 0)
2306 {
2307 return error(GL_INVALID_VALUE);
2308 }
2309
2310 es2::Context *context = es2::getContext();
2311
2312 if(context)
2313 {
2314 es2::Program *programObject = context->getProgram(program);
2315
2316 if(!programObject)
2317 {
2318 if(context->getShader(program))
2319 {
2320 return error(GL_INVALID_OPERATION);
2321 }
2322 else
2323 {
2324 return error(GL_INVALID_VALUE);
2325 }
2326 }
2327
2328 return programObject->getAttachedShaders(maxcount, count, shaders);
2329 }
2330}
2331
2332int GetAttribLocation(GLuint program, const GLchar* name)
2333{
2334 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2335
2336 es2::Context *context = es2::getContext();
2337
2338 if(context)
2339 {
2340
2341 es2::Program *programObject = context->getProgram(program);
2342
2343 if(!programObject)
2344 {
2345 if(context->getShader(program))
2346 {
2347 return error(GL_INVALID_OPERATION, -1);
2348 }
2349 else
2350 {
2351 return error(GL_INVALID_VALUE, -1);
2352 }
2353 }
2354
2355 if(!programObject->isLinked())
2356 {
2357 return error(GL_INVALID_OPERATION, -1);
2358 }
2359
2360 return programObject->getAttributeLocation(name);
2361 }
2362
2363 return -1;
2364}
2365
2366void GetBooleanv(GLenum pname, GLboolean* params)
2367{
2368 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2369
2370 es2::Context *context = es2::getContext();
2371
2372 if(context)
2373 {
2374 if(!(context->getBooleanv(pname, params)))
2375 {
2376 GLenum nativeType;
2377 unsigned int numParams = 0;
2378 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2379 return error(GL_INVALID_ENUM);
2380
2381 if(numParams == 0)
2382 return; // it is known that the pname is valid, but there are no parameters to return
2383
2384 if(nativeType == GL_FLOAT)
2385 {
2386 GLfloat *floatParams = nullptr;
2387 floatParams = new GLfloat[numParams];
2388
2389 context->getFloatv(pname, floatParams);
2390
2391 for(unsigned int i = 0; i < numParams; ++i)
2392 {
2393 if(floatParams[i] == 0.0f)
2394 params[i] = GL_FALSE;
2395 else
2396 params[i] = GL_TRUE;
2397 }
2398
2399 delete [] floatParams;
2400 }
2401 else if(nativeType == GL_INT)
2402 {
2403 GLint *intParams = nullptr;
2404 intParams = new GLint[numParams];
2405
2406 context->getIntegerv(pname, intParams);
2407
2408 for(unsigned int i = 0; i < numParams; ++i)
2409 {
2410 if(intParams[i] == 0)
2411 params[i] = GL_FALSE;
2412 else
2413 params[i] = GL_TRUE;
2414 }
2415
2416 delete [] intParams;
2417 }
2418 }
2419 }
2420}
2421
2422void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2423{
2424 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2425
2426 es2::Context *context = es2::getContext();
2427
2428 if(context)
2429 {
2430 es2::Buffer *buffer;
2431 if(!context->getBuffer(target, &buffer))
2432 {
2433 return error(GL_INVALID_ENUM);
2434 }
2435
2436 if(!buffer)
2437 {
2438 // A null buffer means that "0" is bound to the requested buffer target
2439 return error(GL_INVALID_OPERATION);
2440 }
2441
Nicolas Capens0bac2852016-05-07 06:09:58 -04002442 switch(pname)
2443 {
2444 case GL_BUFFER_USAGE:
2445 *params = buffer->usage();
2446 break;
2447 case GL_BUFFER_SIZE:
2448 *params = (GLint)buffer->size();
2449 break;
2450 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002451 *params = buffer->access();
2452 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002453 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002454 *params = buffer->isMapped();
2455 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002456 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002457 *params = (GLint)buffer->length();
2458 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002459 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002460 *params = (GLint)buffer->offset();
2461 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002462 default:
2463 return error(GL_INVALID_ENUM);
2464 }
2465 }
2466}
2467
2468GLenum GetError(void)
2469{
2470 TRACE("()");
2471
2472 es2::Context *context = es2::getContext();
2473
2474 if(context)
2475 {
2476 return context->getError();
2477 }
2478
2479 return GL_NO_ERROR;
2480}
2481
2482void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2483{
2484 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2485
2486 es2::Context *context = es2::getContext();
2487
2488 if(context)
2489 {
2490 es2::Fence *fenceObject = context->getFence(fence);
2491
2492 if(!fenceObject)
2493 {
2494 return error(GL_INVALID_OPERATION);
2495 }
2496
2497 fenceObject->getFenceiv(pname, params);
2498 }
2499}
2500
2501void GetFloatv(GLenum pname, GLfloat* params)
2502{
2503 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2504
2505 es2::Context *context = es2::getContext();
2506
2507 if(context)
2508 {
2509 if(!(context->getFloatv(pname, params)))
2510 {
2511 GLenum nativeType;
2512 unsigned int numParams = 0;
2513 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2514 return error(GL_INVALID_ENUM);
2515
2516 if(numParams == 0)
2517 return; // it is known that the pname is valid, but that there are no parameters to return.
2518
2519 if(nativeType == GL_BOOL)
2520 {
2521 GLboolean *boolParams = nullptr;
2522 boolParams = new GLboolean[numParams];
2523
2524 context->getBooleanv(pname, boolParams);
2525
2526 for(unsigned int i = 0; i < numParams; ++i)
2527 {
2528 if(boolParams[i] == GL_FALSE)
2529 params[i] = 0.0f;
2530 else
2531 params[i] = 1.0f;
2532 }
2533
2534 delete [] boolParams;
2535 }
2536 else if(nativeType == GL_INT)
2537 {
2538 GLint *intParams = nullptr;
2539 intParams = new GLint[numParams];
2540
2541 context->getIntegerv(pname, intParams);
2542
2543 for(unsigned int i = 0; i < numParams; ++i)
2544 {
2545 params[i] = (GLfloat)intParams[i];
2546 }
2547
2548 delete [] intParams;
2549 }
2550 }
2551 }
2552}
2553
2554void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2555{
2556 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2557 target, attachment, pname, params);
2558
2559 es2::Context *context = es2::getContext();
2560
2561 if(context)
2562 {
2563 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2564 {
2565 return error(GL_INVALID_ENUM);
2566 }
2567
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002568 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002569
Nicolas Capens0bac2852016-05-07 06:09:58 -04002570 if(target == GL_READ_FRAMEBUFFER)
2571 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002572 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002573 }
2574 else
2575 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002576 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002577 }
2578
Nicolas Capens0bac2852016-05-07 06:09:58 -04002579 switch(attachment)
2580 {
2581 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002582 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002583 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002584 if(framebufferName != 0)
2585 {
2586 return error(GL_INVALID_OPERATION);
2587 }
2588 break;
2589 case GL_DEPTH_ATTACHMENT:
2590 case GL_STENCIL_ATTACHMENT:
2591 if(framebufferName == 0)
2592 {
2593 return error(GL_INVALID_OPERATION);
2594 }
2595 break;
2596 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002597 if(framebufferName == 0)
2598 {
2599 return error(GL_INVALID_OPERATION);
2600 }
2601 break;
2602 default:
2603 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2604 {
2605 if(framebufferName == 0)
2606 {
2607 return error(GL_INVALID_OPERATION);
2608 }
2609 }
2610 else return error(GL_INVALID_ENUM);
2611 }
2612
2613 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2614
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002615 if(!framebuffer)
2616 {
2617 return error(GL_INVALID_OPERATION);
2618 }
2619
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002620 GLenum attachmentType;
2621 GLuint attachmentHandle;
2622 GLint attachmentLayer;
2623 Renderbuffer *renderbuffer = nullptr;
2624 switch(attachment)
2625 {
2626 case GL_BACK:
2627 attachmentType = framebuffer->getColorbufferType(0);
2628 attachmentHandle = framebuffer->getColorbufferName(0);
2629 attachmentLayer = framebuffer->getColorbufferLayer(0);
2630 renderbuffer = framebuffer->getColorbuffer(0);
2631 break;
2632 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002633 case GL_DEPTH_ATTACHMENT:
2634 attachmentType = framebuffer->getDepthbufferType();
2635 attachmentHandle = framebuffer->getDepthbufferName();
2636 attachmentLayer = framebuffer->getDepthbufferLayer();
2637 renderbuffer = framebuffer->getDepthbuffer();
2638 break;
2639 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002640 case GL_STENCIL_ATTACHMENT:
2641 attachmentType = framebuffer->getStencilbufferType();
2642 attachmentHandle = framebuffer->getStencilbufferName();
2643 attachmentLayer = framebuffer->getStencilbufferLayer();
2644 renderbuffer = framebuffer->getStencilbuffer();
2645 break;
2646 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002647 attachmentType = framebuffer->getDepthbufferType();
2648 attachmentHandle = framebuffer->getDepthbufferName();
2649 attachmentLayer = framebuffer->getDepthbufferLayer();
2650 renderbuffer = framebuffer->getDepthbuffer();
2651
2652 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002653 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002654 // Different attachments to DEPTH and STENCIL, query fails
2655 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002656 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002657 break;
2658 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002659 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2660 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2661 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2662 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2663 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2664 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002665 }
2666
2667 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002668 if(framebufferName == 0)
2669 {
2670 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2671 }
2672 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002673 {
2674 attachmentObjectType = attachmentType;
2675 }
2676 else if(es2::IsTextureTarget(attachmentType))
2677 {
2678 attachmentObjectType = GL_TEXTURE;
2679 }
2680 else UNREACHABLE(attachmentType);
2681
2682 if(attachmentObjectType != GL_NONE)
2683 {
2684 switch(pname)
2685 {
2686 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2687 *params = attachmentObjectType;
2688 break;
2689 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002690 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002691 {
2692 *params = attachmentHandle;
2693 }
2694 else
2695 {
2696 return error(GL_INVALID_ENUM);
2697 }
2698 break;
2699 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2700 if(attachmentObjectType == GL_TEXTURE)
2701 {
Nicolas Capens83463112018-06-12 23:55:16 -04002702 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002703 }
2704 else
2705 {
2706 return error(GL_INVALID_ENUM);
2707 }
2708 break;
2709 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2710 if(attachmentObjectType == GL_TEXTURE)
2711 {
2712 if(es2::IsCubemapTextureTarget(attachmentType))
2713 {
2714 *params = attachmentType;
2715 }
2716 else
2717 {
2718 *params = 0;
2719 }
2720 }
2721 else
2722 {
2723 return error(GL_INVALID_ENUM);
2724 }
2725 break;
2726 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002727 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002728 break;
2729 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002730 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002731 break;
2732 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002733 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002734 break;
2735 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002736 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002737 break;
2738 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002739 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002740 break;
2741 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002742 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002743 break;
2744 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002745 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002746 break;
2747 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002748 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2749 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002750 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002751 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002752 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002753
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002754 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002755 break;
2756 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002757 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002758 break;
2759 default:
2760 return error(GL_INVALID_ENUM);
2761 }
2762 }
2763 else
2764 {
2765 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2766 // is NONE, then querying any other pname will generate INVALID_ENUM.
2767
2768 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2769 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2770 // INVALID_OPERATION for all other pnames
2771
2772 switch(pname)
2773 {
2774 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2775 *params = GL_NONE;
2776 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002777 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002778 *params = 0;
2779 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002780 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002781 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002782 }
2783 }
2784 }
2785}
2786
2787GLenum GetGraphicsResetStatusEXT(void)
2788{
2789 TRACE("()");
2790
2791 return GL_NO_ERROR;
2792}
2793
2794void GetIntegerv(GLenum pname, GLint* params)
2795{
2796 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2797
2798 es2::Context *context = es2::getContext();
2799
2800 if(!context)
2801 {
2802 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2803 #ifdef __ANDROID__
2804 ALOGI("expected_badness glGetIntegerv() called without current context.");
2805 #else
2806 ERR("glGetIntegerv() called without current context.");
2807 #endif
2808
2809 // This is not spec compliant! When there is no current GL context, functions should
2810 // have no side effects. Google Maps queries these values before creating a context,
2811 // so we need this as a bug-compatible workaround.
2812 switch(pname)
2813 {
2814 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2815 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2816 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2817 case GL_STENCIL_BITS: *params = 8; return;
2818 case GL_ALIASED_LINE_WIDTH_RANGE:
2819 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2820 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2821 return;
2822 }
2823 }
2824
2825 if(context)
2826 {
2827 if(!(context->getIntegerv(pname, params)))
2828 {
2829 GLenum nativeType;
2830 unsigned int numParams = 0;
2831 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2832 return error(GL_INVALID_ENUM);
2833
2834 if(numParams == 0)
2835 return; // it is known that pname is valid, but there are no parameters to return
2836
2837 if(nativeType == GL_BOOL)
2838 {
2839 GLboolean *boolParams = nullptr;
2840 boolParams = new GLboolean[numParams];
2841
2842 context->getBooleanv(pname, boolParams);
2843
2844 for(unsigned int i = 0; i < numParams; ++i)
2845 {
2846 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2847 }
2848
2849 delete [] boolParams;
2850 }
2851 else if(nativeType == GL_FLOAT)
2852 {
2853 GLfloat *floatParams = nullptr;
2854 floatParams = new GLfloat[numParams];
2855
2856 context->getFloatv(pname, floatParams);
2857
2858 for(unsigned int i = 0; i < numParams; ++i)
2859 {
2860 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2861 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002862 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002863 }
2864 else
2865 {
2866 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2867 }
2868 }
2869
2870 delete [] floatParams;
2871 }
2872 }
2873 }
2874}
2875
2876void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2877{
2878 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2879
2880 es2::Context *context = es2::getContext();
2881
2882 if(context)
2883 {
2884 es2::Program *programObject = context->getProgram(program);
2885
2886 if(!programObject)
2887 {
2888 if(context->getShader(program))
2889 {
2890 return error(GL_INVALID_OPERATION);
2891 }
2892 else
2893 {
2894 return error(GL_INVALID_VALUE);
2895 }
2896 }
2897
Nicolas Capens0bac2852016-05-07 06:09:58 -04002898 switch(pname)
2899 {
2900 case GL_DELETE_STATUS:
2901 *params = programObject->isFlaggedForDeletion();
2902 return;
2903 case GL_LINK_STATUS:
2904 *params = programObject->isLinked();
2905 return;
2906 case GL_VALIDATE_STATUS:
2907 *params = programObject->isValidated();
2908 return;
2909 case GL_INFO_LOG_LENGTH:
2910 *params = (GLint)programObject->getInfoLogLength();
2911 return;
2912 case GL_ATTACHED_SHADERS:
2913 *params = programObject->getAttachedShadersCount();
2914 return;
2915 case GL_ACTIVE_ATTRIBUTES:
2916 *params = (GLint)programObject->getActiveAttributeCount();
2917 return;
2918 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2919 *params = programObject->getActiveAttributeMaxLength();
2920 return;
2921 case GL_ACTIVE_UNIFORMS:
2922 *params = (GLint)programObject->getActiveUniformCount();
2923 return;
2924 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2925 *params = programObject->getActiveUniformMaxLength();
2926 return;
2927 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002928 *params = (GLint)programObject->getActiveUniformBlockCount();
2929 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002930 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002931 *params = programObject->getActiveUniformBlockMaxLength();
2932 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002933 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002934 *params = programObject->getTransformFeedbackBufferMode();
2935 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002936 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002937 *params = programObject->getTransformFeedbackVaryingCount();
2938 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002939 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002940 *params = programObject->getTransformFeedbackVaryingMaxLength();
2941 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002942 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002943 *params = programObject->getBinaryRetrievableHint();
2944 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002945 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002946 *params = programObject->getBinaryLength();
2947 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002948 default:
2949 return error(GL_INVALID_ENUM);
2950 }
2951 }
2952}
2953
2954void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2955{
2956 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2957 program, bufsize, length, infolog);
2958
2959 if(bufsize < 0)
2960 {
2961 return error(GL_INVALID_VALUE);
2962 }
2963
2964 es2::Context *context = es2::getContext();
2965
2966 if(context)
2967 {
2968 es2::Program *programObject = context->getProgram(program);
2969
2970 if(!programObject)
2971 {
2972 if(context->getShader(program))
2973 {
2974 return error(GL_INVALID_OPERATION);
2975 }
2976 else
2977 {
2978 return error(GL_INVALID_VALUE);
2979 }
2980 }
2981
2982 programObject->getInfoLog(bufsize, length, infolog);
2983 }
2984}
2985
2986void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2987{
2988 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2989
2990 switch(pname)
2991 {
2992 case GL_CURRENT_QUERY_EXT:
2993 break;
2994 default:
2995 return error(GL_INVALID_ENUM);
2996 }
2997
2998 es2::Context *context = es2::getContext();
2999
3000 if(context)
3001 {
3002 params[0] = context->getActiveQuery(target);
3003 }
3004}
3005
3006void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3007{
3008 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3009
3010 switch(pname)
3011 {
3012 case GL_QUERY_RESULT_EXT:
3013 case GL_QUERY_RESULT_AVAILABLE_EXT:
3014 break;
3015 default:
3016 return error(GL_INVALID_ENUM);
3017 }
3018
3019 es2::Context *context = es2::getContext();
3020
3021 if(context)
3022 {
3023 es2::Query *queryObject = context->getQuery(name);
3024
3025 if(!queryObject)
3026 {
3027 return error(GL_INVALID_OPERATION);
3028 }
3029
3030 if(context->getActiveQuery(queryObject->getType()) == name)
3031 {
3032 return error(GL_INVALID_OPERATION);
3033 }
3034
3035 switch(pname)
3036 {
3037 case GL_QUERY_RESULT_EXT:
3038 params[0] = queryObject->getResult();
3039 break;
3040 case GL_QUERY_RESULT_AVAILABLE_EXT:
3041 params[0] = queryObject->isResultAvailable();
3042 break;
3043 default:
3044 ASSERT(false);
3045 }
3046 }
3047}
3048
3049void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3050{
3051 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3052
3053 es2::Context *context = es2::getContext();
3054
3055 if(context)
3056 {
3057 if(target != GL_RENDERBUFFER)
3058 {
3059 return error(GL_INVALID_ENUM);
3060 }
3061
3062 if(context->getRenderbufferName() == 0)
3063 {
3064 return error(GL_INVALID_OPERATION);
3065 }
3066
3067 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3068
3069 switch(pname)
3070 {
3071 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3072 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003073 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3074 {
3075 GLint internalformat = renderbuffer->getFormat();
3076 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3077 }
3078 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003079 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3080 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3081 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3082 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3083 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3084 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003085 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003086 default:
3087 return error(GL_INVALID_ENUM);
3088 }
3089 }
3090}
3091
3092void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3093{
3094 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3095
3096 es2::Context *context = es2::getContext();
3097
3098 if(context)
3099 {
3100 es2::Shader *shaderObject = context->getShader(shader);
3101
3102 if(!shaderObject)
3103 {
3104 if(context->getProgram(shader))
3105 {
3106 return error(GL_INVALID_OPERATION);
3107 }
3108 else
3109 {
3110 return error(GL_INVALID_VALUE);
3111 }
3112 }
3113
3114 switch(pname)
3115 {
3116 case GL_SHADER_TYPE:
3117 *params = shaderObject->getType();
3118 return;
3119 case GL_DELETE_STATUS:
3120 *params = shaderObject->isFlaggedForDeletion();
3121 return;
3122 case GL_COMPILE_STATUS:
3123 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3124 return;
3125 case GL_INFO_LOG_LENGTH:
3126 *params = (GLint)shaderObject->getInfoLogLength();
3127 return;
3128 case GL_SHADER_SOURCE_LENGTH:
3129 *params = (GLint)shaderObject->getSourceLength();
3130 return;
3131 default:
3132 return error(GL_INVALID_ENUM);
3133 }
3134 }
3135}
3136
3137void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3138{
3139 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3140 shader, bufsize, length, infolog);
3141
3142 if(bufsize < 0)
3143 {
3144 return error(GL_INVALID_VALUE);
3145 }
3146
3147 es2::Context *context = es2::getContext();
3148
3149 if(context)
3150 {
3151 es2::Shader *shaderObject = context->getShader(shader);
3152
3153 if(!shaderObject)
3154 {
3155 if(context->getProgram(shader))
3156 {
3157 return error(GL_INVALID_OPERATION);
3158 }
3159 else
3160 {
3161 return error(GL_INVALID_VALUE);
3162 }
3163 }
3164
3165 shaderObject->getInfoLog(bufsize, length, infolog);
3166 }
3167}
3168
3169void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3170{
3171 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3172 shadertype, precisiontype, range, precision);
3173
3174 switch(shadertype)
3175 {
3176 case GL_VERTEX_SHADER:
3177 case GL_FRAGMENT_SHADER:
3178 break;
3179 default:
3180 return error(GL_INVALID_ENUM);
3181 }
3182
3183 switch(precisiontype)
3184 {
3185 case GL_LOW_FLOAT:
3186 case GL_MEDIUM_FLOAT:
3187 case GL_HIGH_FLOAT:
3188 // IEEE 754 single-precision
3189 range[0] = 127;
3190 range[1] = 127;
3191 *precision = 23;
3192 break;
3193 case GL_LOW_INT:
3194 case GL_MEDIUM_INT:
3195 case GL_HIGH_INT:
3196 // Full integer precision is supported
3197 range[0] = 31;
3198 range[1] = 30;
3199 *precision = 0;
3200 break;
3201 default:
3202 return error(GL_INVALID_ENUM);
3203 }
3204}
3205
3206void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3207{
3208 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3209 shader, bufsize, length, source);
3210
3211 if(bufsize < 0)
3212 {
3213 return error(GL_INVALID_VALUE);
3214 }
3215
3216 es2::Context *context = es2::getContext();
3217
3218 if(context)
3219 {
3220 es2::Shader *shaderObject = context->getShader(shader);
3221
3222 if(!shaderObject)
3223 {
3224 if(context->getProgram(shader))
3225 {
3226 return error(GL_INVALID_OPERATION);
3227 }
3228 else
3229 {
3230 return error(GL_INVALID_VALUE);
3231 }
3232 }
3233
3234 shaderObject->getSource(bufsize, length, source);
3235 }
3236}
3237
3238const GLubyte* GetString(GLenum name)
3239{
3240 TRACE("(GLenum name = 0x%X)", name);
3241
3242 switch(name)
3243 {
3244 case GL_VENDOR:
3245 return (GLubyte*)"Google Inc.";
3246 case GL_RENDERER:
3247 return (GLubyte*)"Google SwiftShader";
3248 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003249 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003250 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003251 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003252 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003253 {
3254 es2::Context *context = es2::getContext();
3255 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3256 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003257 default:
3258 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3259 }
3260}
3261
3262void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3263{
3264 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3265
3266 es2::Context *context = es2::getContext();
3267
3268 if(context)
3269 {
3270 es2::Texture *texture;
3271
Nicolas Capens0bac2852016-05-07 06:09:58 -04003272 switch(target)
3273 {
Nicolas Capens83463112018-06-12 23:55:16 -04003274 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3275 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3276 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3277 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3278 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3279 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003280 default:
3281 return error(GL_INVALID_ENUM);
3282 }
3283
3284 switch(pname)
3285 {
3286 case GL_TEXTURE_MAG_FILTER:
3287 *params = (GLfloat)texture->getMagFilter();
3288 break;
3289 case GL_TEXTURE_MIN_FILTER:
3290 *params = (GLfloat)texture->getMinFilter();
3291 break;
3292 case GL_TEXTURE_WRAP_S:
3293 *params = (GLfloat)texture->getWrapS();
3294 break;
3295 case GL_TEXTURE_WRAP_T:
3296 *params = (GLfloat)texture->getWrapT();
3297 break;
3298 case GL_TEXTURE_WRAP_R_OES:
3299 *params = (GLfloat)texture->getWrapR();
3300 break;
3301 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3302 *params = texture->getMaxAnisotropy();
3303 break;
3304 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3305 *params = (GLfloat)1;
3306 break;
3307 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003308 *params = (GLfloat)texture->getBaseLevel();
3309 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003310 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003311 *params = (GLfloat)texture->getCompareFunc();
3312 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003313 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003314 *params = (GLfloat)texture->getCompareMode();
3315 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003316 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003317 *params = (GLfloat)texture->getImmutableFormat();
3318 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003319 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003320 *params = (GLfloat)texture->getImmutableLevels();
3321 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003322 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003323 *params = (GLfloat)texture->getMaxLevel();
3324 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003325 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003326 *params = texture->getMaxLOD();
3327 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003328 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003329 *params = texture->getMinLOD();
3330 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003331 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003332 *params = (GLfloat)texture->getSwizzleR();
3333 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003334 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003335 *params = (GLfloat)texture->getSwizzleG();
3336 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003337 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003338 *params = (GLfloat)texture->getSwizzleB();
3339 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003340 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003341 *params = (GLfloat)texture->getSwizzleA();
3342 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003343 default:
3344 return error(GL_INVALID_ENUM);
3345 }
3346 }
3347}
3348
3349void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3350{
3351 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3352
3353 es2::Context *context = es2::getContext();
3354
3355 if(context)
3356 {
3357 es2::Texture *texture;
3358
Nicolas Capens0bac2852016-05-07 06:09:58 -04003359 switch(target)
3360 {
Nicolas Capens83463112018-06-12 23:55:16 -04003361 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3362 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3363 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3364 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3365 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3366 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003367 default:
3368 return error(GL_INVALID_ENUM);
3369 }
3370
3371 switch(pname)
3372 {
3373 case GL_TEXTURE_MAG_FILTER:
3374 *params = texture->getMagFilter();
3375 break;
3376 case GL_TEXTURE_MIN_FILTER:
3377 *params = texture->getMinFilter();
3378 break;
3379 case GL_TEXTURE_WRAP_S:
3380 *params = texture->getWrapS();
3381 break;
3382 case GL_TEXTURE_WRAP_T:
3383 *params = texture->getWrapT();
3384 break;
3385 case GL_TEXTURE_WRAP_R_OES:
3386 *params = texture->getWrapR();
3387 break;
3388 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3389 *params = (GLint)texture->getMaxAnisotropy();
3390 break;
3391 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3392 *params = 1;
3393 break;
3394 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003395 *params = texture->getBaseLevel();
3396 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003397 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003398 *params = (GLint)texture->getCompareFunc();
3399 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003400 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003401 *params = (GLint)texture->getCompareMode();
3402 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003403 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003404 *params = (GLint)texture->getImmutableFormat();
3405 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003406 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003407 *params = (GLint)texture->getImmutableLevels();
3408 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003409 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003410 *params = texture->getMaxLevel();
3411 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003412 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003413 *params = (GLint)roundf(texture->getMaxLOD());
3414 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003415 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003416 *params = (GLint)roundf(texture->getMinLOD());
3417 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003418 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003419 *params = (GLint)texture->getSwizzleR();
3420 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003421 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003422 *params = (GLint)texture->getSwizzleG();
3423 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003424 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003425 *params = (GLint)texture->getSwizzleB();
3426 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003427 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003428 *params = (GLint)texture->getSwizzleA();
3429 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003430 default:
3431 return error(GL_INVALID_ENUM);
3432 }
3433 }
3434}
3435
3436void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3437{
3438 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3439 program, location, bufSize, params);
3440
3441 if(bufSize < 0)
3442 {
3443 return error(GL_INVALID_VALUE);
3444 }
3445
3446 es2::Context *context = es2::getContext();
3447
3448 if(context)
3449 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003450 es2::Program *programObject = context->getProgram(program);
3451
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003452 if(!programObject)
3453 {
3454 if(context->getShader(program))
3455 {
3456 return error(GL_INVALID_OPERATION);
3457 }
3458 else
3459 {
3460 return error(GL_INVALID_VALUE);
3461 }
3462 }
3463
3464 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003465 {
3466 return error(GL_INVALID_OPERATION);
3467 }
3468
3469 if(!programObject->getUniformfv(location, &bufSize, params))
3470 {
3471 return error(GL_INVALID_OPERATION);
3472 }
3473 }
3474}
3475
3476void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3477{
3478 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3479
3480 es2::Context *context = es2::getContext();
3481
3482 if(context)
3483 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003484 es2::Program *programObject = context->getProgram(program);
3485
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003486 if(!programObject)
3487 {
3488 if(context->getShader(program))
3489 {
3490 return error(GL_INVALID_OPERATION);
3491 }
3492 else
3493 {
3494 return error(GL_INVALID_VALUE);
3495 }
3496 }
3497
3498 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003499 {
3500 return error(GL_INVALID_OPERATION);
3501 }
3502
3503 if(!programObject->getUniformfv(location, nullptr, params))
3504 {
3505 return error(GL_INVALID_OPERATION);
3506 }
3507 }
3508}
3509
3510void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3511{
3512 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3513 program, location, bufSize, params);
3514
3515 if(bufSize < 0)
3516 {
3517 return error(GL_INVALID_VALUE);
3518 }
3519
3520 es2::Context *context = es2::getContext();
3521
3522 if(context)
3523 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003524 es2::Program *programObject = context->getProgram(program);
3525
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003526 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003527 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003528 if(context->getShader(program))
3529 {
3530 return error(GL_INVALID_OPERATION);
3531 }
3532 else
3533 {
3534 return error(GL_INVALID_VALUE);
3535 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003536 }
3537
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003538 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003539 {
3540 return error(GL_INVALID_OPERATION);
3541 }
3542
3543 if(!programObject->getUniformiv(location, &bufSize, params))
3544 {
3545 return error(GL_INVALID_OPERATION);
3546 }
3547 }
3548}
3549
3550void GetUniformiv(GLuint program, GLint location, GLint* params)
3551{
3552 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3553
3554 es2::Context *context = es2::getContext();
3555
3556 if(context)
3557 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003558 es2::Program *programObject = context->getProgram(program);
3559
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003560 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003561 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003562 if(context->getShader(program))
3563 {
3564 return error(GL_INVALID_OPERATION);
3565 }
3566 else
3567 {
3568 return error(GL_INVALID_VALUE);
3569 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003570 }
3571
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003572 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003573 {
3574 return error(GL_INVALID_OPERATION);
3575 }
3576
3577 if(!programObject->getUniformiv(location, nullptr, params))
3578 {
3579 return error(GL_INVALID_OPERATION);
3580 }
3581 }
3582}
3583
3584int GetUniformLocation(GLuint program, const GLchar* name)
3585{
3586 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3587
3588 es2::Context *context = es2::getContext();
3589
3590 if(strstr(name, "gl_") == name)
3591 {
3592 return -1;
3593 }
3594
3595 if(context)
3596 {
3597 es2::Program *programObject = context->getProgram(program);
3598
3599 if(!programObject)
3600 {
3601 if(context->getShader(program))
3602 {
3603 return error(GL_INVALID_OPERATION, -1);
3604 }
3605 else
3606 {
3607 return error(GL_INVALID_VALUE, -1);
3608 }
3609 }
3610
3611 if(!programObject->isLinked())
3612 {
3613 return error(GL_INVALID_OPERATION, -1);
3614 }
3615
3616 return programObject->getUniformLocation(name);
3617 }
3618
3619 return -1;
3620}
3621
3622void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3623{
3624 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3625
3626 es2::Context *context = es2::getContext();
3627
3628 if(context)
3629 {
3630 if(index >= es2::MAX_VERTEX_ATTRIBS)
3631 {
3632 return error(GL_INVALID_VALUE);
3633 }
3634
3635 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3636
Nicolas Capens0bac2852016-05-07 06:09:58 -04003637 switch(pname)
3638 {
3639 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3640 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3641 break;
3642 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3643 *params = (GLfloat)attribState.mSize;
3644 break;
3645 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3646 *params = (GLfloat)attribState.mStride;
3647 break;
3648 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3649 *params = (GLfloat)attribState.mType;
3650 break;
3651 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3652 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3653 break;
3654 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3655 *params = (GLfloat)attribState.mBoundBuffer.name();
3656 break;
3657 case GL_CURRENT_VERTEX_ATTRIB:
3658 {
3659 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3660 for(int i = 0; i < 4; ++i)
3661 {
3662 params[i] = attrib.getCurrentValueF(i);
3663 }
3664 }
3665 break;
3666 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003667 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3668 break;
3669 default:
3670 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003671 }
3672 }
3673}
3674
3675void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3676{
3677 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3678
3679 es2::Context *context = es2::getContext();
3680
3681 if(context)
3682 {
3683 if(index >= es2::MAX_VERTEX_ATTRIBS)
3684 {
3685 return error(GL_INVALID_VALUE);
3686 }
3687
3688 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3689
Nicolas Capens0bac2852016-05-07 06:09:58 -04003690 switch(pname)
3691 {
3692 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3693 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3694 break;
3695 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3696 *params = attribState.mSize;
3697 break;
3698 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3699 *params = attribState.mStride;
3700 break;
3701 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3702 *params = attribState.mType;
3703 break;
3704 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3705 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3706 break;
3707 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3708 *params = attribState.mBoundBuffer.name();
3709 break;
3710 case GL_CURRENT_VERTEX_ATTRIB:
3711 {
3712 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3713 for(int i = 0; i < 4; ++i)
3714 {
3715 float currentValue = attrib.getCurrentValueF(i);
3716 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3717 }
3718 }
3719 break;
3720 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003721 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3722 break;
3723 default:
3724 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003725 }
3726 }
3727}
3728
3729void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3730{
3731 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3732
3733 es2::Context *context = es2::getContext();
3734
3735 if(context)
3736 {
3737 if(index >= es2::MAX_VERTEX_ATTRIBS)
3738 {
3739 return error(GL_INVALID_VALUE);
3740 }
3741
3742 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3743 {
3744 return error(GL_INVALID_ENUM);
3745 }
3746
3747 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3748 }
3749}
3750
3751void Hint(GLenum target, GLenum mode)
3752{
3753 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3754
3755 switch(mode)
3756 {
3757 case GL_FASTEST:
3758 case GL_NICEST:
3759 case GL_DONT_CARE:
3760 break;
3761 default:
3762 return error(GL_INVALID_ENUM);
3763 }
3764
3765 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003766
3767 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003768 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003769 switch(target)
3770 {
3771 case GL_GENERATE_MIPMAP_HINT:
3772 context->setGenerateMipmapHint(mode);
3773 break;
3774 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3775 context->setFragmentShaderDerivativeHint(mode);
3776 break;
3777 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3778 context->setTextureFilteringHint(mode);
3779 break;
3780 default:
3781 return error(GL_INVALID_ENUM);
3782 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003783 }
3784}
3785
3786GLboolean IsBuffer(GLuint buffer)
3787{
3788 TRACE("(GLuint buffer = %d)", buffer);
3789
3790 es2::Context *context = es2::getContext();
3791
3792 if(context && buffer)
3793 {
3794 es2::Buffer *bufferObject = context->getBuffer(buffer);
3795
3796 if(bufferObject)
3797 {
3798 return GL_TRUE;
3799 }
3800 }
3801
3802 return GL_FALSE;
3803}
3804
3805GLboolean IsEnabled(GLenum cap)
3806{
3807 TRACE("(GLenum cap = 0x%X)", cap);
3808
3809 es2::Context *context = es2::getContext();
3810
3811 if(context)
3812 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003813 switch(cap)
3814 {
3815 case GL_CULL_FACE: return context->isCullFaceEnabled();
3816 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3817 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3818 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3819 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3820 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3821 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3822 case GL_BLEND: return context->isBlendEnabled();
3823 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003824 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3825 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003826 default:
3827 return error(GL_INVALID_ENUM, false);
3828 }
3829 }
3830
3831 return false;
3832}
3833
3834GLboolean IsFenceNV(GLuint fence)
3835{
3836 TRACE("(GLuint fence = %d)", fence);
3837
3838 es2::Context *context = es2::getContext();
3839
3840 if(context)
3841 {
3842 es2::Fence *fenceObject = context->getFence(fence);
3843
3844 if(!fenceObject)
3845 {
3846 return GL_FALSE;
3847 }
3848
3849 return fenceObject->isFence();
3850 }
3851
3852 return GL_FALSE;
3853}
3854
3855GLboolean IsFramebuffer(GLuint framebuffer)
3856{
3857 TRACE("(GLuint framebuffer = %d)", framebuffer);
3858
3859 es2::Context *context = es2::getContext();
3860
3861 if(context && framebuffer)
3862 {
3863 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3864
3865 if(framebufferObject)
3866 {
3867 return GL_TRUE;
3868 }
3869 }
3870
3871 return GL_FALSE;
3872}
3873
3874GLboolean IsProgram(GLuint program)
3875{
3876 TRACE("(GLuint program = %d)", program);
3877
3878 es2::Context *context = es2::getContext();
3879
3880 if(context && program)
3881 {
3882 es2::Program *programObject = context->getProgram(program);
3883
3884 if(programObject)
3885 {
3886 return GL_TRUE;
3887 }
3888 }
3889
3890 return GL_FALSE;
3891}
3892
3893GLboolean IsQueryEXT(GLuint name)
3894{
3895 TRACE("(GLuint name = %d)", name);
3896
3897 if(name == 0)
3898 {
3899 return GL_FALSE;
3900 }
3901
3902 es2::Context *context = es2::getContext();
3903
3904 if(context)
3905 {
3906 es2::Query *queryObject = context->getQuery(name);
3907
3908 if(queryObject)
3909 {
3910 return GL_TRUE;
3911 }
3912 }
3913
3914 return GL_FALSE;
3915}
3916
3917GLboolean IsRenderbuffer(GLuint renderbuffer)
3918{
3919 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3920
3921 es2::Context *context = es2::getContext();
3922
3923 if(context && renderbuffer)
3924 {
3925 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3926
3927 if(renderbufferObject)
3928 {
3929 return GL_TRUE;
3930 }
3931 }
3932
3933 return GL_FALSE;
3934}
3935
3936GLboolean IsShader(GLuint shader)
3937{
3938 TRACE("(GLuint shader = %d)", shader);
3939
3940 es2::Context *context = es2::getContext();
3941
3942 if(context && shader)
3943 {
3944 es2::Shader *shaderObject = context->getShader(shader);
3945
3946 if(shaderObject)
3947 {
3948 return GL_TRUE;
3949 }
3950 }
3951
3952 return GL_FALSE;
3953}
3954
3955GLboolean IsTexture(GLuint texture)
3956{
3957 TRACE("(GLuint texture = %d)", texture);
3958
3959 es2::Context *context = es2::getContext();
3960
3961 if(context && texture)
3962 {
3963 es2::Texture *textureObject = context->getTexture(texture);
3964
3965 if(textureObject)
3966 {
3967 return GL_TRUE;
3968 }
3969 }
3970
3971 return GL_FALSE;
3972}
3973
3974void LineWidth(GLfloat width)
3975{
3976 TRACE("(GLfloat width = %f)", width);
3977
3978 if(width <= 0.0f)
3979 {
3980 return error(GL_INVALID_VALUE);
3981 }
3982
3983 es2::Context *context = es2::getContext();
3984
3985 if(context)
3986 {
3987 context->setLineWidth(width);
3988 }
3989}
3990
3991void LinkProgram(GLuint program)
3992{
3993 TRACE("(GLuint program = %d)", program);
3994
3995 es2::Context *context = es2::getContext();
3996
3997 if(context)
3998 {
3999 es2::Program *programObject = context->getProgram(program);
4000
4001 if(!programObject)
4002 {
4003 if(context->getShader(program))
4004 {
4005 return error(GL_INVALID_OPERATION);
4006 }
4007 else
4008 {
4009 return error(GL_INVALID_VALUE);
4010 }
4011 }
4012
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004013 if(programObject == context->getCurrentProgram())
4014 {
4015 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4016 if(transformFeedback && transformFeedback->isActive())
4017 {
4018 return error(GL_INVALID_OPERATION);
4019 }
4020 }
4021
Nicolas Capens0bac2852016-05-07 06:09:58 -04004022 programObject->link();
4023 }
4024}
4025
4026void PixelStorei(GLenum pname, GLint param)
4027{
4028 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4029
4030 es2::Context *context = es2::getContext();
4031
4032 if(context)
4033 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004034 switch(pname)
4035 {
4036 case GL_UNPACK_ALIGNMENT:
4037 if(param != 1 && param != 2 && param != 4 && param != 8)
4038 {
4039 return error(GL_INVALID_VALUE);
4040 }
4041 context->setUnpackAlignment(param);
4042 break;
4043 case GL_PACK_ALIGNMENT:
4044 if(param != 1 && param != 2 && param != 4 && param != 8)
4045 {
4046 return error(GL_INVALID_VALUE);
4047 }
4048 context->setPackAlignment(param);
4049 break;
4050 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004051 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004052 {
Nicolas Capens83463112018-06-12 23:55:16 -04004053 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004054 }
Nicolas Capens83463112018-06-12 23:55:16 -04004055 context->setPackRowLength(param);
4056 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004057 case GL_PACK_SKIP_PIXELS:
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->setPackSkipPixels(param);
4063 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 case GL_PACK_SKIP_ROWS:
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->setPackSkipRows(param);
4070 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 case GL_UNPACK_ROW_LENGTH:
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->setUnpackRowLength(param);
4077 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 case GL_UNPACK_IMAGE_HEIGHT:
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->setUnpackImageHeight(param);
4084 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 case GL_UNPACK_SKIP_PIXELS:
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->setUnpackSkipPixels(param);
4091 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 case GL_UNPACK_SKIP_ROWS:
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->setUnpackSkipRows(param);
4098 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004099 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004100 if(param < 0)
4101 {
4102 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004103 }
Nicolas Capens83463112018-06-12 23:55:16 -04004104 context->setUnpackSkipImages(param);
4105 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004106 default:
4107 return error(GL_INVALID_ENUM);
4108 }
4109 }
4110}
4111
4112void PolygonOffset(GLfloat factor, GLfloat units)
4113{
4114 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4115
4116 es2::Context *context = es2::getContext();
4117
4118 if(context)
4119 {
4120 context->setPolygonOffsetParams(factor, units);
4121 }
4122}
4123
4124void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4125 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4126{
4127 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4128 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4129 x, y, width, height, format, type, bufSize, data);
4130
4131 if(width < 0 || height < 0 || bufSize < 0)
4132 {
4133 return error(GL_INVALID_VALUE);
4134 }
4135
4136 es2::Context *context = es2::getContext();
4137
4138 if(context)
4139 {
4140 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4141 }
4142}
4143
4144void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4145{
4146 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4147 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4148 x, y, width, height, format, type, pixels);
4149
4150 if(width < 0 || height < 0)
4151 {
4152 return error(GL_INVALID_VALUE);
4153 }
4154
4155 es2::Context *context = es2::getContext();
4156
4157 if(context)
4158 {
4159 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4160 }
4161}
4162
4163void ReleaseShaderCompiler(void)
4164{
4165 TRACE("()");
4166
4167 es2::Shader::releaseCompiler();
4168}
4169
Nicolas Capens400667e2017-03-29 14:40:14 -04004170void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004171{
4172 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4173 target, samples, internalformat, width, height);
4174
4175 switch(target)
4176 {
4177 case GL_RENDERBUFFER:
4178 break;
4179 default:
4180 return error(GL_INVALID_ENUM);
4181 }
4182
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004183 if(width < 0 || height < 0 || samples < 0 ||
4184 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4185 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004186 {
4187 return error(GL_INVALID_VALUE);
4188 }
4189
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004190 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004191 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004192 {
4193 return error(GL_INVALID_OPERATION);
4194 }
4195
Nicolas Capens0bac2852016-05-07 06:09:58 -04004196 es2::Context *context = es2::getContext();
4197
4198 if(context)
4199 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004200 GLuint handle = context->getRenderbufferName();
4201 if(handle == 0)
4202 {
4203 return error(GL_INVALID_OPERATION);
4204 }
4205
Nicolas Capens83463112018-06-12 23:55:16 -04004206 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004207 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004208 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004209 }
Nicolas Capens83463112018-06-12 23:55:16 -04004210 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004211 {
4212 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4213 }
Nicolas Capens83463112018-06-12 23:55:16 -04004214 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004215 {
4216 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4217 }
Nicolas Capens83463112018-06-12 23:55:16 -04004218 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004219 {
4220 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4221 }
4222 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004223 }
4224}
4225
Nicolas Capens400667e2017-03-29 14:40:14 -04004226void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4227{
4228 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4229}
4230
Nicolas Capens0bac2852016-05-07 06:09:58 -04004231void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4232{
Nicolas Capens400667e2017-03-29 14:40:14 -04004233 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004234}
4235
4236void SampleCoverage(GLclampf value, GLboolean invert)
4237{
4238 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4239
4240 es2::Context* context = es2::getContext();
4241
4242 if(context)
4243 {
4244 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4245 }
4246}
4247
4248void SetFenceNV(GLuint fence, GLenum condition)
4249{
4250 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4251
4252 if(condition != GL_ALL_COMPLETED_NV)
4253 {
4254 return error(GL_INVALID_ENUM);
4255 }
4256
4257 es2::Context *context = es2::getContext();
4258
4259 if(context)
4260 {
4261 es2::Fence *fenceObject = context->getFence(fence);
4262
4263 if(!fenceObject)
4264 {
4265 return error(GL_INVALID_OPERATION);
4266 }
4267
4268 fenceObject->setFence(condition);
4269 }
4270}
4271
4272void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4273{
4274 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4275
4276 if(width < 0 || height < 0)
4277 {
4278 return error(GL_INVALID_VALUE);
4279 }
4280
4281 es2::Context* context = es2::getContext();
4282
4283 if(context)
4284 {
4285 context->setScissorParams(x, y, width, height);
4286 }
4287}
4288
4289void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4290{
4291 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4292 "const GLvoid* binary = %p, GLsizei length = %d)",
4293 n, shaders, binaryformat, binary, length);
4294
4295 // No binary shader formats are supported.
4296 return error(GL_INVALID_ENUM);
4297}
4298
4299void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4300{
4301 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4302 shader, count, string, length);
4303
4304 if(count < 0)
4305 {
4306 return error(GL_INVALID_VALUE);
4307 }
4308
4309 es2::Context *context = es2::getContext();
4310
4311 if(context)
4312 {
4313 es2::Shader *shaderObject = context->getShader(shader);
4314
4315 if(!shaderObject)
4316 {
4317 if(context->getProgram(shader))
4318 {
4319 return error(GL_INVALID_OPERATION);
4320 }
4321 else
4322 {
4323 return error(GL_INVALID_VALUE);
4324 }
4325 }
4326
4327 shaderObject->setSource(count, string, length);
4328 }
4329}
4330
4331void StencilFunc(GLenum func, GLint ref, GLuint mask)
4332{
4333 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4334}
4335
4336void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4337{
4338 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4339
4340 switch(face)
4341 {
4342 case GL_FRONT:
4343 case GL_BACK:
4344 case GL_FRONT_AND_BACK:
4345 break;
4346 default:
4347 return error(GL_INVALID_ENUM);
4348 }
4349
4350 switch(func)
4351 {
4352 case GL_NEVER:
4353 case GL_ALWAYS:
4354 case GL_LESS:
4355 case GL_LEQUAL:
4356 case GL_EQUAL:
4357 case GL_GEQUAL:
4358 case GL_GREATER:
4359 case GL_NOTEQUAL:
4360 break;
4361 default:
4362 return error(GL_INVALID_ENUM);
4363 }
4364
4365 es2::Context *context = es2::getContext();
4366
4367 if(context)
4368 {
4369 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4370 {
4371 context->setStencilParams(func, ref, mask);
4372 }
4373
4374 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4375 {
4376 context->setStencilBackParams(func, ref, mask);
4377 }
4378 }
4379}
4380
4381void StencilMask(GLuint mask)
4382{
4383 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4384}
4385
4386void StencilMaskSeparate(GLenum face, GLuint mask)
4387{
4388 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4389
4390 switch(face)
4391 {
4392 case GL_FRONT:
4393 case GL_BACK:
4394 case GL_FRONT_AND_BACK:
4395 break;
4396 default:
4397 return error(GL_INVALID_ENUM);
4398 }
4399
4400 es2::Context *context = es2::getContext();
4401
4402 if(context)
4403 {
4404 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4405 {
4406 context->setStencilWritemask(mask);
4407 }
4408
4409 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4410 {
4411 context->setStencilBackWritemask(mask);
4412 }
4413 }
4414}
4415
4416void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4417{
4418 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4419}
4420
4421void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4422{
4423 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4424 face, fail, zfail, zpass);
4425
4426 switch(face)
4427 {
4428 case GL_FRONT:
4429 case GL_BACK:
4430 case GL_FRONT_AND_BACK:
4431 break;
4432 default:
4433 return error(GL_INVALID_ENUM);
4434 }
4435
4436 switch(fail)
4437 {
4438 case GL_ZERO:
4439 case GL_KEEP:
4440 case GL_REPLACE:
4441 case GL_INCR:
4442 case GL_DECR:
4443 case GL_INVERT:
4444 case GL_INCR_WRAP:
4445 case GL_DECR_WRAP:
4446 break;
4447 default:
4448 return error(GL_INVALID_ENUM);
4449 }
4450
4451 switch(zfail)
4452 {
4453 case GL_ZERO:
4454 case GL_KEEP:
4455 case GL_REPLACE:
4456 case GL_INCR:
4457 case GL_DECR:
4458 case GL_INVERT:
4459 case GL_INCR_WRAP:
4460 case GL_DECR_WRAP:
4461 break;
4462 default:
4463 return error(GL_INVALID_ENUM);
4464 }
4465
4466 switch(zpass)
4467 {
4468 case GL_ZERO:
4469 case GL_KEEP:
4470 case GL_REPLACE:
4471 case GL_INCR:
4472 case GL_DECR:
4473 case GL_INVERT:
4474 case GL_INCR_WRAP:
4475 case GL_DECR_WRAP:
4476 break;
4477 default:
4478 return error(GL_INVALID_ENUM);
4479 }
4480
4481 es2::Context *context = es2::getContext();
4482
4483 if(context)
4484 {
4485 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4486 {
4487 context->setStencilOperations(fail, zfail, zpass);
4488 }
4489
4490 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4491 {
4492 context->setStencilBackOperations(fail, zfail, zpass);
4493 }
4494 }
4495}
4496
4497GLboolean TestFenceNV(GLuint fence)
4498{
4499 TRACE("(GLuint fence = %d)", fence);
4500
4501 es2::Context *context = es2::getContext();
4502
4503 if(context)
4504 {
4505 es2::Fence *fenceObject = context->getFence(fence);
4506
4507 if(!fenceObject)
4508 {
4509 return error(GL_INVALID_OPERATION, GL_TRUE);
4510 }
4511
4512 return fenceObject->testFence();
4513 }
4514
4515 return GL_TRUE;
4516}
4517
4518void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004519 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004520{
4521 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004522 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4523 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004524
4525 if(!validImageSize(level, width, height))
4526 {
4527 return error(GL_INVALID_VALUE);
4528 }
4529
4530 es2::Context *context = es2::getContext();
4531
4532 if(context)
4533 {
Nicolas Capens83463112018-06-12 23:55:16 -04004534 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004535 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4536 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4537 {
4538 internalformat = GL_BGRA_EXT;
4539 }
4540
Nicolas Capens83463112018-06-12 23:55:16 -04004541 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004542 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004543 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004544 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004545 }
4546
4547 if(border != 0)
4548 {
4549 return error(GL_INVALID_VALUE);
4550 }
4551
4552 switch(target)
4553 {
Alexis Hetu46768622018-01-16 22:09:28 -05004554 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004555 if(level != 0)
4556 {
4557 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4558 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004559 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004560 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004561 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4562 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4563 {
4564 return error(GL_INVALID_VALUE);
4565 }
4566 break;
4567 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4569 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4570 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4571 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4572 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4573 if(width != height)
4574 {
4575 return error(GL_INVALID_VALUE);
4576 }
4577
4578 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4579 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4580 {
4581 return error(GL_INVALID_VALUE);
4582 }
4583 break;
4584 default:
4585 return error(GL_INVALID_ENUM);
4586 }
4587
Nicolas Capens5555af42017-12-14 13:14:03 -05004588 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004589 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004590 {
4591 return error(validationError);
4592 }
4593
Nicolas Capens894858a2018-03-22 00:55:23 -04004594 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4595
Alexis Hetu46768622018-01-16 22:09:28 -05004596 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004597 {
Alexis Hetu46768622018-01-16 22:09:28 -05004598 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004599
4600 if(!texture)
4601 {
4602 return error(GL_INVALID_OPERATION);
4603 }
4604
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004605 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004606 }
4607 else
4608 {
4609 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4610
4611 if(!texture)
4612 {
4613 return error(GL_INVALID_OPERATION);
4614 }
4615
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004616 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004617 }
4618 }
4619}
4620
4621void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4622{
4623 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4624
4625 es2::Context *context = es2::getContext();
4626
4627 if(context)
4628 {
4629 es2::Texture *texture;
4630
Nicolas Capens0bac2852016-05-07 06:09:58 -04004631 switch(target)
4632 {
Nicolas Capens83463112018-06-12 23:55:16 -04004633 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4634 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4635 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4636 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4637 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4638 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004639 default:
4640 return error(GL_INVALID_ENUM);
4641 }
4642
4643 switch(pname)
4644 {
4645 case GL_TEXTURE_WRAP_S:
4646 if(!texture->setWrapS((GLenum)param))
4647 {
4648 return error(GL_INVALID_ENUM);
4649 }
4650 break;
4651 case GL_TEXTURE_WRAP_T:
4652 if(!texture->setWrapT((GLenum)param))
4653 {
4654 return error(GL_INVALID_ENUM);
4655 }
4656 break;
4657 case GL_TEXTURE_WRAP_R_OES:
4658 if(!texture->setWrapR((GLenum)param))
4659 {
4660 return error(GL_INVALID_ENUM);
4661 }
4662 break;
4663 case GL_TEXTURE_MIN_FILTER:
4664 if(!texture->setMinFilter((GLenum)param))
4665 {
4666 return error(GL_INVALID_ENUM);
4667 }
4668 break;
4669 case GL_TEXTURE_MAG_FILTER:
4670 if(!texture->setMagFilter((GLenum)param))
4671 {
4672 return error(GL_INVALID_ENUM);
4673 }
4674 break;
4675 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4676 if(!texture->setMaxAnisotropy(param))
4677 {
4678 return error(GL_INVALID_VALUE);
4679 }
4680 break;
4681 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004682 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004683 {
4684 return error(GL_INVALID_VALUE);
4685 }
4686 break;
4687 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004688 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004689 {
4690 return error(GL_INVALID_VALUE);
4691 }
4692 break;
4693 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004694 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004695 {
4696 return error(GL_INVALID_VALUE);
4697 }
4698 break;
4699 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004700 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004701 {
4702 return error(GL_INVALID_VALUE);
4703 }
4704 break;
4705 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004706 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004707 {
4708 return error(GL_INVALID_VALUE);
4709 }
4710 break;
4711 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004712 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004713 {
4714 return error(GL_INVALID_VALUE);
4715 }
4716 break;
4717 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004718 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004719 {
4720 return error(GL_INVALID_VALUE);
4721 }
4722 break;
4723 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004724 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004725 {
4726 return error(GL_INVALID_VALUE);
4727 }
4728 break;
4729 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004730 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004731 {
4732 return error(GL_INVALID_VALUE);
4733 }
4734 break;
4735 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004736 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004737 {
4738 return error(GL_INVALID_VALUE);
4739 }
4740 break;
4741 default:
4742 return error(GL_INVALID_ENUM);
4743 }
4744 }
4745}
4746
4747void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4748{
4749 glTexParameterf(target, pname, *params);
4750}
4751
4752void TexParameteri(GLenum target, GLenum pname, GLint param)
4753{
4754 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4755
4756 es2::Context *context = es2::getContext();
4757
4758 if(context)
4759 {
4760 es2::Texture *texture;
4761
Nicolas Capens0bac2852016-05-07 06:09:58 -04004762 switch(target)
4763 {
Nicolas Capens83463112018-06-12 23:55:16 -04004764 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4765 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4766 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4767 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4768 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4769 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004770 default:
4771 return error(GL_INVALID_ENUM);
4772 }
4773
4774 switch(pname)
4775 {
4776 case GL_TEXTURE_WRAP_S:
4777 if(!texture->setWrapS((GLenum)param))
4778 {
4779 return error(GL_INVALID_ENUM);
4780 }
4781 break;
4782 case GL_TEXTURE_WRAP_T:
4783 if(!texture->setWrapT((GLenum)param))
4784 {
4785 return error(GL_INVALID_ENUM);
4786 }
4787 break;
4788 case GL_TEXTURE_WRAP_R_OES:
4789 if(!texture->setWrapR((GLenum)param))
4790 {
4791 return error(GL_INVALID_ENUM);
4792 }
4793 break;
4794 case GL_TEXTURE_MIN_FILTER:
4795 if(!texture->setMinFilter((GLenum)param))
4796 {
4797 return error(GL_INVALID_ENUM);
4798 }
4799 break;
4800 case GL_TEXTURE_MAG_FILTER:
4801 if(!texture->setMagFilter((GLenum)param))
4802 {
4803 return error(GL_INVALID_ENUM);
4804 }
4805 break;
4806 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4807 if(!texture->setMaxAnisotropy((GLfloat)param))
4808 {
4809 return error(GL_INVALID_VALUE);
4810 }
4811 break;
4812 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004813 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4814 {
4815 return error(GL_INVALID_OPERATION); // Base level has to be 0
4816 }
Nicolas Capens83463112018-06-12 23:55:16 -04004817 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004818 {
4819 return error(GL_INVALID_VALUE);
4820 }
4821 break;
4822 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004823 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004824 {
4825 return error(GL_INVALID_VALUE);
4826 }
4827 break;
4828 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004829 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004830 {
4831 return error(GL_INVALID_VALUE);
4832 }
4833 break;
4834 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004835 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004836 {
4837 return error(GL_INVALID_VALUE);
4838 }
4839 break;
4840 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004841 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004842 {
4843 return error(GL_INVALID_VALUE);
4844 }
4845 break;
4846 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004847 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004848 {
4849 return error(GL_INVALID_VALUE);
4850 }
4851 break;
4852 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004853 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004854 {
4855 return error(GL_INVALID_VALUE);
4856 }
4857 break;
4858 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004859 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004860 {
4861 return error(GL_INVALID_VALUE);
4862 }
4863 break;
4864 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004865 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004866 {
4867 return error(GL_INVALID_VALUE);
4868 }
4869 break;
4870 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004871 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004872 {
4873 return error(GL_INVALID_VALUE);
4874 }
4875 break;
4876 default:
4877 return error(GL_INVALID_ENUM);
4878 }
4879 }
4880}
4881
4882void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4883{
4884 glTexParameteri(target, pname, *params);
4885}
4886
4887void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004888 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004889{
4890 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4891 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004892 "const GLvoid* data = %p)",
4893 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004894
4895 if(!es2::IsTextureTarget(target))
4896 {
4897 return error(GL_INVALID_ENUM);
4898 }
4899
4900 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4901 {
4902 return error(GL_INVALID_VALUE);
4903 }
4904
4905 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4906 {
4907 return error(GL_INVALID_VALUE);
4908 }
4909
4910 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4911 {
4912 return error(GL_INVALID_VALUE);
4913 }
4914
Nicolas Capens0bac2852016-05-07 06:09:58 -04004915 es2::Context *context = es2::getContext();
4916
4917 if(context)
4918 {
Alexis Hetu46768622018-01-16 22:09:28 -05004919 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004920 {
Alexis Hetu46768622018-01-16 22:09:28 -05004921 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004922
Nicolas Capens83463112018-06-12 23:55:16 -04004923 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004924 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004925 {
4926 return error(validationError);
4927 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004928
Nicolas Capens5555af42017-12-14 13:14:03 -05004929 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004930 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004931 {
4932 return error(validationError);
4933 }
4934
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004935 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004936 }
4937 else if(es2::IsCubemapTextureTarget(target))
4938 {
4939 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4940
Nicolas Capens83463112018-06-12 23:55:16 -04004941 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004942 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004943 {
4944 return error(validationError);
4945 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004946
Nicolas Capens5555af42017-12-14 13:14:03 -05004947 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004948 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004949 {
4950 return error(validationError);
4951 }
4952
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004953 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004954 }
4955 else UNREACHABLE(target);
4956 }
4957}
4958
4959void Uniform1f(GLint location, GLfloat x)
4960{
4961 glUniform1fv(location, 1, &x);
4962}
4963
4964void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4965{
4966 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4967
4968 if(count < 0)
4969 {
4970 return error(GL_INVALID_VALUE);
4971 }
4972
Nicolas Capens0bac2852016-05-07 06:09:58 -04004973 es2::Context *context = es2::getContext();
4974
4975 if(context)
4976 {
4977 es2::Program *program = context->getCurrentProgram();
4978
4979 if(!program)
4980 {
4981 return error(GL_INVALID_OPERATION);
4982 }
4983
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004984 if(location == -1)
4985 {
4986 return;
4987 }
4988
Nicolas Capens0bac2852016-05-07 06:09:58 -04004989 if(!program->setUniform1fv(location, count, v))
4990 {
4991 return error(GL_INVALID_OPERATION);
4992 }
4993 }
4994}
4995
4996void Uniform1i(GLint location, GLint x)
4997{
4998 glUniform1iv(location, 1, &x);
4999}
5000
5001void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5002{
5003 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5004
5005 if(count < 0)
5006 {
5007 return error(GL_INVALID_VALUE);
5008 }
5009
Nicolas Capens0bac2852016-05-07 06:09:58 -04005010 es2::Context *context = es2::getContext();
5011
5012 if(context)
5013 {
5014 es2::Program *program = context->getCurrentProgram();
5015
5016 if(!program)
5017 {
5018 return error(GL_INVALID_OPERATION);
5019 }
5020
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005021 if(location == -1)
5022 {
5023 return;
5024 }
5025
Nicolas Capens0bac2852016-05-07 06:09:58 -04005026 if(!program->setUniform1iv(location, count, v))
5027 {
5028 return error(GL_INVALID_OPERATION);
5029 }
5030 }
5031}
5032
5033void Uniform2f(GLint location, GLfloat x, GLfloat y)
5034{
5035 GLfloat xy[2] = {x, y};
5036
5037 glUniform2fv(location, 1, (GLfloat*)&xy);
5038}
5039
5040void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5041{
5042 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5043
5044 if(count < 0)
5045 {
5046 return error(GL_INVALID_VALUE);
5047 }
5048
Nicolas Capens0bac2852016-05-07 06:09:58 -04005049 es2::Context *context = es2::getContext();
5050
5051 if(context)
5052 {
5053 es2::Program *program = context->getCurrentProgram();
5054
5055 if(!program)
5056 {
5057 return error(GL_INVALID_OPERATION);
5058 }
5059
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005060 if(location == -1)
5061 {
5062 return;
5063 }
5064
Nicolas Capens0bac2852016-05-07 06:09:58 -04005065 if(!program->setUniform2fv(location, count, v))
5066 {
5067 return error(GL_INVALID_OPERATION);
5068 }
5069 }
5070}
5071
5072void Uniform2i(GLint location, GLint x, GLint y)
5073{
5074 GLint xy[4] = {x, y};
5075
5076 glUniform2iv(location, 1, (GLint*)&xy);
5077}
5078
5079void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5080{
5081 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5082
5083 if(count < 0)
5084 {
5085 return error(GL_INVALID_VALUE);
5086 }
5087
Nicolas Capens0bac2852016-05-07 06:09:58 -04005088 es2::Context *context = es2::getContext();
5089
5090 if(context)
5091 {
5092 es2::Program *program = context->getCurrentProgram();
5093
5094 if(!program)
5095 {
5096 return error(GL_INVALID_OPERATION);
5097 }
5098
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005099 if(location == -1)
5100 {
5101 return;
5102 }
5103
Nicolas Capens0bac2852016-05-07 06:09:58 -04005104 if(!program->setUniform2iv(location, count, v))
5105 {
5106 return error(GL_INVALID_OPERATION);
5107 }
5108 }
5109}
5110
5111void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5112{
5113 GLfloat xyz[3] = {x, y, z};
5114
5115 glUniform3fv(location, 1, (GLfloat*)&xyz);
5116}
5117
5118void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5119{
5120 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5121
5122 if(count < 0)
5123 {
5124 return error(GL_INVALID_VALUE);
5125 }
5126
Nicolas Capens0bac2852016-05-07 06:09:58 -04005127 es2::Context *context = es2::getContext();
5128
5129 if(context)
5130 {
5131 es2::Program *program = context->getCurrentProgram();
5132
5133 if(!program)
5134 {
5135 return error(GL_INVALID_OPERATION);
5136 }
5137
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005138 if(location == -1)
5139 {
5140 return;
5141 }
5142
Nicolas Capens0bac2852016-05-07 06:09:58 -04005143 if(!program->setUniform3fv(location, count, v))
5144 {
5145 return error(GL_INVALID_OPERATION);
5146 }
5147 }
5148}
5149
5150void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5151{
5152 GLint xyz[3] = {x, y, z};
5153
5154 glUniform3iv(location, 1, (GLint*)&xyz);
5155}
5156
5157void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5158{
5159 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5160
5161 if(count < 0)
5162 {
5163 return error(GL_INVALID_VALUE);
5164 }
5165
Nicolas Capens0bac2852016-05-07 06:09:58 -04005166 es2::Context *context = es2::getContext();
5167
5168 if(context)
5169 {
5170 es2::Program *program = context->getCurrentProgram();
5171
5172 if(!program)
5173 {
5174 return error(GL_INVALID_OPERATION);
5175 }
5176
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005177 if(location == -1)
5178 {
5179 return;
5180 }
5181
Nicolas Capens0bac2852016-05-07 06:09:58 -04005182 if(!program->setUniform3iv(location, count, v))
5183 {
5184 return error(GL_INVALID_OPERATION);
5185 }
5186 }
5187}
5188
5189void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5190{
5191 GLfloat xyzw[4] = {x, y, z, w};
5192
5193 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5194}
5195
5196void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5197{
5198 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5199
5200 if(count < 0)
5201 {
5202 return error(GL_INVALID_VALUE);
5203 }
5204
Nicolas Capens0bac2852016-05-07 06:09:58 -04005205 es2::Context *context = es2::getContext();
5206
5207 if(context)
5208 {
5209 es2::Program *program = context->getCurrentProgram();
5210
5211 if(!program)
5212 {
5213 return error(GL_INVALID_OPERATION);
5214 }
5215
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005216 if(location == -1)
5217 {
5218 return;
5219 }
5220
Nicolas Capens0bac2852016-05-07 06:09:58 -04005221 if(!program->setUniform4fv(location, count, v))
5222 {
5223 return error(GL_INVALID_OPERATION);
5224 }
5225 }
5226}
5227
5228void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5229{
5230 GLint xyzw[4] = {x, y, z, w};
5231
5232 glUniform4iv(location, 1, (GLint*)&xyzw);
5233}
5234
5235void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5236{
5237 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5238
5239 if(count < 0)
5240 {
5241 return error(GL_INVALID_VALUE);
5242 }
5243
Nicolas Capens0bac2852016-05-07 06:09:58 -04005244 es2::Context *context = es2::getContext();
5245
5246 if(context)
5247 {
5248 es2::Program *program = context->getCurrentProgram();
5249
5250 if(!program)
5251 {
5252 return error(GL_INVALID_OPERATION);
5253 }
5254
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005255 if(location == -1)
5256 {
5257 return;
5258 }
5259
Nicolas Capens0bac2852016-05-07 06:09:58 -04005260 if(!program->setUniform4iv(location, count, v))
5261 {
5262 return error(GL_INVALID_OPERATION);
5263 }
5264 }
5265}
5266
5267void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5268{
5269 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5270 location, count, transpose, value);
5271
5272 if(count < 0)
5273 {
5274 return error(GL_INVALID_VALUE);
5275 }
5276
Nicolas Capens0bac2852016-05-07 06:09:58 -04005277 es2::Context *context = es2::getContext();
5278
5279 if(context)
5280 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005281 es2::Program *program = context->getCurrentProgram();
5282
5283 if(!program)
5284 {
5285 return error(GL_INVALID_OPERATION);
5286 }
5287
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005288 if(location == -1)
5289 {
5290 return;
5291 }
5292
Nicolas Capens0bac2852016-05-07 06:09:58 -04005293 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5294 {
5295 return error(GL_INVALID_OPERATION);
5296 }
5297 }
5298}
5299
5300void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5301{
5302 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5303 location, count, transpose, value);
5304
5305 if(count < 0)
5306 {
5307 return error(GL_INVALID_VALUE);
5308 }
5309
Nicolas Capens0bac2852016-05-07 06:09:58 -04005310 es2::Context *context = es2::getContext();
5311
5312 if(context)
5313 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005314 es2::Program *program = context->getCurrentProgram();
5315
5316 if(!program)
5317 {
5318 return error(GL_INVALID_OPERATION);
5319 }
5320
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005321 if(location == -1)
5322 {
5323 return;
5324 }
5325
Nicolas Capens0bac2852016-05-07 06:09:58 -04005326 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5327 {
5328 return error(GL_INVALID_OPERATION);
5329 }
5330 }
5331}
5332
5333void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5334{
5335 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5336 location, count, transpose, value);
5337
5338 if(count < 0)
5339 {
5340 return error(GL_INVALID_VALUE);
5341 }
5342
Nicolas Capens0bac2852016-05-07 06:09:58 -04005343 es2::Context *context = es2::getContext();
5344
5345 if(context)
5346 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005347 es2::Program *program = context->getCurrentProgram();
5348
5349 if(!program)
5350 {
5351 return error(GL_INVALID_OPERATION);
5352 }
5353
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005354 if(location == -1)
5355 {
5356 return;
5357 }
5358
Nicolas Capens0bac2852016-05-07 06:09:58 -04005359 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5360 {
5361 return error(GL_INVALID_OPERATION);
5362 }
5363 }
5364}
5365
5366void UseProgram(GLuint program)
5367{
5368 TRACE("(GLuint program = %d)", program);
5369
5370 es2::Context *context = es2::getContext();
5371
5372 if(context)
5373 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005374 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5375 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5376 {
5377 return error(GL_INVALID_OPERATION);
5378 }
5379
Nicolas Capens0bac2852016-05-07 06:09:58 -04005380 es2::Program *programObject = context->getProgram(program);
5381
5382 if(!programObject && program != 0)
5383 {
5384 if(context->getShader(program))
5385 {
5386 return error(GL_INVALID_OPERATION);
5387 }
5388 else
5389 {
5390 return error(GL_INVALID_VALUE);
5391 }
5392 }
5393
5394 if(program != 0 && !programObject->isLinked())
5395 {
5396 return error(GL_INVALID_OPERATION);
5397 }
5398
5399 context->useProgram(program);
5400 }
5401}
5402
5403void ValidateProgram(GLuint program)
5404{
5405 TRACE("(GLuint program = %d)", program);
5406
5407 es2::Context *context = es2::getContext();
5408
5409 if(context)
5410 {
5411 es2::Program *programObject = context->getProgram(program);
5412
5413 if(!programObject)
5414 {
5415 if(context->getShader(program))
5416 {
5417 return error(GL_INVALID_OPERATION);
5418 }
5419 else
5420 {
5421 return error(GL_INVALID_VALUE);
5422 }
5423 }
5424
Ben Vanik1fd3b282017-07-10 14:08:12 -07005425 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005426 }
5427}
5428
5429void VertexAttrib1f(GLuint index, GLfloat x)
5430{
5431 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5432
5433 if(index >= es2::MAX_VERTEX_ATTRIBS)
5434 {
5435 return error(GL_INVALID_VALUE);
5436 }
5437
5438 es2::Context *context = es2::getContext();
5439
5440 if(context)
5441 {
5442 GLfloat vals[4] = { x, 0, 0, 1 };
5443 context->setVertexAttrib(index, vals);
5444 }
5445}
5446
5447void VertexAttrib1fv(GLuint index, const GLfloat* values)
5448{
5449 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5450
5451 if(index >= es2::MAX_VERTEX_ATTRIBS)
5452 {
5453 return error(GL_INVALID_VALUE);
5454 }
5455
5456 es2::Context *context = es2::getContext();
5457
5458 if(context)
5459 {
5460 GLfloat vals[4] = { values[0], 0, 0, 1 };
5461 context->setVertexAttrib(index, vals);
5462 }
5463}
5464
5465void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5466{
5467 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5468
5469 if(index >= es2::MAX_VERTEX_ATTRIBS)
5470 {
5471 return error(GL_INVALID_VALUE);
5472 }
5473
5474 es2::Context *context = es2::getContext();
5475
5476 if(context)
5477 {
5478 GLfloat vals[4] = { x, y, 0, 1 };
5479 context->setVertexAttrib(index, vals);
5480 }
5481}
5482
5483void VertexAttrib2fv(GLuint index, const GLfloat* values)
5484{
5485 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5486
5487 if(index >= es2::MAX_VERTEX_ATTRIBS)
5488 {
5489 return error(GL_INVALID_VALUE);
5490 }
5491
5492 es2::Context *context = es2::getContext();
5493
5494 if(context)
5495 {
5496 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5497 context->setVertexAttrib(index, vals);
5498 }
5499}
5500
5501void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5502{
5503 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5504
5505 if(index >= es2::MAX_VERTEX_ATTRIBS)
5506 {
5507 return error(GL_INVALID_VALUE);
5508 }
5509
5510 es2::Context *context = es2::getContext();
5511
5512 if(context)
5513 {
5514 GLfloat vals[4] = { x, y, z, 1 };
5515 context->setVertexAttrib(index, vals);
5516 }
5517}
5518
5519void VertexAttrib3fv(GLuint index, const GLfloat* values)
5520{
5521 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5522
5523 if(index >= es2::MAX_VERTEX_ATTRIBS)
5524 {
5525 return error(GL_INVALID_VALUE);
5526 }
5527
5528 es2::Context *context = es2::getContext();
5529
5530 if(context)
5531 {
5532 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5533 context->setVertexAttrib(index, vals);
5534 }
5535}
5536
5537void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5538{
5539 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5540
5541 if(index >= es2::MAX_VERTEX_ATTRIBS)
5542 {
5543 return error(GL_INVALID_VALUE);
5544 }
5545
5546 es2::Context *context = es2::getContext();
5547
5548 if(context)
5549 {
5550 GLfloat vals[4] = { x, y, z, w };
5551 context->setVertexAttrib(index, vals);
5552 }
5553}
5554
5555void VertexAttrib4fv(GLuint index, const GLfloat* values)
5556{
5557 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5558
5559 if(index >= es2::MAX_VERTEX_ATTRIBS)
5560 {
5561 return error(GL_INVALID_VALUE);
5562 }
5563
5564 es2::Context *context = es2::getContext();
5565
5566 if(context)
5567 {
5568 context->setVertexAttrib(index, values);
5569 }
5570}
5571
5572void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5573{
5574 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5575 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5576 index, size, type, normalized, stride, ptr);
5577
5578 if(index >= es2::MAX_VERTEX_ATTRIBS)
5579 {
5580 return error(GL_INVALID_VALUE);
5581 }
5582
5583 if(size < 1 || size > 4)
5584 {
5585 return error(GL_INVALID_VALUE);
5586 }
5587
Nicolas Capens0bac2852016-05-07 06:09:58 -04005588 switch(type)
5589 {
5590 case GL_BYTE:
5591 case GL_UNSIGNED_BYTE:
5592 case GL_SHORT:
5593 case GL_UNSIGNED_SHORT:
5594 case GL_FIXED:
5595 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005596 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005597 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005598 break;
5599 case GL_INT_2_10_10_10_REV:
5600 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005601 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005602 {
Nicolas Capens83463112018-06-12 23:55:16 -04005603 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005604 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005605 case GL_INT:
5606 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005607 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005608 default:
5609 return error(GL_INVALID_ENUM);
5610 }
5611
5612 if(stride < 0)
5613 {
5614 return error(GL_INVALID_VALUE);
5615 }
5616
5617 es2::Context *context = es2::getContext();
5618
5619 if(context)
5620 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005621 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5622 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5623 {
5624 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5625 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5626 return error(GL_INVALID_OPERATION);
5627 }
5628
Alexis Hetu6f284032017-12-11 15:19:36 -05005629 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005630 }
5631}
5632
5633void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5634{
5635 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5636
5637 if(width < 0 || height < 0)
5638 {
5639 return error(GL_INVALID_VALUE);
5640 }
5641
5642 es2::Context *context = es2::getContext();
5643
5644 if(context)
5645 {
5646 context->setViewportParams(x, y, width, height);
5647 }
5648}
5649
Alexis Hetub9dda642016-10-06 11:25:32 -04005650static 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 -04005651{
5652 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5653 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5654 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5655 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5656
5657 switch(filter)
5658 {
5659 case GL_NEAREST:
5660 break;
5661 default:
5662 return error(GL_INVALID_ENUM);
5663 }
5664
5665 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5666 {
5667 return error(GL_INVALID_VALUE);
5668 }
5669
5670 es2::Context *context = es2::getContext();
5671
5672 if(context)
5673 {
5674 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5675 {
5676 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5677 return error(GL_INVALID_OPERATION);
5678 }
5679
Alexis Hetub9dda642016-10-06 11:25:32 -04005680 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005681 }
5682}
5683
Alexis Hetub9dda642016-10-06 11:25:32 -04005684void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5685{
5686 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5687}
5688
Nicolas Capens0bac2852016-05-07 06:09:58 -04005689void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5690 GLbitfield mask, GLenum filter)
5691{
5692 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5693 {
5694 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5695 return error(GL_INVALID_OPERATION);
5696 }
5697
Alexis Hetub9dda642016-10-06 11:25:32 -04005698 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005699}
5700
5701void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005702 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005703{
5704 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5705 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005706 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5707 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005708
5709 switch(target)
5710 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005711 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005712 switch(format)
5713 {
5714 case GL_DEPTH_COMPONENT:
5715 case GL_DEPTH_STENCIL_OES:
5716 return error(GL_INVALID_OPERATION);
5717 default:
5718 break;
5719 }
5720 break;
5721 default:
5722 return error(GL_INVALID_ENUM);
5723 }
5724
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005725 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005726 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005727 return error(GL_INVALID_OPERATION);
5728 }
5729
Nicolas Capens83463112018-06-12 23:55:16 -04005730 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005731 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005732 {
5733 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005734 }
5735
5736 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5737 {
5738 return error(GL_INVALID_VALUE);
5739 }
5740
Nicolas Capensefdf1032018-05-08 16:03:16 -04005741 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005742 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5743 {
5744 return error(GL_INVALID_VALUE);
5745 }
5746
5747 if(border != 0)
5748 {
5749 return error(GL_INVALID_VALUE);
5750 }
5751
5752 es2::Context *context = es2::getContext();
5753
5754 if(context)
5755 {
5756 es2::Texture3D *texture = context->getTexture3D();
5757
5758 if(!texture)
5759 {
5760 return error(GL_INVALID_OPERATION);
5761 }
5762
Nicolas Capens2fc90512018-01-23 22:24:22 +00005763 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005764 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005765 {
5766 return error(validationError);
5767 }
5768
Nicolas Capens894858a2018-03-22 00:55:23 -04005769 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005770 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005771 }
5772}
5773
Alexis Hetu53f48092016-06-17 14:08:06 -04005774void 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 -04005775{
5776 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5777 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005778 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5779 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005780
5781 switch(target)
5782 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005783 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005784 break;
5785 default:
5786 return error(GL_INVALID_ENUM);
5787 }
5788
Nicolas Capens0bac2852016-05-07 06:09:58 -04005789 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5790 {
5791 return error(GL_INVALID_VALUE);
5792 }
5793
5794 if((width < 0) || (height < 0) || (depth < 0))
5795 {
5796 return error(GL_INVALID_VALUE);
5797 }
5798
5799 es2::Context *context = es2::getContext();
5800
5801 if(context)
5802 {
5803 es2::Texture3D *texture = context->getTexture3D();
5804
Nicolas Capens83463112018-06-12 23:55:16 -04005805 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005806 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005807 {
5808 return error(validationError);
5809 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005810
Nicolas Capens5555af42017-12-14 13:14:03 -05005811 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005812 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005813 {
5814 return error(validationError);
5815 }
5816
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005817 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005818 }
5819}
5820
5821void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5822{
5823 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5824 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5825 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5826
5827 switch(target)
5828 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005829 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005830 break;
5831 default:
5832 return error(GL_INVALID_ENUM);
5833 }
5834
5835 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5836 {
5837 return error(GL_INVALID_VALUE);
5838 }
5839
5840 es2::Context *context = es2::getContext();
5841
5842 if(context)
5843 {
5844 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5845
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005846 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005847 {
5848 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5849 }
5850
5851 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5852
5853 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5854 {
5855 return error(GL_INVALID_OPERATION);
5856 }
5857
5858 es2::Texture3D *texture = context->getTexture3D();
5859
Nicolas Capens83463112018-06-12 23:55:16 -04005860 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 -05005861 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005862 {
5863 return error(validationError);
5864 }
5865
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005866 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005867 }
5868}
5869
5870void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5871{
5872 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5873 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5874 target, level, internalformat, width, height, depth, border, imageSize, data);
5875
5876 switch(target)
5877 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005878 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005879 break;
5880 default:
5881 return error(GL_INVALID_ENUM);
5882 }
5883
5884 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5885 {
5886 return error(GL_INVALID_VALUE);
5887 }
5888
Nicolas Capensefdf1032018-05-08 16:03:16 -04005889 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005890 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5891 {
5892 return error(GL_INVALID_VALUE);
5893 }
5894
Nicolas Capens83463112018-06-12 23:55:16 -04005895 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005896 {
Nicolas Capens03589982018-02-01 17:28:32 -05005897 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005898 }
5899
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005900 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005901 {
5902 return error(GL_INVALID_VALUE);
5903 }
5904
5905 es2::Context *context = es2::getContext();
5906
5907 if(context)
5908 {
5909 es2::Texture3D *texture = context->getTexture3D();
5910
5911 if(!texture)
5912 {
5913 return error(GL_INVALID_OPERATION);
5914 }
5915
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005916 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005917
Nicolas Capense65f5642018-02-26 17:47:06 -05005918 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005919 {
5920 return error(validationError);
5921 }
5922
Nicolas Capens0bac2852016-05-07 06:09:58 -04005923 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5924 }
5925}
5926
5927void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5928{
5929 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5930 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5931 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5932 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5933
5934 switch(target)
5935 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005936 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005937 break;
5938 default:
5939 return error(GL_INVALID_ENUM);
5940 }
5941
5942 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5943 {
5944 return error(GL_INVALID_VALUE);
5945 }
5946
5947 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5948 {
5949 return error(GL_INVALID_VALUE);
5950 }
5951
Nicolas Capens83463112018-06-12 23:55:16 -04005952 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005953 {
Nicolas Capens03589982018-02-01 17:28:32 -05005954 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005955 }
5956
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005957 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005958 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005959 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005960 }
5961
5962 es2::Context *context = es2::getContext();
5963
5964 if(context)
5965 {
5966 es2::Texture3D *texture = context->getTexture3D();
5967
5968 if(!texture)
5969 {
5970 return error(GL_INVALID_OPERATION);
5971 }
5972
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005973 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005974 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005975 {
5976 return error(validationError);
5977 }
5978
5979 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005980 }
5981}
5982
5983void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5984{
5985 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5986 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5987
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005988 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005989 {
5990 return error(GL_INVALID_ENUM);
5991 }
5992
5993 es2::Context *context = es2::getContext();
5994
5995 if(context)
5996 {
5997 if(texture == 0)
5998 {
5999 textarget = GL_NONE;
6000 }
6001 else
6002 {
6003 es2::Texture *tex = context->getTexture(texture);
6004
6005 if(!tex)
6006 {
6007 return error(GL_INVALID_OPERATION);
6008 }
6009
6010 if(tex->isCompressed(textarget, level))
6011 {
6012 return error(GL_INVALID_OPERATION);
6013 }
6014
6015 switch(textarget)
6016 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006017 case GL_TEXTURE_3D:
6018 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006019 {
6020 return error(GL_INVALID_OPERATION);
6021 }
6022 break;
6023 default:
6024 return error(GL_INVALID_ENUM);
6025 }
6026
6027 if(level != 0)
6028 {
6029 return error(GL_INVALID_VALUE);
6030 }
6031 }
6032
6033 es2::Framebuffer *framebuffer = nullptr;
6034 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006035 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006036 {
6037 framebuffer = context->getReadFramebuffer();
6038 framebufferName = context->getReadFramebufferName();
6039 }
6040 else
6041 {
6042 framebuffer = context->getDrawFramebuffer();
6043 framebufferName = context->getDrawFramebufferName();
6044 }
6045
6046 if(framebufferName == 0 || !framebuffer)
6047 {
6048 return error(GL_INVALID_OPERATION);
6049 }
6050
Nicolas Capens0bac2852016-05-07 06:09:58 -04006051 switch(attachment)
6052 {
Nicolas Capens83463112018-06-12 23:55:16 -04006053 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6054 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6055 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006056 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6057 {
6058 return error(GL_INVALID_ENUM);
6059 }
6060 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6061 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006062 }
6063 }
6064}
6065
6066void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6067{
6068 if(egl::getClientVersion() == 1)
6069 {
6070 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6071 }
6072
6073 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6074
6075 switch(target)
6076 {
6077 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006078 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006079 case GL_TEXTURE_EXTERNAL_OES:
6080 break;
6081 default:
6082 return error(GL_INVALID_ENUM);
6083 }
6084
Nicolas Capens0bac2852016-05-07 06:09:58 -04006085 es2::Context *context = es2::getContext();
6086
6087 if(context)
6088 {
Alexis Hetu46768622018-01-16 22:09:28 -05006089 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006090
6091 if(!texture)
6092 {
6093 return error(GL_INVALID_OPERATION);
6094 }
6095
Nicolas Capens58df2f62016-06-07 14:48:56 -04006096 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006097
Nicolas Capens58df2f62016-06-07 14:48:56 -04006098 if(!eglImage)
6099 {
6100 return error(GL_INVALID_OPERATION);
6101 }
6102
6103 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006104 }
6105}
6106
6107void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6108{
6109 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6110
6111 UNIMPLEMENTED();
6112}
6113
6114GLboolean IsRenderbufferOES(GLuint renderbuffer)
6115{
6116 return IsRenderbuffer(renderbuffer);
6117}
6118
6119void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6120{
6121 BindRenderbuffer(target, renderbuffer);
6122}
6123
6124void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6125{
6126 DeleteRenderbuffers(n, renderbuffers);
6127}
6128
6129void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6130{
6131 GenRenderbuffers(n, renderbuffers);
6132}
6133
6134void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6135{
6136 RenderbufferStorage(target, internalformat, width, height);
6137}
6138
6139void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6140{
6141 GetRenderbufferParameteriv(target, pname, params);
6142}
6143
6144GLboolean IsFramebufferOES(GLuint framebuffer)
6145{
6146 return IsFramebuffer(framebuffer);
6147}
6148
6149void BindFramebufferOES(GLenum target, GLuint framebuffer)
6150{
6151 BindFramebuffer(target, framebuffer);
6152}
6153
6154void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6155{
6156 DeleteFramebuffers(n, framebuffers);
6157}
6158
6159void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6160{
6161 GenFramebuffers(n, framebuffers);
6162}
6163
6164GLenum CheckFramebufferStatusOES(GLenum target)
6165{
6166 return CheckFramebufferStatus(target);
6167}
6168
6169void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6170{
6171 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6172}
6173
6174void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6175{
6176 FramebufferTexture2D(target, attachment, textarget, texture, level);
6177}
6178
6179void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6180{
6181 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6182}
6183
6184void GenerateMipmapOES(GLenum target)
6185{
6186 GenerateMipmap(target);
6187}
6188
6189void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6190{
6191 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6192
6193 if(n < 0 || n > MAX_DRAW_BUFFERS)
6194 {
6195 return error(GL_INVALID_VALUE);
6196 }
6197
6198 es2::Context *context = es2::getContext();
6199
6200 if(context)
6201 {
6202 GLuint drawFramebufferName = context->getDrawFramebufferName();
6203
6204 if((drawFramebufferName == 0) && (n != 1))
6205 {
6206 return error(GL_INVALID_OPERATION);
6207 }
6208
6209 for(unsigned int i = 0; i < (unsigned)n; i++)
6210 {
6211 switch(bufs[i])
6212 {
6213 case GL_BACK:
6214 if(drawFramebufferName != 0)
6215 {
6216 return error(GL_INVALID_OPERATION);
6217 }
6218 break;
6219 case GL_NONE:
6220 break;
6221 case GL_COLOR_ATTACHMENT0_EXT:
6222 case GL_COLOR_ATTACHMENT1_EXT:
6223 case GL_COLOR_ATTACHMENT2_EXT:
6224 case GL_COLOR_ATTACHMENT3_EXT:
6225 case GL_COLOR_ATTACHMENT4_EXT:
6226 case GL_COLOR_ATTACHMENT5_EXT:
6227 case GL_COLOR_ATTACHMENT6_EXT:
6228 case GL_COLOR_ATTACHMENT7_EXT:
6229 case GL_COLOR_ATTACHMENT8_EXT:
6230 case GL_COLOR_ATTACHMENT9_EXT:
6231 case GL_COLOR_ATTACHMENT10_EXT:
6232 case GL_COLOR_ATTACHMENT11_EXT:
6233 case GL_COLOR_ATTACHMENT12_EXT:
6234 case GL_COLOR_ATTACHMENT13_EXT:
6235 case GL_COLOR_ATTACHMENT14_EXT:
6236 case GL_COLOR_ATTACHMENT15_EXT:
6237 {
6238 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6239
6240 if(index >= MAX_COLOR_ATTACHMENTS)
6241 {
6242 return error(GL_INVALID_OPERATION);
6243 }
6244
6245 if(index != i)
6246 {
6247 return error(GL_INVALID_OPERATION);
6248 }
6249
6250 if(drawFramebufferName == 0)
6251 {
6252 return error(GL_INVALID_OPERATION);
6253 }
6254 }
6255 break;
6256 default:
6257 return error(GL_INVALID_ENUM);
6258 }
6259 }
6260
6261 context->setFramebufferDrawBuffers(n, bufs);
6262 }
6263}
6264
6265}
6266
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006267extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006268{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006269 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006270 {
6271 const char *name;
6272 __eglMustCastToProperFunctionPointerType address;
6273 };
6274
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006275 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006276 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006277 bool operator()(const Function &a, const Function &b) const
6278 {
6279 return strcmp(a.name, b.name) < 0;
6280 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006281 };
6282
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006283 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6284 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6285 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006286 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006287 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6288
6289 FUNCTION(glActiveTexture),
6290 FUNCTION(glAttachShader),
6291 FUNCTION(glBeginQuery),
6292 FUNCTION(glBeginQueryEXT),
6293 FUNCTION(glBeginTransformFeedback),
6294 FUNCTION(glBindAttribLocation),
6295 FUNCTION(glBindBuffer),
6296 FUNCTION(glBindBufferBase),
6297 FUNCTION(glBindBufferRange),
6298 FUNCTION(glBindFramebuffer),
6299 FUNCTION(glBindFramebufferOES),
6300 FUNCTION(glBindRenderbuffer),
6301 FUNCTION(glBindRenderbufferOES),
6302 FUNCTION(glBindSampler),
6303 FUNCTION(glBindTexture),
6304 FUNCTION(glBindTransformFeedback),
6305 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006306 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006307 FUNCTION(glBlendColor),
6308 FUNCTION(glBlendEquation),
6309 FUNCTION(glBlendEquationSeparate),
6310 FUNCTION(glBlendFunc),
6311 FUNCTION(glBlendFuncSeparate),
6312 FUNCTION(glBlitFramebuffer),
6313 FUNCTION(glBlitFramebufferANGLE),
6314 FUNCTION(glBufferData),
6315 FUNCTION(glBufferSubData),
6316 FUNCTION(glCheckFramebufferStatus),
6317 FUNCTION(glCheckFramebufferStatusOES),
6318 FUNCTION(glClear),
6319 FUNCTION(glClearBufferfi),
6320 FUNCTION(glClearBufferfv),
6321 FUNCTION(glClearBufferiv),
6322 FUNCTION(glClearBufferuiv),
6323 FUNCTION(glClearColor),
6324 FUNCTION(glClearDepthf),
6325 FUNCTION(glClearStencil),
6326 FUNCTION(glClientWaitSync),
6327 FUNCTION(glColorMask),
6328 FUNCTION(glCompileShader),
6329 FUNCTION(glCompressedTexImage2D),
6330 FUNCTION(glCompressedTexImage3D),
6331 FUNCTION(glCompressedTexSubImage2D),
6332 FUNCTION(glCompressedTexSubImage3D),
6333 FUNCTION(glCopyBufferSubData),
6334 FUNCTION(glCopyTexImage2D),
6335 FUNCTION(glCopyTexSubImage2D),
6336 FUNCTION(glCopyTexSubImage3D),
6337 FUNCTION(glCreateProgram),
6338 FUNCTION(glCreateShader),
6339 FUNCTION(glCullFace),
6340 FUNCTION(glDeleteBuffers),
6341 FUNCTION(glDeleteFencesNV),
6342 FUNCTION(glDeleteFramebuffers),
6343 FUNCTION(glDeleteFramebuffersOES),
6344 FUNCTION(glDeleteProgram),
6345 FUNCTION(glDeleteQueries),
6346 FUNCTION(glDeleteQueriesEXT),
6347 FUNCTION(glDeleteRenderbuffers),
6348 FUNCTION(glDeleteRenderbuffersOES),
6349 FUNCTION(glDeleteSamplers),
6350 FUNCTION(glDeleteShader),
6351 FUNCTION(glDeleteSync),
6352 FUNCTION(glDeleteTextures),
6353 FUNCTION(glDeleteTransformFeedbacks),
6354 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006355 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006356 FUNCTION(glDepthFunc),
Nicolas Capens659d89e2018-06-22 13:57:37 -04006357 //FUNCTION(DepthFunc),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006358 FUNCTION(glDepthMask),
6359 FUNCTION(glDepthRangef),
6360 FUNCTION(glDetachShader),
6361 FUNCTION(glDisable),
6362 FUNCTION(glDisableVertexAttribArray),
6363 FUNCTION(glDrawArrays),
6364 FUNCTION(glDrawArraysInstanced),
6365 FUNCTION(glDrawBuffers),
6366 FUNCTION(glDrawBuffersEXT),
6367 FUNCTION(glDrawElements),
6368 FUNCTION(glDrawElementsInstanced),
6369 FUNCTION(glDrawRangeElements),
6370 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6371 FUNCTION(glEGLImageTargetTexture2DOES),
6372 FUNCTION(glEnable),
6373 FUNCTION(glEnableVertexAttribArray),
6374 FUNCTION(glEndQuery),
6375 FUNCTION(glEndQueryEXT),
6376 FUNCTION(glEndTransformFeedback),
6377 FUNCTION(glFenceSync),
6378 FUNCTION(glFinish),
6379 FUNCTION(glFinishFenceNV),
6380 FUNCTION(glFlush),
6381 FUNCTION(glFlushMappedBufferRange),
6382 FUNCTION(glFramebufferRenderbuffer),
6383 FUNCTION(glFramebufferRenderbufferOES),
6384 FUNCTION(glFramebufferTexture2D),
6385 FUNCTION(glFramebufferTexture2DOES),
6386 FUNCTION(glFramebufferTextureLayer),
6387 FUNCTION(glFrontFace),
6388 FUNCTION(glGenBuffers),
6389 FUNCTION(glGenFencesNV),
6390 FUNCTION(glGenFramebuffers),
6391 FUNCTION(glGenFramebuffersOES),
6392 FUNCTION(glGenQueries),
6393 FUNCTION(glGenQueriesEXT),
6394 FUNCTION(glGenRenderbuffers),
6395 FUNCTION(glGenRenderbuffersOES),
6396 FUNCTION(glGenSamplers),
6397 FUNCTION(glGenTextures),
6398 FUNCTION(glGenTransformFeedbacks),
6399 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006400 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006401 FUNCTION(glGenerateMipmap),
6402 FUNCTION(glGenerateMipmapOES),
6403 FUNCTION(glGetActiveAttrib),
6404 FUNCTION(glGetActiveUniform),
6405 FUNCTION(glGetActiveUniformBlockName),
6406 FUNCTION(glGetActiveUniformBlockiv),
6407 FUNCTION(glGetActiveUniformsiv),
6408 FUNCTION(glGetAttachedShaders),
6409 FUNCTION(glGetAttribLocation),
6410 FUNCTION(glGetBooleanv),
6411 FUNCTION(glGetBufferParameteri64v),
6412 FUNCTION(glGetBufferParameteriv),
6413 FUNCTION(glGetBufferPointerv),
6414 FUNCTION(glGetError),
6415 FUNCTION(glGetFenceivNV),
6416 FUNCTION(glGetFloatv),
6417 FUNCTION(glGetFragDataLocation),
6418 FUNCTION(glGetFramebufferAttachmentParameteriv),
6419 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6420 FUNCTION(glGetGraphicsResetStatusEXT),
6421 FUNCTION(glGetInteger64i_v),
6422 FUNCTION(glGetInteger64v),
6423 FUNCTION(glGetIntegeri_v),
6424 FUNCTION(glGetIntegerv),
6425 FUNCTION(glGetInternalformativ),
6426 FUNCTION(glGetProgramBinary),
6427 FUNCTION(glGetProgramInfoLog),
6428 FUNCTION(glGetProgramiv),
6429 FUNCTION(glGetQueryObjectuiv),
6430 FUNCTION(glGetQueryObjectuivEXT),
6431 FUNCTION(glGetQueryiv),
6432 FUNCTION(glGetQueryivEXT),
6433 FUNCTION(glGetRenderbufferParameteriv),
6434 FUNCTION(glGetRenderbufferParameterivOES),
6435 FUNCTION(glGetSamplerParameterfv),
6436 FUNCTION(glGetSamplerParameteriv),
6437 FUNCTION(glGetShaderInfoLog),
6438 FUNCTION(glGetShaderPrecisionFormat),
6439 FUNCTION(glGetShaderSource),
6440 FUNCTION(glGetShaderiv),
6441 FUNCTION(glGetString),
6442 FUNCTION(glGetStringi),
6443 FUNCTION(glGetSynciv),
6444 FUNCTION(glGetTexParameterfv),
6445 FUNCTION(glGetTexParameteriv),
6446 FUNCTION(glGetTransformFeedbackVarying),
6447 FUNCTION(glGetUniformBlockIndex),
6448 FUNCTION(glGetUniformIndices),
6449 FUNCTION(glGetUniformLocation),
6450 FUNCTION(glGetUniformfv),
6451 FUNCTION(glGetUniformiv),
6452 FUNCTION(glGetUniformuiv),
6453 FUNCTION(glGetVertexAttribIiv),
6454 FUNCTION(glGetVertexAttribIuiv),
6455 FUNCTION(glGetVertexAttribPointerv),
6456 FUNCTION(glGetVertexAttribfv),
6457 FUNCTION(glGetVertexAttribiv),
6458 FUNCTION(glGetnUniformfvEXT),
6459 FUNCTION(glGetnUniformivEXT),
6460 FUNCTION(glHint),
6461 FUNCTION(glInvalidateFramebuffer),
6462 FUNCTION(glInvalidateSubFramebuffer),
6463 FUNCTION(glIsBuffer),
6464 FUNCTION(glIsEnabled),
6465 FUNCTION(glIsFenceNV),
6466 FUNCTION(glIsFramebuffer),
6467 FUNCTION(glIsFramebufferOES),
6468 FUNCTION(glIsProgram),
6469 FUNCTION(glIsQuery),
6470 FUNCTION(glIsQueryEXT),
6471 FUNCTION(glIsRenderbuffer),
6472 FUNCTION(glIsRenderbufferOES),
6473 FUNCTION(glIsSampler),
6474 FUNCTION(glIsShader),
6475 FUNCTION(glIsSync),
6476 FUNCTION(glIsTexture),
6477 FUNCTION(glIsTransformFeedback),
6478 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006479 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006480 FUNCTION(glLineWidth),
6481 FUNCTION(glLinkProgram),
6482 FUNCTION(glMapBufferRange),
6483 FUNCTION(glPauseTransformFeedback),
6484 FUNCTION(glPixelStorei),
6485 FUNCTION(glPolygonOffset),
6486 FUNCTION(glProgramBinary),
6487 FUNCTION(glProgramParameteri),
6488 FUNCTION(glReadBuffer),
6489 FUNCTION(glReadPixels),
6490 FUNCTION(glReadnPixelsEXT),
6491 FUNCTION(glReleaseShaderCompiler),
6492 FUNCTION(glRenderbufferStorage),
6493 FUNCTION(glRenderbufferStorageMultisample),
6494 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6495 FUNCTION(glRenderbufferStorageOES),
6496 FUNCTION(glResumeTransformFeedback),
6497 FUNCTION(glSampleCoverage),
6498 FUNCTION(glSamplerParameterf),
6499 FUNCTION(glSamplerParameterfv),
6500 FUNCTION(glSamplerParameteri),
6501 FUNCTION(glSamplerParameteriv),
6502 FUNCTION(glScissor),
6503 FUNCTION(glSetFenceNV),
6504 FUNCTION(glShaderBinary),
6505 FUNCTION(glShaderSource),
6506 FUNCTION(glStencilFunc),
6507 FUNCTION(glStencilFuncSeparate),
6508 FUNCTION(glStencilMask),
6509 FUNCTION(glStencilMaskSeparate),
6510 FUNCTION(glStencilOp),
6511 FUNCTION(glStencilOpSeparate),
6512 FUNCTION(glTestFenceNV),
6513 FUNCTION(glTexImage2D),
6514 FUNCTION(glTexImage3D),
6515 FUNCTION(glTexImage3DOES),
6516 FUNCTION(glTexParameterf),
6517 FUNCTION(glTexParameterfv),
6518 FUNCTION(glTexParameteri),
6519 FUNCTION(glTexParameteriv),
6520 FUNCTION(glTexStorage2D),
6521 FUNCTION(glTexStorage3D),
6522 FUNCTION(glTexSubImage2D),
6523 FUNCTION(glTexSubImage3D),
6524 FUNCTION(glTransformFeedbackVaryings),
6525 FUNCTION(glUniform1f),
6526 FUNCTION(glUniform1fv),
6527 FUNCTION(glUniform1i),
6528 FUNCTION(glUniform1iv),
6529 FUNCTION(glUniform1ui),
6530 FUNCTION(glUniform1uiv),
6531 FUNCTION(glUniform2f),
6532 FUNCTION(glUniform2fv),
6533 FUNCTION(glUniform2i),
6534 FUNCTION(glUniform2iv),
6535 FUNCTION(glUniform2ui),
6536 FUNCTION(glUniform2uiv),
6537 FUNCTION(glUniform3f),
6538 FUNCTION(glUniform3fv),
6539 FUNCTION(glUniform3i),
6540 FUNCTION(glUniform3iv),
6541 FUNCTION(glUniform3ui),
6542 FUNCTION(glUniform3uiv),
6543 FUNCTION(glUniform4f),
6544 FUNCTION(glUniform4fv),
6545 FUNCTION(glUniform4i),
6546 FUNCTION(glUniform4iv),
6547 FUNCTION(glUniform4ui),
6548 FUNCTION(glUniform4uiv),
6549 FUNCTION(glUniformBlockBinding),
6550 FUNCTION(glUniformMatrix2fv),
6551 FUNCTION(glUniformMatrix2x3fv),
6552 FUNCTION(glUniformMatrix2x4fv),
6553 FUNCTION(glUniformMatrix3fv),
6554 FUNCTION(glUniformMatrix3x2fv),
6555 FUNCTION(glUniformMatrix3x4fv),
6556 FUNCTION(glUniformMatrix4fv),
6557 FUNCTION(glUniformMatrix4x2fv),
6558 FUNCTION(glUniformMatrix4x3fv),
6559 FUNCTION(glUnmapBuffer),
6560 FUNCTION(glUseProgram),
6561 FUNCTION(glValidateProgram),
6562 FUNCTION(glVertexAttrib1f),
6563 FUNCTION(glVertexAttrib1fv),
6564 FUNCTION(glVertexAttrib2f),
6565 FUNCTION(glVertexAttrib2fv),
6566 FUNCTION(glVertexAttrib3f),
6567 FUNCTION(glVertexAttrib3fv),
6568 FUNCTION(glVertexAttrib4f),
6569 FUNCTION(glVertexAttrib4fv),
6570 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006571 FUNCTION(glVertexAttribDivisorANGLE),
6572 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006573 FUNCTION(glVertexAttribI4i),
6574 FUNCTION(glVertexAttribI4iv),
6575 FUNCTION(glVertexAttribI4ui),
6576 FUNCTION(glVertexAttribI4uiv),
6577 FUNCTION(glVertexAttribIPointer),
6578 FUNCTION(glVertexAttribPointer),
6579 FUNCTION(glViewport),
6580 FUNCTION(glWaitSync),
6581
6582 #undef FUNCTION
6583 };
6584
6585 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6586 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6587
6588 Function needle;
6589 needle.name = procname;
6590
6591 if(procname && strncmp("gl", procname, 2) == 0)
6592 {
6593 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
6594 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006595 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006596 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006597 }
6598 }
6599
6600 return nullptr;
6601}