blob: aa743e7ee13229f2bda34080eff8897e46e81e98 [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
57static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
58{
59 GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
60 if(validationError != GL_NONE)
61 {
62 return error(validationError, false);
63 }
64
65 // [OpenGL ES 2.0.24] table 3.9
66 switch(textureFormat)
67 {
68 case GL_ALPHA:
69 if(colorbufferFormat != GL_ALPHA &&
70 colorbufferFormat != GL_RGBA &&
71 colorbufferFormat != GL_RGBA4 &&
72 colorbufferFormat != GL_RGB5_A1 &&
73 colorbufferFormat != GL_RGBA8_OES &&
74 colorbufferFormat != GL_BGRA8_EXT &&
75 colorbufferFormat != GL_RGBA16F_EXT &&
76 colorbufferFormat != GL_RGBA32F_EXT)
77 {
78 return error(GL_INVALID_OPERATION, false);
79 }
80 break;
81 case GL_LUMINANCE:
82 case GL_RGB:
83 if(colorbufferFormat != GL_RGB &&
84 colorbufferFormat != GL_RGB565 &&
85 colorbufferFormat != GL_RGB8_OES &&
86 colorbufferFormat != GL_RGBA &&
87 colorbufferFormat != GL_RGBA4 &&
88 colorbufferFormat != GL_RGB5_A1 &&
89 colorbufferFormat != GL_RGBA8_OES &&
90 colorbufferFormat != GL_RGB16F_EXT &&
91 colorbufferFormat != GL_RGB32F_EXT &&
92 colorbufferFormat != GL_BGRA8_EXT &&
93 colorbufferFormat != GL_RGBA16F_EXT &&
94 colorbufferFormat != GL_RGBA32F_EXT)
95 {
96 return error(GL_INVALID_OPERATION, false);
97 }
98 break;
99 case GL_LUMINANCE_ALPHA:
100 case GL_RGBA:
101 if(colorbufferFormat != GL_RGBA &&
102 colorbufferFormat != GL_RGBA4 &&
103 colorbufferFormat != GL_RGB5_A1 &&
104 colorbufferFormat != GL_RGBA8_OES &&
105 colorbufferFormat != GL_BGRA8_EXT &&
106 colorbufferFormat != GL_RGBA16F_EXT &&
107 colorbufferFormat != GL_RGBA32F_EXT)
108 {
109 return error(GL_INVALID_OPERATION, false);
110 }
111 break;
112 case GL_DEPTH_COMPONENT:
113 case GL_DEPTH_STENCIL_OES:
114 return error(GL_INVALID_OPERATION, false);
115 default:
116 return error(GL_INVALID_ENUM, false);
117 }
118 return true;
119}
120
121void ActiveTexture(GLenum texture)
122{
123 TRACE("(GLenum texture = 0x%X)", texture);
124
125 es2::Context *context = es2::getContext();
126
127 if(context)
128 {
129 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
130 {
131 return error(GL_INVALID_ENUM);
132 }
133
134 context->setActiveSampler(texture - GL_TEXTURE0);
135 }
136}
137
138void AttachShader(GLuint program, GLuint shader)
139{
140 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
141
142 es2::Context *context = es2::getContext();
143
144 if(context)
145 {
146 es2::Program *programObject = context->getProgram(program);
147 es2::Shader *shaderObject = context->getShader(shader);
148
149 if(!programObject)
150 {
151 if(context->getShader(program))
152 {
153 return error(GL_INVALID_OPERATION);
154 }
155 else
156 {
157 return error(GL_INVALID_VALUE);
158 }
159 }
160
161 if(!shaderObject)
162 {
163 if(context->getProgram(shader))
164 {
165 return error(GL_INVALID_OPERATION);
166 }
167 else
168 {
169 return error(GL_INVALID_VALUE);
170 }
171 }
172
173 if(!programObject->attachShader(shaderObject))
174 {
175 return error(GL_INVALID_OPERATION);
176 }
177 }
178}
179
180void BeginQueryEXT(GLenum target, GLuint name)
181{
182 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
183
184 switch(target)
185 {
186 case GL_ANY_SAMPLES_PASSED_EXT:
187 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
188 break;
189 default:
190 return error(GL_INVALID_ENUM);
191 }
192
193 if(name == 0)
194 {
195 return error(GL_INVALID_OPERATION);
196 }
197
198 es2::Context *context = es2::getContext();
199
200 if(context)
201 {
202 context->beginQuery(target, name);
203 }
204}
205
206void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
207{
208 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
209
210 if(index >= es2::MAX_VERTEX_ATTRIBS)
211 {
212 return error(GL_INVALID_VALUE);
213 }
214
215 es2::Context *context = es2::getContext();
216
217 if(context)
218 {
219 es2::Program *programObject = context->getProgram(program);
220
221 if(!programObject)
222 {
223 if(context->getShader(program))
224 {
225 return error(GL_INVALID_OPERATION);
226 }
227 else
228 {
229 return error(GL_INVALID_VALUE);
230 }
231 }
232
233 if(strncmp(name, "gl_", 3) == 0)
234 {
235 return error(GL_INVALID_OPERATION);
236 }
237
238 programObject->bindAttributeLocation(index, name);
239 }
240}
241
242void BindBuffer(GLenum target, GLuint buffer)
243{
244 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
245
246 es2::Context *context = es2::getContext();
247
248 if(context)
249 {
250 GLint clientVersion = egl::getClientVersion();
251
252 switch(target)
253 {
254 case GL_ARRAY_BUFFER:
255 context->bindArrayBuffer(buffer);
256 return;
257 case GL_ELEMENT_ARRAY_BUFFER:
258 context->bindElementArrayBuffer(buffer);
259 return;
260 case GL_COPY_READ_BUFFER:
261 if(clientVersion >= 3)
262 {
263 context->bindCopyReadBuffer(buffer);
264 return;
265 }
266 else return error(GL_INVALID_ENUM);
267 case GL_COPY_WRITE_BUFFER:
268 if(clientVersion >= 3)
269 {
270 context->bindCopyWriteBuffer(buffer);
271 return;
272 }
273 else return error(GL_INVALID_ENUM);
274 case GL_PIXEL_PACK_BUFFER:
275 if(clientVersion >= 3)
276 {
277 context->bindPixelPackBuffer(buffer);
278 return;
279 }
280 else return error(GL_INVALID_ENUM);
281 case GL_PIXEL_UNPACK_BUFFER:
282 if(clientVersion >= 3)
283 {
284 context->bindPixelUnpackBuffer(buffer);
285 return;
286 }
287 else return error(GL_INVALID_ENUM);
288 case GL_TRANSFORM_FEEDBACK_BUFFER:
289 if(clientVersion >= 3)
290 {
291 context->bindTransformFeedbackBuffer(buffer);
292 return;
293 }
294 else return error(GL_INVALID_ENUM);
295 case GL_UNIFORM_BUFFER:
296 if(clientVersion >= 3)
297 {
298 context->bindGenericUniformBuffer(buffer);
299 return;
300 }
301 else return error(GL_INVALID_ENUM);
302 default:
303 return error(GL_INVALID_ENUM);
304 }
305 }
306}
307
308void BindFramebuffer(GLenum target, GLuint framebuffer)
309{
310 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
311
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000312 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400313 {
314 return error(GL_INVALID_ENUM);
315 }
316
317 es2::Context *context = es2::getContext();
318
319 if(context)
320 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000321 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400322 {
323 context->bindReadFramebuffer(framebuffer);
324 }
325
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000326 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400327 {
328 context->bindDrawFramebuffer(framebuffer);
329 }
330 }
331}
332
333void BindRenderbuffer(GLenum target, GLuint renderbuffer)
334{
335 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
336
337 if(target != GL_RENDERBUFFER)
338 {
339 return error(GL_INVALID_ENUM);
340 }
341
342 es2::Context *context = es2::getContext();
343
344 if(context)
345 {
346 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
347 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
348 // If renderbuffer is not zero, then the resulting renderbuffer object
349 // is a new state vector, initialized with a zero-sized memory buffer.
350 context->bindRenderbuffer(renderbuffer);
351 }
352}
353
354void BindTexture(GLenum target, GLuint texture)
355{
356 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
357
358 es2::Context *context = es2::getContext();
359
360 if(context)
361 {
362 es2::Texture *textureObject = context->getTexture(texture);
363
364 if(textureObject && textureObject->getTarget() != target && texture != 0)
365 {
366 return error(GL_INVALID_OPERATION);
367 }
368
369 GLint clientVersion = context->getClientVersion();
370
371 switch(target)
372 {
373 case GL_TEXTURE_2D:
374 context->bindTexture2D(texture);
375 break;
376 case GL_TEXTURE_CUBE_MAP:
377 context->bindTextureCubeMap(texture);
378 break;
379 case GL_TEXTURE_EXTERNAL_OES:
380 context->bindTextureExternal(texture);
381 break;
382 case GL_TEXTURE_2D_ARRAY:
383 if(clientVersion < 3)
384 {
385 return error(GL_INVALID_ENUM);
386 }
387 context->bindTexture2DArray(texture);
388 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500389 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400390 context->bindTexture3D(texture);
391 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500392 case GL_TEXTURE_RECTANGLE_ARB:
393 context->bindTexture2DRect(texture);
394 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400395 default:
396 return error(GL_INVALID_ENUM);
397 }
398 }
399}
400
401void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
402{
403 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
404 red, green, blue, alpha);
405
406 es2::Context* context = es2::getContext();
407
408 if(context)
409 {
410 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
411 }
412}
413
414void BlendEquation(GLenum mode)
415{
416 glBlendEquationSeparate(mode, mode);
417}
418
419void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
420{
421 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
422
423 switch(modeRGB)
424 {
425 case GL_FUNC_ADD:
426 case GL_FUNC_SUBTRACT:
427 case GL_FUNC_REVERSE_SUBTRACT:
428 case GL_MIN_EXT:
429 case GL_MAX_EXT:
430 break;
431 default:
432 return error(GL_INVALID_ENUM);
433 }
434
435 switch(modeAlpha)
436 {
437 case GL_FUNC_ADD:
438 case GL_FUNC_SUBTRACT:
439 case GL_FUNC_REVERSE_SUBTRACT:
440 case GL_MIN_EXT:
441 case GL_MAX_EXT:
442 break;
443 default:
444 return error(GL_INVALID_ENUM);
445 }
446
447 es2::Context *context = es2::getContext();
448
449 if(context)
450 {
451 context->setBlendEquation(modeRGB, modeAlpha);
452 }
453}
454
455void BlendFunc(GLenum sfactor, GLenum dfactor)
456{
457 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
458}
459
460void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
461{
462 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
463 srcRGB, dstRGB, srcAlpha, dstAlpha);
464
465 GLint clientVersion = egl::getClientVersion();
466
467 switch(srcRGB)
468 {
469 case GL_ZERO:
470 case GL_ONE:
471 case GL_SRC_COLOR:
472 case GL_ONE_MINUS_SRC_COLOR:
473 case GL_DST_COLOR:
474 case GL_ONE_MINUS_DST_COLOR:
475 case GL_SRC_ALPHA:
476 case GL_ONE_MINUS_SRC_ALPHA:
477 case GL_DST_ALPHA:
478 case GL_ONE_MINUS_DST_ALPHA:
479 case GL_CONSTANT_COLOR:
480 case GL_ONE_MINUS_CONSTANT_COLOR:
481 case GL_CONSTANT_ALPHA:
482 case GL_ONE_MINUS_CONSTANT_ALPHA:
483 case GL_SRC_ALPHA_SATURATE:
484 break;
485 default:
486 return error(GL_INVALID_ENUM);
487 }
488
489 switch(dstRGB)
490 {
491 case GL_ZERO:
492 case GL_ONE:
493 case GL_SRC_COLOR:
494 case GL_ONE_MINUS_SRC_COLOR:
495 case GL_DST_COLOR:
496 case GL_ONE_MINUS_DST_COLOR:
497 case GL_SRC_ALPHA:
498 case GL_ONE_MINUS_SRC_ALPHA:
499 case GL_DST_ALPHA:
500 case GL_ONE_MINUS_DST_ALPHA:
501 case GL_CONSTANT_COLOR:
502 case GL_ONE_MINUS_CONSTANT_COLOR:
503 case GL_CONSTANT_ALPHA:
504 case GL_ONE_MINUS_CONSTANT_ALPHA:
505 break;
506 case GL_SRC_ALPHA_SATURATE:
507 if(clientVersion < 3)
508 {
509 return error(GL_INVALID_ENUM);
510 }
511 break;
512 default:
513 return error(GL_INVALID_ENUM);
514 }
515
516 switch(srcAlpha)
517 {
518 case GL_ZERO:
519 case GL_ONE:
520 case GL_SRC_COLOR:
521 case GL_ONE_MINUS_SRC_COLOR:
522 case GL_DST_COLOR:
523 case GL_ONE_MINUS_DST_COLOR:
524 case GL_SRC_ALPHA:
525 case GL_ONE_MINUS_SRC_ALPHA:
526 case GL_DST_ALPHA:
527 case GL_ONE_MINUS_DST_ALPHA:
528 case GL_CONSTANT_COLOR:
529 case GL_ONE_MINUS_CONSTANT_COLOR:
530 case GL_CONSTANT_ALPHA:
531 case GL_ONE_MINUS_CONSTANT_ALPHA:
532 case GL_SRC_ALPHA_SATURATE:
533 break;
534 default:
535 return error(GL_INVALID_ENUM);
536 }
537
538 switch(dstAlpha)
539 {
540 case GL_ZERO:
541 case GL_ONE:
542 case GL_SRC_COLOR:
543 case GL_ONE_MINUS_SRC_COLOR:
544 case GL_DST_COLOR:
545 case GL_ONE_MINUS_DST_COLOR:
546 case GL_SRC_ALPHA:
547 case GL_ONE_MINUS_SRC_ALPHA:
548 case GL_DST_ALPHA:
549 case GL_ONE_MINUS_DST_ALPHA:
550 case GL_CONSTANT_COLOR:
551 case GL_ONE_MINUS_CONSTANT_COLOR:
552 case GL_CONSTANT_ALPHA:
553 case GL_ONE_MINUS_CONSTANT_ALPHA:
554 break;
555 case GL_SRC_ALPHA_SATURATE:
556 if(clientVersion < 3)
557 {
558 return error(GL_INVALID_ENUM);
559 }
560 break;
561 default:
562 return error(GL_INVALID_ENUM);
563 }
564
565 es2::Context *context = es2::getContext();
566
567 if(context)
568 {
569 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
570 }
571}
572
573void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
574{
575 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
576
577 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
578 target, size, data, usage);
579
580 if(size < 0)
581 {
582 return error(GL_INVALID_VALUE);
583 }
584
585 GLint clientVersion = egl::getClientVersion();
586
587 switch(usage)
588 {
589 case GL_STREAM_DRAW:
590 case GL_STATIC_DRAW:
591 case GL_DYNAMIC_DRAW:
592 break;
593 case GL_STREAM_READ:
594 case GL_STREAM_COPY:
595 case GL_STATIC_READ:
596 case GL_STATIC_COPY:
597 case GL_DYNAMIC_READ:
598 case GL_DYNAMIC_COPY:
599 if(clientVersion < 3)
600 {
601 return error(GL_INVALID_ENUM);
602 }
603 break;
604 default:
605 return error(GL_INVALID_ENUM);
606 }
607
608 es2::Context *context = es2::getContext();
609
610 if(context)
611 {
612 es2::Buffer *buffer = nullptr;
613 if(!context->getBuffer(target, &buffer))
614 {
615 return error(GL_INVALID_ENUM);
616 }
617
618 if(!buffer)
619 {
620 // A null buffer means that "0" is bound to the requested buffer target
621 return error(GL_INVALID_OPERATION);
622 }
623
624 buffer->bufferData(data, size, usage);
625 }
626}
627
628void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
629{
630 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
631 offset = static_cast<GLint>(offset);
632
633 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
634 target, offset, size, data);
635
636 if(size < 0 || offset < 0)
637 {
638 return error(GL_INVALID_VALUE);
639 }
640
641 es2::Context *context = es2::getContext();
642
643 if(context)
644 {
645 es2::Buffer *buffer = nullptr;
646 if(!context->getBuffer(target, &buffer))
647 {
648 return error(GL_INVALID_ENUM);
649 }
650
651 if(!buffer)
652 {
653 // A null buffer means that "0" is bound to the requested buffer target
654 return error(GL_INVALID_OPERATION);
655 }
656
Alexis Hetu6e864492017-11-14 15:27:00 -0500657 if(buffer->isMapped())
658 {
659 // It is an invalid operation to update an already mapped buffer
660 return error(GL_INVALID_OPERATION);
661 }
662
Nicolas Capens0bac2852016-05-07 06:09:58 -0400663 if((size_t)size + offset > buffer->size())
664 {
665 return error(GL_INVALID_VALUE);
666 }
667
668 buffer->bufferSubData(data, size, offset);
669 }
670}
671
672GLenum CheckFramebufferStatus(GLenum target)
673{
674 TRACE("(GLenum target = 0x%X)", target);
675
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000676 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400677 {
678 return error(GL_INVALID_ENUM, 0);
679 }
680
681 es2::Context *context = es2::getContext();
682
683 if(context)
684 {
685 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000686 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400687 {
688 framebuffer = context->getReadFramebuffer();
689 }
690 else
691 {
692 framebuffer = context->getDrawFramebuffer();
693 }
694
695 return framebuffer->completeness();
696 }
697
698 return 0;
699}
700
701void Clear(GLbitfield mask)
702{
703 TRACE("(GLbitfield mask = %X)", mask);
704
705 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
706 {
707 return error(GL_INVALID_VALUE);
708 }
709
710 es2::Context *context = es2::getContext();
711
712 if(context)
713 {
714 context->clear(mask);
715 }
716}
717
718void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
719{
720 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
721 red, green, blue, alpha);
722
723 es2::Context *context = es2::getContext();
724
725 if(context)
726 {
727 context->setClearColor(red, green, blue, alpha);
728 }
729}
730
731void ClearDepthf(GLclampf depth)
732{
733 TRACE("(GLclampf depth = %f)", depth);
734
735 es2::Context *context = es2::getContext();
736
737 if(context)
738 {
739 context->setClearDepth(depth);
740 }
741}
742
743void ClearStencil(GLint s)
744{
745 TRACE("(GLint s = %d)", s);
746
747 es2::Context *context = es2::getContext();
748
749 if(context)
750 {
751 context->setClearStencil(s);
752 }
753}
754
755void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
756{
757 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
758 red, green, blue, alpha);
759
760 es2::Context *context = es2::getContext();
761
762 if(context)
763 {
764 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
765 }
766}
767
768void CompileShader(GLuint shader)
769{
770 TRACE("(GLuint shader = %d)", shader);
771
772 es2::Context *context = es2::getContext();
773
774 if(context)
775 {
776 es2::Shader *shaderObject = context->getShader(shader);
777
778 if(!shaderObject)
779 {
780 if(context->getProgram(shader))
781 {
782 return error(GL_INVALID_OPERATION);
783 }
784 else
785 {
786 return error(GL_INVALID_VALUE);
787 }
788 }
789
790 shaderObject->compile();
791 }
792}
793
794void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
795 GLint border, GLsizei imageSize, const GLvoid* data)
796{
797 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
798 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
799 target, level, internalformat, width, height, border, imageSize, data);
800
801 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
802 {
803 return error(GL_INVALID_VALUE);
804 }
805
806 switch(internalformat)
807 {
808 case GL_DEPTH_COMPONENT:
809 case GL_DEPTH_COMPONENT16:
810 case GL_DEPTH_COMPONENT32_OES:
811 case GL_DEPTH_STENCIL_OES:
812 case GL_DEPTH24_STENCIL8_OES:
813 return error(GL_INVALID_OPERATION);
814 default:
815 {
816 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
817 if(validationError != GL_NONE)
818 {
819 return error(validationError);
820 }
821 }
822 break;
823 }
824
825 if(border != 0)
826 {
827 return error(GL_INVALID_VALUE);
828 }
829
830 es2::Context *context = es2::getContext();
831
832 if(context)
833 {
834 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
835 {
836 return error(GL_INVALID_VALUE);
837 }
838
839 switch(target)
840 {
841 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -0500842 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400843 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
844 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
845 {
846 return error(GL_INVALID_VALUE);
847 }
848 break;
849 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
850 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
851 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
852 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
853 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
854 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
855 if(width != height)
856 {
857 return error(GL_INVALID_VALUE);
858 }
859
860 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
861 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
862 {
863 return error(GL_INVALID_VALUE);
864 }
865 break;
866 default:
867 return error(GL_INVALID_ENUM);
868 }
869
870 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat))
871 {
872 return error(GL_INVALID_VALUE);
873 }
874
Alexis Hetu46768622018-01-16 22:09:28 -0500875 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400876 {
Alexis Hetu46768622018-01-16 22:09:28 -0500877 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400878
879 if(!texture)
880 {
881 return error(GL_INVALID_OPERATION);
882 }
883
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500884 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500885 if(validationError != GL_NONE)
886 {
887 return error(validationError);
888 }
889
Nicolas Capens0bac2852016-05-07 06:09:58 -0400890 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
891 }
892 else
893 {
894 es2::TextureCubeMap *texture = context->getTextureCubeMap();
895
896 if(!texture)
897 {
898 return error(GL_INVALID_OPERATION);
899 }
900
901 switch(target)
902 {
903 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
904 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
905 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
907 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
908 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500909 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500910 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500911 if(validationError != GL_NONE)
912 {
913 return error(validationError);
914 }
915
916 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
917 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400918 break;
919 default: UNREACHABLE(target);
920 }
921 }
922 }
923}
924
925void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
926 GLenum format, GLsizei imageSize, const GLvoid* data)
927{
928 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
929 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
930 "GLsizei imageSize = %d, const GLvoid* data = %p)",
931 target, level, xoffset, yoffset, width, height, format, imageSize, data);
932
933 if(!es2::IsTextureTarget(target))
934 {
935 return error(GL_INVALID_ENUM);
936 }
937
938 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
939 {
940 return error(GL_INVALID_VALUE);
941 }
942
943 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
944 {
945 return error(GL_INVALID_VALUE);
946 }
947
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500948 if(imageSize != egl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400949 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500950 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400951 }
952
953 es2::Context *context = es2::getContext();
954
955 if(context)
956 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400957 if(xoffset % 4 != 0 || yoffset % 4 != 0)
958 {
959 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
960 return error(GL_INVALID_OPERATION);
961 }
962
963 GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_NONE);
964
Alexis Hetu46768622018-01-16 22:09:28 -0500965 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400966 {
Alexis Hetu46768622018-01-16 22:09:28 -0500967 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400968
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500969 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
970 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400971 {
972 return error(validationError);
973 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500974
975 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
976 if(validationError != GL_NONE)
977 {
978 return error(validationError);
979 }
980
981 texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400982 }
983 else if(es2::IsCubemapTextureTarget(target))
984 {
985 es2::TextureCubeMap *texture = context->getTextureCubeMap();
986
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500987 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
988 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 {
990 return error(validationError);
991 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500992
993 validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
994 if(validationError != GL_NONE)
995 {
996 return error(validationError);
997 }
998
999 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001000 }
1001 else UNREACHABLE(target);
1002 }
1003}
1004
1005void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
1006{
1007 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
1008 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
1009 target, level, internalformat, x, y, width, height, border);
1010
1011 if(!validImageSize(level, width, height))
1012 {
1013 return error(GL_INVALID_VALUE);
1014 }
1015
1016 if(border != 0)
1017 {
1018 return error(GL_INVALID_VALUE);
1019 }
1020
1021 es2::Context *context = es2::getContext();
1022
1023 if(context)
1024 {
1025 switch(target)
1026 {
1027 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05001028 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04001029 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
1030 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
1031 {
1032 return error(GL_INVALID_VALUE);
1033 }
1034 break;
1035 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1036 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1037 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1038 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1039 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1040 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1041 if(width != height)
1042 {
1043 return error(GL_INVALID_VALUE);
1044 }
1045
1046 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
1047 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
1048 {
1049 return error(GL_INVALID_VALUE);
1050 }
1051 break;
1052 default:
1053 return error(GL_INVALID_ENUM);
1054 }
1055
1056 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1057
1058 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1059 {
1060 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1061 }
1062
1063 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1064
1065 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1066 {
1067 return error(GL_INVALID_OPERATION);
1068 }
1069
1070 GLenum colorbufferFormat = source->getFormat();
1071
1072 if(!validateColorBufferFormat(internalformat, colorbufferFormat))
1073 {
1074 return;
1075 }
1076
Alexis Hetu46768622018-01-16 22:09:28 -05001077 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001078 {
Alexis Hetu46768622018-01-16 22:09:28 -05001079 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001080
1081 if(!texture)
1082 {
1083 return error(GL_INVALID_OPERATION);
1084 }
1085
1086 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
1087 }
1088 else if(es2::IsCubemapTextureTarget(target))
1089 {
1090 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1091
1092 if(!texture)
1093 {
1094 return error(GL_INVALID_OPERATION);
1095 }
1096
1097 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1098 }
1099 else UNREACHABLE(target);
1100 }
1101}
1102
1103void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1104{
1105 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1106 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1107 target, level, xoffset, yoffset, x, y, width, height);
1108
1109 if(!es2::IsTextureTarget(target))
1110 {
1111 return error(GL_INVALID_ENUM);
1112 }
1113
1114 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1115 {
1116 return error(GL_INVALID_VALUE);
1117 }
1118
1119 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1120 {
1121 return error(GL_INVALID_VALUE);
1122 }
1123
1124 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1125 {
1126 return error(GL_INVALID_VALUE);
1127 }
1128
Nicolas Capens0bac2852016-05-07 06:09:58 -04001129 es2::Context *context = es2::getContext();
1130
1131 if(context)
1132 {
1133 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1134
1135 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1136 {
1137 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1138 }
1139
1140 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1141
1142 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1143 {
1144 return error(GL_INVALID_OPERATION);
1145 }
1146
1147 es2::Texture *texture = nullptr;
1148
Alexis Hetu46768622018-01-16 22:09:28 -05001149 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001150 {
Alexis Hetu46768622018-01-16 22:09:28 -05001151 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001152 }
1153 else if(es2::IsCubemapTextureTarget(target))
1154 {
1155 texture = context->getTextureCubeMap();
1156 }
1157 else UNREACHABLE(target);
1158
Nicolas Capensd2faaa92017-12-04 11:15:51 -05001159 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capens0bac2852016-05-07 06:09:58 -04001160 if(validationError != GL_NONE)
1161 {
1162 return error(validationError);
1163 }
1164
1165 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
1166 }
1167}
1168
1169GLuint CreateProgram(void)
1170{
1171 TRACE("()");
1172
1173 es2::Context *context = es2::getContext();
1174
1175 if(context)
1176 {
1177 return context->createProgram();
1178 }
1179
1180 return 0;
1181}
1182
1183GLuint CreateShader(GLenum type)
1184{
1185 TRACE("(GLenum type = 0x%X)", type);
1186
1187 es2::Context *context = es2::getContext();
1188
1189 if(context)
1190 {
1191 switch(type)
1192 {
1193 case GL_FRAGMENT_SHADER:
1194 case GL_VERTEX_SHADER:
1195 return context->createShader(type);
1196 default:
1197 return error(GL_INVALID_ENUM, 0);
1198 }
1199 }
1200
1201 return 0;
1202}
1203
1204void CullFace(GLenum mode)
1205{
1206 TRACE("(GLenum mode = 0x%X)", mode);
1207
1208 switch(mode)
1209 {
1210 case GL_FRONT:
1211 case GL_BACK:
1212 case GL_FRONT_AND_BACK:
1213 {
1214 es2::Context *context = es2::getContext();
1215
1216 if(context)
1217 {
1218 context->setCullMode(mode);
1219 }
1220 }
1221 break;
1222 default:
1223 return error(GL_INVALID_ENUM);
1224 }
1225}
1226
1227void DeleteBuffers(GLsizei n, const GLuint* buffers)
1228{
1229 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1230
1231 if(n < 0)
1232 {
1233 return error(GL_INVALID_VALUE);
1234 }
1235
1236 es2::Context *context = es2::getContext();
1237
1238 if(context)
1239 {
1240 for(int i = 0; i < n; i++)
1241 {
1242 context->deleteBuffer(buffers[i]);
1243 }
1244 }
1245}
1246
1247void DeleteFencesNV(GLsizei n, const GLuint* fences)
1248{
1249 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1250
1251 if(n < 0)
1252 {
1253 return error(GL_INVALID_VALUE);
1254 }
1255
1256 es2::Context *context = es2::getContext();
1257
1258 if(context)
1259 {
1260 for(int i = 0; i < n; i++)
1261 {
1262 context->deleteFence(fences[i]);
1263 }
1264 }
1265}
1266
1267void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1268{
1269 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1270
1271 if(n < 0)
1272 {
1273 return error(GL_INVALID_VALUE);
1274 }
1275
1276 es2::Context *context = es2::getContext();
1277
1278 if(context)
1279 {
1280 for(int i = 0; i < n; i++)
1281 {
1282 if(framebuffers[i] != 0)
1283 {
1284 context->deleteFramebuffer(framebuffers[i]);
1285 }
1286 }
1287 }
1288}
1289
1290void DeleteProgram(GLuint program)
1291{
1292 TRACE("(GLuint program = %d)", program);
1293
1294 if(program == 0)
1295 {
1296 return;
1297 }
1298
1299 es2::Context *context = es2::getContext();
1300
1301 if(context)
1302 {
1303 if(!context->getProgram(program))
1304 {
1305 if(context->getShader(program))
1306 {
1307 return error(GL_INVALID_OPERATION);
1308 }
1309 else
1310 {
1311 return error(GL_INVALID_VALUE);
1312 }
1313 }
1314
1315 context->deleteProgram(program);
1316 }
1317}
1318
1319void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1320{
1321 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1322
1323 if(n < 0)
1324 {
1325 return error(GL_INVALID_VALUE);
1326 }
1327
1328 es2::Context *context = es2::getContext();
1329
1330 if(context)
1331 {
1332 for(int i = 0; i < n; i++)
1333 {
1334 context->deleteQuery(ids[i]);
1335 }
1336 }
1337}
1338
1339void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1340{
1341 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1342
1343 if(n < 0)
1344 {
1345 return error(GL_INVALID_VALUE);
1346 }
1347
1348 es2::Context *context = es2::getContext();
1349
1350 if(context)
1351 {
1352 for(int i = 0; i < n; i++)
1353 {
1354 context->deleteRenderbuffer(renderbuffers[i]);
1355 }
1356 }
1357}
1358
1359void DeleteShader(GLuint shader)
1360{
1361 TRACE("(GLuint shader = %d)", shader);
1362
1363 if(shader == 0)
1364 {
1365 return;
1366 }
1367
1368 es2::Context *context = es2::getContext();
1369
1370 if(context)
1371 {
1372 if(!context->getShader(shader))
1373 {
1374 if(context->getProgram(shader))
1375 {
1376 return error(GL_INVALID_OPERATION);
1377 }
1378 else
1379 {
1380 return error(GL_INVALID_VALUE);
1381 }
1382 }
1383
1384 context->deleteShader(shader);
1385 }
1386}
1387
1388void DeleteTextures(GLsizei n, const GLuint* textures)
1389{
1390 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1391
1392 if(n < 0)
1393 {
1394 return error(GL_INVALID_VALUE);
1395 }
1396
1397 es2::Context *context = es2::getContext();
1398
1399 if(context)
1400 {
1401 for(int i = 0; i < n; i++)
1402 {
1403 if(textures[i] != 0)
1404 {
1405 context->deleteTexture(textures[i]);
1406 }
1407 }
1408 }
1409}
1410
1411void DepthFunc(GLenum func)
1412{
1413 TRACE("(GLenum func = 0x%X)", func);
1414
1415 switch(func)
1416 {
1417 case GL_NEVER:
1418 case GL_ALWAYS:
1419 case GL_LESS:
1420 case GL_LEQUAL:
1421 case GL_EQUAL:
1422 case GL_GREATER:
1423 case GL_GEQUAL:
1424 case GL_NOTEQUAL:
1425 break;
1426 default:
1427 return error(GL_INVALID_ENUM);
1428 }
1429
1430 es2::Context *context = es2::getContext();
1431
1432 if(context)
1433 {
1434 context->setDepthFunc(func);
1435 }
1436}
1437
1438void DepthMask(GLboolean flag)
1439{
1440 TRACE("(GLboolean flag = %d)", flag);
1441
1442 es2::Context *context = es2::getContext();
1443
1444 if(context)
1445 {
1446 context->setDepthMask(flag != GL_FALSE);
1447 }
1448}
1449
1450void DepthRangef(GLclampf zNear, GLclampf zFar)
1451{
1452 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1453
1454 es2::Context *context = es2::getContext();
1455
1456 if(context)
1457 {
1458 context->setDepthRange(zNear, zFar);
1459 }
1460}
1461
1462void DetachShader(GLuint program, GLuint shader)
1463{
1464 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1465
1466 es2::Context *context = es2::getContext();
1467
1468 if(context)
1469 {
1470
1471 es2::Program *programObject = context->getProgram(program);
1472 es2::Shader *shaderObject = context->getShader(shader);
1473
1474 if(!programObject)
1475 {
1476 es2::Shader *shaderByProgramHandle;
1477 shaderByProgramHandle = context->getShader(program);
1478 if(!shaderByProgramHandle)
1479 {
1480 return error(GL_INVALID_VALUE);
1481 }
1482 else
1483 {
1484 return error(GL_INVALID_OPERATION);
1485 }
1486 }
1487
1488 if(!shaderObject)
1489 {
1490 es2::Program *programByShaderHandle = context->getProgram(shader);
1491 if(!programByShaderHandle)
1492 {
1493 return error(GL_INVALID_VALUE);
1494 }
1495 else
1496 {
1497 return error(GL_INVALID_OPERATION);
1498 }
1499 }
1500
1501 if(!programObject->detachShader(shaderObject))
1502 {
1503 return error(GL_INVALID_OPERATION);
1504 }
1505 }
1506}
1507
1508void Disable(GLenum cap)
1509{
1510 TRACE("(GLenum cap = 0x%X)", cap);
1511
1512 es2::Context *context = es2::getContext();
1513
1514 if(context)
1515 {
1516 switch(cap)
1517 {
1518 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1519 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1520 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1521 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1522 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1523 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1524 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1525 case GL_BLEND: context->setBlendEnabled(false); break;
1526 case GL_DITHER: context->setDitherEnabled(false); break;
1527 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1528 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1529 default:
1530 return error(GL_INVALID_ENUM);
1531 }
1532 }
1533}
1534
1535void DisableVertexAttribArray(GLuint index)
1536{
1537 TRACE("(GLuint index = %d)", index);
1538
1539 if(index >= es2::MAX_VERTEX_ATTRIBS)
1540 {
1541 return error(GL_INVALID_VALUE);
1542 }
1543
1544 es2::Context *context = es2::getContext();
1545
1546 if(context)
1547 {
1548 context->setVertexAttribArrayEnabled(index, false);
1549 }
1550}
1551
1552void DrawArrays(GLenum mode, GLint first, GLsizei count)
1553{
1554 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1555
1556 switch(mode)
1557 {
1558 case GL_POINTS:
1559 case GL_LINES:
1560 case GL_LINE_LOOP:
1561 case GL_LINE_STRIP:
1562 case GL_TRIANGLES:
1563 case GL_TRIANGLE_FAN:
1564 case GL_TRIANGLE_STRIP:
1565 break;
1566 default:
1567 return error(GL_INVALID_ENUM);
1568 }
1569
1570 if(count < 0 || first < 0)
1571 {
1572 return error(GL_INVALID_VALUE);
1573 }
1574
1575 es2::Context *context = es2::getContext();
1576
1577 if(context)
1578 {
1579 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1580 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1581 {
1582 return error(GL_INVALID_OPERATION);
1583 }
1584
1585 context->drawArrays(mode, first, count);
1586 }
1587}
1588
1589void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1590{
1591 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1592 mode, count, type, indices);
1593
1594 switch(mode)
1595 {
1596 case GL_POINTS:
1597 case GL_LINES:
1598 case GL_LINE_LOOP:
1599 case GL_LINE_STRIP:
1600 case GL_TRIANGLES:
1601 case GL_TRIANGLE_FAN:
1602 case GL_TRIANGLE_STRIP:
1603 break;
1604 default:
1605 return error(GL_INVALID_ENUM);
1606 }
1607
1608 if(count < 0)
1609 {
1610 return error(GL_INVALID_VALUE);
1611 }
1612
1613 es2::Context *context = es2::getContext();
1614
1615 if(context)
1616 {
1617 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1618 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1619 {
1620 return error(GL_INVALID_OPERATION);
1621 }
1622
1623 switch(type)
1624 {
1625 case GL_UNSIGNED_BYTE:
1626 case GL_UNSIGNED_SHORT:
1627 case GL_UNSIGNED_INT:
1628 break;
1629 default:
1630 return error(GL_INVALID_ENUM);
1631 }
1632
1633 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1634 }
1635}
1636
1637void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1638{
1639 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1640 mode, first, count, instanceCount);
1641
1642 switch(mode)
1643 {
1644 case GL_POINTS:
1645 case GL_LINES:
1646 case GL_LINE_LOOP:
1647 case GL_LINE_STRIP:
1648 case GL_TRIANGLES:
1649 case GL_TRIANGLE_FAN:
1650 case GL_TRIANGLE_STRIP:
1651 break;
1652 default:
1653 return error(GL_INVALID_ENUM);
1654 }
1655
1656 if(count < 0 || instanceCount < 0)
1657 {
1658 return error(GL_INVALID_VALUE);
1659 }
1660
1661 es2::Context *context = es2::getContext();
1662
1663 if(context)
1664 {
1665 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1666 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1667 {
1668 return error(GL_INVALID_OPERATION);
1669 }
1670
1671 context->drawArrays(mode, first, count, instanceCount);
1672 }
1673}
1674
1675void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1676{
1677 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1678 mode, count, type, indices, instanceCount);
1679
1680 switch(mode)
1681 {
1682 case GL_POINTS:
1683 case GL_LINES:
1684 case GL_LINE_LOOP:
1685 case GL_LINE_STRIP:
1686 case GL_TRIANGLES:
1687 case GL_TRIANGLE_FAN:
1688 case GL_TRIANGLE_STRIP:
1689 break;
1690 default:
1691 return error(GL_INVALID_ENUM);
1692 }
1693
1694 switch(type)
1695 {
1696 case GL_UNSIGNED_BYTE:
1697 case GL_UNSIGNED_SHORT:
1698 case GL_UNSIGNED_INT:
1699 break;
1700 default:
1701 return error(GL_INVALID_ENUM);
1702 }
1703
1704 if(count < 0 || instanceCount < 0)
1705 {
1706 return error(GL_INVALID_VALUE);
1707 }
1708
1709 es2::Context *context = es2::getContext();
1710
1711 if(context)
1712 {
1713 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1714 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1715 {
1716 return error(GL_INVALID_OPERATION);
1717 }
1718
1719 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1720 }
1721}
1722
1723void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1724{
1725 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1726
1727 es2::Context *context = es2::getContext();
1728
1729 if(context)
1730 {
1731 if(index >= es2::MAX_VERTEX_ATTRIBS)
1732 {
1733 return error(GL_INVALID_VALUE);
1734 }
1735
1736 context->setVertexAttribDivisor(index, divisor);
1737 }
1738}
1739
1740void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1741{
1742 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1743 mode, first, count, instanceCount);
1744
1745 switch(mode)
1746 {
1747 case GL_POINTS:
1748 case GL_LINES:
1749 case GL_LINE_LOOP:
1750 case GL_LINE_STRIP:
1751 case GL_TRIANGLES:
1752 case GL_TRIANGLE_FAN:
1753 case GL_TRIANGLE_STRIP:
1754 break;
1755 default:
1756 return error(GL_INVALID_ENUM);
1757 }
1758
1759 if(count < 0 || instanceCount < 0)
1760 {
1761 return error(GL_INVALID_VALUE);
1762 }
1763
1764 es2::Context *context = es2::getContext();
1765
1766 if(context)
1767 {
1768 if(!context->hasZeroDivisor())
1769 {
1770 return error(GL_INVALID_OPERATION);
1771 }
1772
1773 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1774 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1775 {
1776 return error(GL_INVALID_OPERATION);
1777 }
1778
1779 context->drawArrays(mode, first, count, instanceCount);
1780 }
1781}
1782
1783void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1784{
1785 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1786 mode, count, type, indices, instanceCount);
1787
1788 switch(mode)
1789 {
1790 case GL_POINTS:
1791 case GL_LINES:
1792 case GL_LINE_LOOP:
1793 case GL_LINE_STRIP:
1794 case GL_TRIANGLES:
1795 case GL_TRIANGLE_FAN:
1796 case GL_TRIANGLE_STRIP:
1797 break;
1798 default:
1799 return error(GL_INVALID_ENUM);
1800 }
1801
1802 switch(type)
1803 {
1804 case GL_UNSIGNED_BYTE:
1805 case GL_UNSIGNED_SHORT:
1806 case GL_UNSIGNED_INT:
1807 break;
1808 default:
1809 return error(GL_INVALID_ENUM);
1810 }
1811
1812 if(count < 0 || instanceCount < 0)
1813 {
1814 return error(GL_INVALID_VALUE);
1815 }
1816
1817 es2::Context *context = es2::getContext();
1818
1819 if(context)
1820 {
1821 if(!context->hasZeroDivisor())
1822 {
1823 return error(GL_INVALID_OPERATION);
1824 }
1825
1826 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1827 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1828 {
1829 return error(GL_INVALID_OPERATION);
1830 }
1831
1832 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1833 }
1834}
1835
1836void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1837{
1838 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1839
1840 es2::Context *context = es2::getContext();
1841
1842 if(context)
1843 {
1844 if(index >= MAX_VERTEX_ATTRIBS)
1845 {
1846 return error(GL_INVALID_VALUE);
1847 }
1848
1849 context->setVertexAttribDivisor(index, divisor);
1850 }
1851}
1852
1853void Enable(GLenum cap)
1854{
1855 TRACE("(GLenum cap = 0x%X)", cap);
1856
1857 es2::Context *context = es2::getContext();
1858
1859 if(context)
1860 {
1861 switch(cap)
1862 {
1863 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1864 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1865 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1866 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1867 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1868 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1869 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1870 case GL_BLEND: context->setBlendEnabled(true); break;
1871 case GL_DITHER: context->setDitherEnabled(true); break;
1872 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1873 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1874 default:
1875 return error(GL_INVALID_ENUM);
1876 }
1877 }
1878}
1879
1880void EnableVertexAttribArray(GLuint index)
1881{
1882 TRACE("(GLuint index = %d)", index);
1883
1884 if(index >= es2::MAX_VERTEX_ATTRIBS)
1885 {
1886 return error(GL_INVALID_VALUE);
1887 }
1888
1889 es2::Context *context = es2::getContext();
1890
1891 if(context)
1892 {
1893 context->setVertexAttribArrayEnabled(index, true);
1894 }
1895}
1896
1897void EndQueryEXT(GLenum target)
1898{
1899 TRACE("GLenum target = 0x%X)", target);
1900
1901 switch(target)
1902 {
1903 case GL_ANY_SAMPLES_PASSED_EXT:
1904 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1905 break;
1906 default:
1907 return error(GL_INVALID_ENUM);
1908 }
1909
1910 es2::Context *context = es2::getContext();
1911
1912 if(context)
1913 {
1914 context->endQuery(target);
1915 }
1916}
1917
1918void FinishFenceNV(GLuint fence)
1919{
1920 TRACE("(GLuint fence = %d)", fence);
1921
1922 es2::Context *context = es2::getContext();
1923
1924 if(context)
1925 {
1926 es2::Fence *fenceObject = context->getFence(fence);
1927
1928 if(!fenceObject)
1929 {
1930 return error(GL_INVALID_OPERATION);
1931 }
1932
1933 fenceObject->finishFence();
1934 }
1935}
1936
1937void Finish(void)
1938{
1939 TRACE("()");
1940
1941 es2::Context *context = es2::getContext();
1942
1943 if(context)
1944 {
1945 context->finish();
1946 }
1947}
1948
1949void Flush(void)
1950{
1951 TRACE("()");
1952
1953 es2::Context *context = es2::getContext();
1954
1955 if(context)
1956 {
1957 context->flush();
1958 }
1959}
1960
1961void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1962{
1963 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1964 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1965
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001966 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001967 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1968 {
1969 return error(GL_INVALID_ENUM);
1970 }
1971
1972 es2::Context *context = es2::getContext();
1973
1974 if(context)
1975 {
1976 es2::Framebuffer *framebuffer = nullptr;
1977 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001978 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001979 {
1980 framebuffer = context->getReadFramebuffer();
1981 framebufferName = context->getReadFramebufferName();
1982 }
1983 else
1984 {
1985 framebuffer = context->getDrawFramebuffer();
1986 framebufferName = context->getDrawFramebufferName();
1987 }
1988
1989 if(!framebuffer || framebufferName == 0)
1990 {
1991 return error(GL_INVALID_OPERATION);
1992 }
1993
1994 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1995 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1996 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1997 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1998 if(renderbuffer != 0)
1999 {
2000 if(!context->getRenderbuffer(renderbuffer))
2001 {
2002 return error(GL_INVALID_OPERATION);
2003 }
2004 }
2005
2006 GLint clientVersion = context->getClientVersion();
2007
2008 switch(attachment)
2009 {
2010 case GL_COLOR_ATTACHMENT0:
2011 case GL_COLOR_ATTACHMENT1:
2012 case GL_COLOR_ATTACHMENT2:
2013 case GL_COLOR_ATTACHMENT3:
2014 case GL_COLOR_ATTACHMENT4:
2015 case GL_COLOR_ATTACHMENT5:
2016 case GL_COLOR_ATTACHMENT6:
2017 case GL_COLOR_ATTACHMENT7:
2018 case GL_COLOR_ATTACHMENT8:
2019 case GL_COLOR_ATTACHMENT9:
2020 case GL_COLOR_ATTACHMENT10:
2021 case GL_COLOR_ATTACHMENT11:
2022 case GL_COLOR_ATTACHMENT12:
2023 case GL_COLOR_ATTACHMENT13:
2024 case GL_COLOR_ATTACHMENT14:
2025 case GL_COLOR_ATTACHMENT15:
2026 case GL_COLOR_ATTACHMENT16:
2027 case GL_COLOR_ATTACHMENT17:
2028 case GL_COLOR_ATTACHMENT18:
2029 case GL_COLOR_ATTACHMENT19:
2030 case GL_COLOR_ATTACHMENT20:
2031 case GL_COLOR_ATTACHMENT21:
2032 case GL_COLOR_ATTACHMENT22:
2033 case GL_COLOR_ATTACHMENT23:
2034 case GL_COLOR_ATTACHMENT24:
2035 case GL_COLOR_ATTACHMENT25:
2036 case GL_COLOR_ATTACHMENT26:
2037 case GL_COLOR_ATTACHMENT27:
2038 case GL_COLOR_ATTACHMENT28:
2039 case GL_COLOR_ATTACHMENT29:
2040 case GL_COLOR_ATTACHMENT30:
2041 case GL_COLOR_ATTACHMENT31:
2042 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2043 {
2044 return error(GL_INVALID_ENUM);
2045 }
2046 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
2047 break;
2048 case GL_DEPTH_ATTACHMENT:
2049 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
2050 break;
2051 case GL_STENCIL_ATTACHMENT:
2052 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
2053 break;
2054 case GL_DEPTH_STENCIL_ATTACHMENT:
2055 if(clientVersion >= 3)
2056 {
2057 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
2058 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
2059 break;
2060 }
2061 else return error(GL_INVALID_ENUM);
2062 default:
2063 return error(GL_INVALID_ENUM);
2064 }
2065 }
2066}
2067
2068void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
2069{
2070 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
2071 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
2072
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002073 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002074 {
2075 return error(GL_INVALID_ENUM);
2076 }
2077
2078 es2::Context *context = es2::getContext();
2079
2080 if(context)
2081 {
Nicolas Capensd5401e22017-03-16 17:32:43 -04002082 GLint clientVersion = context->getClientVersion();
2083
Nicolas Capens0bac2852016-05-07 06:09:58 -04002084 if(texture == 0)
2085 {
2086 textarget = GL_NONE;
2087 }
2088 else
2089 {
2090 es2::Texture *tex = context->getTexture(texture);
2091
2092 if(!tex)
2093 {
2094 return error(GL_INVALID_OPERATION);
2095 }
2096
2097 switch(textarget)
2098 {
2099 case GL_TEXTURE_2D:
2100 if(tex->getTarget() != GL_TEXTURE_2D)
2101 {
2102 return error(GL_INVALID_OPERATION);
2103 }
2104 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002105 case GL_TEXTURE_RECTANGLE_ARB:
2106 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
2107 {
2108 return error(GL_INVALID_OPERATION);
2109 }
2110 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002111 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2112 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2113 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2114 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2115 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2116 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2117 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2118 {
2119 return error(GL_INVALID_OPERATION);
2120 }
2121 break;
2122 default:
2123 return error(GL_INVALID_ENUM);
2124 }
2125
Nicolas Capensd5401e22017-03-16 17:32:43 -04002126 if((level != 0) && (clientVersion < 3))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002127 {
2128 return error(GL_INVALID_VALUE);
2129 }
2130
2131 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2132 {
2133 return error(GL_INVALID_VALUE);
2134 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002135
2136 if(tex->isCompressed(textarget, level))
2137 {
2138 return error(GL_INVALID_OPERATION);
2139 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002140 }
2141
2142 es2::Framebuffer *framebuffer = nullptr;
2143 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002144 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002145 {
2146 framebuffer = context->getReadFramebuffer();
2147 framebufferName = context->getReadFramebufferName();
2148 }
2149 else
2150 {
2151 framebuffer = context->getDrawFramebuffer();
2152 framebufferName = context->getDrawFramebufferName();
2153 }
2154
2155 if(framebufferName == 0 || !framebuffer)
2156 {
2157 return error(GL_INVALID_OPERATION);
2158 }
2159
2160 switch(attachment)
2161 {
2162 case GL_COLOR_ATTACHMENT0:
2163 case GL_COLOR_ATTACHMENT1:
2164 case GL_COLOR_ATTACHMENT2:
2165 case GL_COLOR_ATTACHMENT3:
2166 case GL_COLOR_ATTACHMENT4:
2167 case GL_COLOR_ATTACHMENT5:
2168 case GL_COLOR_ATTACHMENT6:
2169 case GL_COLOR_ATTACHMENT7:
2170 case GL_COLOR_ATTACHMENT8:
2171 case GL_COLOR_ATTACHMENT9:
2172 case GL_COLOR_ATTACHMENT10:
2173 case GL_COLOR_ATTACHMENT11:
2174 case GL_COLOR_ATTACHMENT12:
2175 case GL_COLOR_ATTACHMENT13:
2176 case GL_COLOR_ATTACHMENT14:
2177 case GL_COLOR_ATTACHMENT15:
2178 case GL_COLOR_ATTACHMENT16:
2179 case GL_COLOR_ATTACHMENT17:
2180 case GL_COLOR_ATTACHMENT18:
2181 case GL_COLOR_ATTACHMENT19:
2182 case GL_COLOR_ATTACHMENT20:
2183 case GL_COLOR_ATTACHMENT21:
2184 case GL_COLOR_ATTACHMENT22:
2185 case GL_COLOR_ATTACHMENT23:
2186 case GL_COLOR_ATTACHMENT24:
2187 case GL_COLOR_ATTACHMENT25:
2188 case GL_COLOR_ATTACHMENT26:
2189 case GL_COLOR_ATTACHMENT27:
2190 case GL_COLOR_ATTACHMENT28:
2191 case GL_COLOR_ATTACHMENT29:
2192 case GL_COLOR_ATTACHMENT30:
2193 case GL_COLOR_ATTACHMENT31:
2194 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2195 {
2196 return error(GL_INVALID_ENUM);
2197 }
2198 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2199 break;
2200 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2201 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capensd5401e22017-03-16 17:32:43 -04002202 case GL_DEPTH_STENCIL_ATTACHMENT:
2203 if(clientVersion >= 3)
2204 {
2205 framebuffer->setDepthbuffer(textarget, texture, level);
2206 framebuffer->setStencilbuffer(textarget, texture, level);
2207 break;
2208 }
2209 else return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002210 default:
2211 return error(GL_INVALID_ENUM);
2212 }
2213 }
2214}
2215
2216void FrontFace(GLenum mode)
2217{
2218 TRACE("(GLenum mode = 0x%X)", mode);
2219
2220 switch(mode)
2221 {
2222 case GL_CW:
2223 case GL_CCW:
2224 {
2225 es2::Context *context = es2::getContext();
2226
2227 if(context)
2228 {
2229 context->setFrontFace(mode);
2230 }
2231 }
2232 break;
2233 default:
2234 return error(GL_INVALID_ENUM);
2235 }
2236}
2237
2238void GenBuffers(GLsizei n, GLuint* buffers)
2239{
2240 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2241
2242 if(n < 0)
2243 {
2244 return error(GL_INVALID_VALUE);
2245 }
2246
2247 es2::Context *context = es2::getContext();
2248
2249 if(context)
2250 {
2251 for(int i = 0; i < n; i++)
2252 {
2253 buffers[i] = context->createBuffer();
2254 }
2255 }
2256}
2257
2258void GenerateMipmap(GLenum target)
2259{
2260 TRACE("(GLenum target = 0x%X)", target);
2261
2262 es2::Context *context = es2::getContext();
2263
2264 if(context)
2265 {
2266 es2::Texture *texture = nullptr;
2267
2268 GLint clientVersion = context->getClientVersion();
2269
2270 switch(target)
2271 {
2272 case GL_TEXTURE_2D:
2273 texture = context->getTexture2D();
2274 break;
2275 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002276 {
2277 TextureCubeMap *cube = context->getTextureCubeMap();
2278 texture = cube;
2279
2280 if(!cube->isCubeComplete())
2281 {
2282 return error(GL_INVALID_OPERATION);
2283 }
2284 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002285 break;
2286 case GL_TEXTURE_2D_ARRAY:
2287 if(clientVersion < 3)
2288 {
2289 return error(GL_INVALID_ENUM);
2290 }
2291 else
2292 {
2293 texture = context->getTexture2DArray();
2294 }
2295 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002296 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002297 texture = context->getTexture3D();
2298 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002299 case GL_TEXTURE_RECTANGLE_ARB:
2300 texture = context->getTexture2DRect();
2301 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002302 default:
2303 return error(GL_INVALID_ENUM);
2304 }
2305
Nicolas Capense6115342017-12-18 15:58:46 -05002306 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel()), clientVersion))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002307 {
2308 return error(GL_INVALID_OPERATION);
2309 }
2310
Nicolas Capens0bac2852016-05-07 06:09:58 -04002311 texture->generateMipmaps();
2312 }
2313}
2314
2315void GenFencesNV(GLsizei n, GLuint* fences)
2316{
2317 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2318
2319 if(n < 0)
2320 {
2321 return error(GL_INVALID_VALUE);
2322 }
2323
2324 es2::Context *context = es2::getContext();
2325
2326 if(context)
2327 {
2328 for(int i = 0; i < n; i++)
2329 {
2330 fences[i] = context->createFence();
2331 }
2332 }
2333}
2334
2335void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2336{
2337 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2338
2339 if(n < 0)
2340 {
2341 return error(GL_INVALID_VALUE);
2342 }
2343
2344 es2::Context *context = es2::getContext();
2345
2346 if(context)
2347 {
2348 for(int i = 0; i < n; i++)
2349 {
2350 framebuffers[i] = context->createFramebuffer();
2351 }
2352 }
2353}
2354
2355void GenQueriesEXT(GLsizei n, GLuint* ids)
2356{
2357 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2358
2359 if(n < 0)
2360 {
2361 return error(GL_INVALID_VALUE);
2362 }
2363
2364 es2::Context *context = es2::getContext();
2365
2366 if(context)
2367 {
2368 for(int i = 0; i < n; i++)
2369 {
2370 ids[i] = context->createQuery();
2371 }
2372 }
2373}
2374
2375void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2376{
2377 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2378
2379 if(n < 0)
2380 {
2381 return error(GL_INVALID_VALUE);
2382 }
2383
2384 es2::Context *context = es2::getContext();
2385
2386 if(context)
2387 {
2388 for(int i = 0; i < n; i++)
2389 {
2390 renderbuffers[i] = context->createRenderbuffer();
2391 }
2392 }
2393}
2394
2395void GenTextures(GLsizei n, GLuint* textures)
2396{
2397 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2398
2399 if(n < 0)
2400 {
2401 return error(GL_INVALID_VALUE);
2402 }
2403
2404 es2::Context *context = es2::getContext();
2405
2406 if(context)
2407 {
2408 for(int i = 0; i < n; i++)
2409 {
2410 textures[i] = context->createTexture();
2411 }
2412 }
2413}
2414
2415void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2416{
2417 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2418 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2419 program, index, bufsize, length, size, type, name);
2420
2421 if(bufsize < 0)
2422 {
2423 return error(GL_INVALID_VALUE);
2424 }
2425
2426 es2::Context *context = es2::getContext();
2427
2428 if(context)
2429 {
2430 es2::Program *programObject = context->getProgram(program);
2431
2432 if(!programObject)
2433 {
2434 if(context->getShader(program))
2435 {
2436 return error(GL_INVALID_OPERATION);
2437 }
2438 else
2439 {
2440 return error(GL_INVALID_VALUE);
2441 }
2442 }
2443
2444 if(index >= programObject->getActiveAttributeCount())
2445 {
2446 return error(GL_INVALID_VALUE);
2447 }
2448
2449 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2450 }
2451}
2452
2453void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2454{
2455 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2456 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2457 program, index, bufsize, length, size, type, name);
2458
2459 if(bufsize < 0)
2460 {
2461 return error(GL_INVALID_VALUE);
2462 }
2463
2464 es2::Context *context = es2::getContext();
2465
2466 if(context)
2467 {
2468 es2::Program *programObject = context->getProgram(program);
2469
2470 if(!programObject)
2471 {
2472 if(context->getShader(program))
2473 {
2474 return error(GL_INVALID_OPERATION);
2475 }
2476 else
2477 {
2478 return error(GL_INVALID_VALUE);
2479 }
2480 }
2481
2482 if(index >= programObject->getActiveUniformCount())
2483 {
2484 return error(GL_INVALID_VALUE);
2485 }
2486
2487 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2488 }
2489}
2490
2491void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2492{
2493 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2494 program, maxcount, count, shaders);
2495
2496 if(maxcount < 0)
2497 {
2498 return error(GL_INVALID_VALUE);
2499 }
2500
2501 es2::Context *context = es2::getContext();
2502
2503 if(context)
2504 {
2505 es2::Program *programObject = context->getProgram(program);
2506
2507 if(!programObject)
2508 {
2509 if(context->getShader(program))
2510 {
2511 return error(GL_INVALID_OPERATION);
2512 }
2513 else
2514 {
2515 return error(GL_INVALID_VALUE);
2516 }
2517 }
2518
2519 return programObject->getAttachedShaders(maxcount, count, shaders);
2520 }
2521}
2522
2523int GetAttribLocation(GLuint program, const GLchar* name)
2524{
2525 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2526
2527 es2::Context *context = es2::getContext();
2528
2529 if(context)
2530 {
2531
2532 es2::Program *programObject = context->getProgram(program);
2533
2534 if(!programObject)
2535 {
2536 if(context->getShader(program))
2537 {
2538 return error(GL_INVALID_OPERATION, -1);
2539 }
2540 else
2541 {
2542 return error(GL_INVALID_VALUE, -1);
2543 }
2544 }
2545
2546 if(!programObject->isLinked())
2547 {
2548 return error(GL_INVALID_OPERATION, -1);
2549 }
2550
2551 return programObject->getAttributeLocation(name);
2552 }
2553
2554 return -1;
2555}
2556
2557void GetBooleanv(GLenum pname, GLboolean* params)
2558{
2559 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2560
2561 es2::Context *context = es2::getContext();
2562
2563 if(context)
2564 {
2565 if(!(context->getBooleanv(pname, params)))
2566 {
2567 GLenum nativeType;
2568 unsigned int numParams = 0;
2569 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2570 return error(GL_INVALID_ENUM);
2571
2572 if(numParams == 0)
2573 return; // it is known that the pname is valid, but there are no parameters to return
2574
2575 if(nativeType == GL_FLOAT)
2576 {
2577 GLfloat *floatParams = nullptr;
2578 floatParams = new GLfloat[numParams];
2579
2580 context->getFloatv(pname, floatParams);
2581
2582 for(unsigned int i = 0; i < numParams; ++i)
2583 {
2584 if(floatParams[i] == 0.0f)
2585 params[i] = GL_FALSE;
2586 else
2587 params[i] = GL_TRUE;
2588 }
2589
2590 delete [] floatParams;
2591 }
2592 else if(nativeType == GL_INT)
2593 {
2594 GLint *intParams = nullptr;
2595 intParams = new GLint[numParams];
2596
2597 context->getIntegerv(pname, intParams);
2598
2599 for(unsigned int i = 0; i < numParams; ++i)
2600 {
2601 if(intParams[i] == 0)
2602 params[i] = GL_FALSE;
2603 else
2604 params[i] = GL_TRUE;
2605 }
2606
2607 delete [] intParams;
2608 }
2609 }
2610 }
2611}
2612
2613void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2614{
2615 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2616
2617 es2::Context *context = es2::getContext();
2618
2619 if(context)
2620 {
2621 es2::Buffer *buffer;
2622 if(!context->getBuffer(target, &buffer))
2623 {
2624 return error(GL_INVALID_ENUM);
2625 }
2626
2627 if(!buffer)
2628 {
2629 // A null buffer means that "0" is bound to the requested buffer target
2630 return error(GL_INVALID_OPERATION);
2631 }
2632
2633 GLint clientVersion = context->getClientVersion();
2634
2635 switch(pname)
2636 {
2637 case GL_BUFFER_USAGE:
2638 *params = buffer->usage();
2639 break;
2640 case GL_BUFFER_SIZE:
2641 *params = (GLint)buffer->size();
2642 break;
2643 case GL_BUFFER_ACCESS_FLAGS:
2644 if(clientVersion >= 3)
2645 {
2646 *params = buffer->access();
2647 break;
2648 }
2649 else return error(GL_INVALID_ENUM);
2650 case GL_BUFFER_MAPPED:
2651 if(clientVersion >= 3)
2652 {
2653 *params = buffer->isMapped();
2654 break;
2655 }
2656 else return error(GL_INVALID_ENUM);
2657 case GL_BUFFER_MAP_LENGTH:
2658 if(clientVersion >= 3)
2659 {
2660 *params = (GLint)buffer->length();
2661 break;
2662 }
2663 else return error(GL_INVALID_ENUM);
2664 case GL_BUFFER_MAP_OFFSET:
2665 if(clientVersion >= 3)
2666 {
2667 *params = (GLint)buffer->offset();
2668 break;
2669 }
2670 else return error(GL_INVALID_ENUM);
2671 default:
2672 return error(GL_INVALID_ENUM);
2673 }
2674 }
2675}
2676
2677GLenum GetError(void)
2678{
2679 TRACE("()");
2680
2681 es2::Context *context = es2::getContext();
2682
2683 if(context)
2684 {
2685 return context->getError();
2686 }
2687
2688 return GL_NO_ERROR;
2689}
2690
2691void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2692{
2693 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2694
2695 es2::Context *context = es2::getContext();
2696
2697 if(context)
2698 {
2699 es2::Fence *fenceObject = context->getFence(fence);
2700
2701 if(!fenceObject)
2702 {
2703 return error(GL_INVALID_OPERATION);
2704 }
2705
2706 fenceObject->getFenceiv(pname, params);
2707 }
2708}
2709
2710void GetFloatv(GLenum pname, GLfloat* params)
2711{
2712 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2713
2714 es2::Context *context = es2::getContext();
2715
2716 if(context)
2717 {
2718 if(!(context->getFloatv(pname, params)))
2719 {
2720 GLenum nativeType;
2721 unsigned int numParams = 0;
2722 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2723 return error(GL_INVALID_ENUM);
2724
2725 if(numParams == 0)
2726 return; // it is known that the pname is valid, but that there are no parameters to return.
2727
2728 if(nativeType == GL_BOOL)
2729 {
2730 GLboolean *boolParams = nullptr;
2731 boolParams = new GLboolean[numParams];
2732
2733 context->getBooleanv(pname, boolParams);
2734
2735 for(unsigned int i = 0; i < numParams; ++i)
2736 {
2737 if(boolParams[i] == GL_FALSE)
2738 params[i] = 0.0f;
2739 else
2740 params[i] = 1.0f;
2741 }
2742
2743 delete [] boolParams;
2744 }
2745 else if(nativeType == GL_INT)
2746 {
2747 GLint *intParams = nullptr;
2748 intParams = new GLint[numParams];
2749
2750 context->getIntegerv(pname, intParams);
2751
2752 for(unsigned int i = 0; i < numParams; ++i)
2753 {
2754 params[i] = (GLfloat)intParams[i];
2755 }
2756
2757 delete [] intParams;
2758 }
2759 }
2760 }
2761}
2762
2763void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2764{
2765 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2766 target, attachment, pname, params);
2767
2768 es2::Context *context = es2::getContext();
2769
2770 if(context)
2771 {
2772 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2773 {
2774 return error(GL_INVALID_ENUM);
2775 }
2776
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002777 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002778
Nicolas Capens0bac2852016-05-07 06:09:58 -04002779 if(target == GL_READ_FRAMEBUFFER)
2780 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002781 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002782 }
2783 else
2784 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002785 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002786 }
2787
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002788 GLint clientVersion = context->getClientVersion();
2789
2790 if(framebufferName == 0) // Default framebuffer.
2791 {
2792 if(clientVersion < 3)
2793 {
2794 return error(GL_INVALID_OPERATION);
2795 }
2796 }
2797
Nicolas Capens0bac2852016-05-07 06:09:58 -04002798 switch(attachment)
2799 {
2800 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002801 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002802 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002803 if(clientVersion < 3)
2804 {
2805 return error(GL_INVALID_ENUM);
2806 }
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002807
2808 if(framebufferName != 0)
2809 {
2810 return error(GL_INVALID_OPERATION);
2811 }
2812 break;
2813 case GL_DEPTH_ATTACHMENT:
2814 case GL_STENCIL_ATTACHMENT:
2815 if(framebufferName == 0)
2816 {
2817 return error(GL_INVALID_OPERATION);
2818 }
2819 break;
2820 case GL_DEPTH_STENCIL_ATTACHMENT:
2821 if(clientVersion < 3)
2822 {
2823 return error(GL_INVALID_ENUM);
2824 }
2825
2826 if(framebufferName == 0)
2827 {
2828 return error(GL_INVALID_OPERATION);
2829 }
2830 break;
2831 default:
2832 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2833 {
2834 if(framebufferName == 0)
2835 {
2836 return error(GL_INVALID_OPERATION);
2837 }
2838 }
2839 else return error(GL_INVALID_ENUM);
2840 }
2841
2842 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2843
2844 GLenum attachmentType;
2845 GLuint attachmentHandle;
2846 GLint attachmentLayer;
2847 Renderbuffer *renderbuffer = nullptr;
2848 switch(attachment)
2849 {
2850 case GL_BACK:
2851 attachmentType = framebuffer->getColorbufferType(0);
2852 attachmentHandle = framebuffer->getColorbufferName(0);
2853 attachmentLayer = framebuffer->getColorbufferLayer(0);
2854 renderbuffer = framebuffer->getColorbuffer(0);
2855 break;
2856 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002857 case GL_DEPTH_ATTACHMENT:
2858 attachmentType = framebuffer->getDepthbufferType();
2859 attachmentHandle = framebuffer->getDepthbufferName();
2860 attachmentLayer = framebuffer->getDepthbufferLayer();
2861 renderbuffer = framebuffer->getDepthbuffer();
2862 break;
2863 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002864 case GL_STENCIL_ATTACHMENT:
2865 attachmentType = framebuffer->getStencilbufferType();
2866 attachmentHandle = framebuffer->getStencilbufferName();
2867 attachmentLayer = framebuffer->getStencilbufferLayer();
2868 renderbuffer = framebuffer->getStencilbuffer();
2869 break;
2870 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002871 attachmentType = framebuffer->getDepthbufferType();
2872 attachmentHandle = framebuffer->getDepthbufferName();
2873 attachmentLayer = framebuffer->getDepthbufferLayer();
2874 renderbuffer = framebuffer->getDepthbuffer();
2875
2876 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002877 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002878 // Different attachments to DEPTH and STENCIL, query fails
2879 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002880 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002881 break;
2882 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002883 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2884 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2885 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2886 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2887 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2888 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002889 }
2890
2891 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002892 if(framebufferName == 0)
2893 {
2894 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2895 }
2896 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002897 {
2898 attachmentObjectType = attachmentType;
2899 }
2900 else if(es2::IsTextureTarget(attachmentType))
2901 {
2902 attachmentObjectType = GL_TEXTURE;
2903 }
2904 else UNREACHABLE(attachmentType);
2905
2906 if(attachmentObjectType != GL_NONE)
2907 {
2908 switch(pname)
2909 {
2910 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2911 *params = attachmentObjectType;
2912 break;
2913 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002914 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002915 {
2916 *params = attachmentHandle;
2917 }
2918 else
2919 {
2920 return error(GL_INVALID_ENUM);
2921 }
2922 break;
2923 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2924 if(attachmentObjectType == GL_TEXTURE)
2925 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002926 *params = clientVersion < 3 ? 0 : renderbuffer->getLevel(); // glFramebufferTexture2D does not allow level to be set to anything else in GL ES 2.0
Nicolas Capens0bac2852016-05-07 06:09:58 -04002927 }
2928 else
2929 {
2930 return error(GL_INVALID_ENUM);
2931 }
2932 break;
2933 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2934 if(attachmentObjectType == GL_TEXTURE)
2935 {
2936 if(es2::IsCubemapTextureTarget(attachmentType))
2937 {
2938 *params = attachmentType;
2939 }
2940 else
2941 {
2942 *params = 0;
2943 }
2944 }
2945 else
2946 {
2947 return error(GL_INVALID_ENUM);
2948 }
2949 break;
2950 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
2951 if(clientVersion >= 3)
2952 {
2953 *params = attachmentLayer;
2954 }
2955 else return error(GL_INVALID_ENUM);
2956 break;
2957 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2958 if(clientVersion >= 3)
2959 {
2960 *params = renderbuffer->getRedSize();
2961 }
2962 else return error(GL_INVALID_ENUM);
2963 break;
2964 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2965 if(clientVersion >= 3)
2966 {
2967 *params = renderbuffer->getGreenSize();
2968 }
2969 else return error(GL_INVALID_ENUM);
2970 break;
2971 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2972 if(clientVersion >= 3)
2973 {
2974 *params = renderbuffer->getBlueSize();
2975 }
2976 else return error(GL_INVALID_ENUM);
2977 break;
2978 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2979 if(clientVersion >= 3)
2980 {
2981 *params = renderbuffer->getAlphaSize();
2982 }
2983 else return error(GL_INVALID_ENUM);
2984 break;
2985 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2986 if(clientVersion >= 3)
2987 {
2988 *params = renderbuffer->getDepthSize();
2989 }
2990 else return error(GL_INVALID_ENUM);
2991 break;
2992 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2993 if(clientVersion >= 3)
2994 {
2995 *params = renderbuffer->getStencilSize();
2996 }
2997 else return error(GL_INVALID_ENUM);
2998 break;
2999 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04003000 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
3001 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003002 {
Nicolas Capens505b7712016-06-14 01:08:12 -04003003 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003004 }
Nicolas Capens505b7712016-06-14 01:08:12 -04003005
Nicolas Capensc61f46b2017-12-04 16:07:22 -05003006 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003007 break;
3008 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3009 if(clientVersion >= 3)
3010 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05003011 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04003012 }
3013 else return error(GL_INVALID_ENUM);
3014 break;
3015 default:
3016 return error(GL_INVALID_ENUM);
3017 }
3018 }
3019 else
3020 {
3021 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3022 // is NONE, then querying any other pname will generate INVALID_ENUM.
3023
3024 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3025 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3026 // INVALID_OPERATION for all other pnames
3027
3028 switch(pname)
3029 {
3030 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3031 *params = GL_NONE;
3032 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003033 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3034 if(clientVersion < 3)
3035 {
3036 return error(GL_INVALID_ENUM);
3037 }
3038 *params = 0;
3039 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003040 default:
3041 if(clientVersion < 3)
3042 {
3043 return error(GL_INVALID_ENUM);
3044 }
3045 else
3046 {
3047 return error(GL_INVALID_OPERATION);
3048 }
3049 }
3050 }
3051 }
3052}
3053
3054GLenum GetGraphicsResetStatusEXT(void)
3055{
3056 TRACE("()");
3057
3058 return GL_NO_ERROR;
3059}
3060
3061void GetIntegerv(GLenum pname, GLint* params)
3062{
3063 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
3064
3065 es2::Context *context = es2::getContext();
3066
3067 if(!context)
3068 {
3069 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
3070 #ifdef __ANDROID__
3071 ALOGI("expected_badness glGetIntegerv() called without current context.");
3072 #else
3073 ERR("glGetIntegerv() called without current context.");
3074 #endif
3075
3076 // This is not spec compliant! When there is no current GL context, functions should
3077 // have no side effects. Google Maps queries these values before creating a context,
3078 // so we need this as a bug-compatible workaround.
3079 switch(pname)
3080 {
3081 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
3082 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
3083 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
3084 case GL_STENCIL_BITS: *params = 8; return;
3085 case GL_ALIASED_LINE_WIDTH_RANGE:
3086 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
3087 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
3088 return;
3089 }
3090 }
3091
3092 if(context)
3093 {
3094 if(!(context->getIntegerv(pname, params)))
3095 {
3096 GLenum nativeType;
3097 unsigned int numParams = 0;
3098 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3099 return error(GL_INVALID_ENUM);
3100
3101 if(numParams == 0)
3102 return; // it is known that pname is valid, but there are no parameters to return
3103
3104 if(nativeType == GL_BOOL)
3105 {
3106 GLboolean *boolParams = nullptr;
3107 boolParams = new GLboolean[numParams];
3108
3109 context->getBooleanv(pname, boolParams);
3110
3111 for(unsigned int i = 0; i < numParams; ++i)
3112 {
3113 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3114 }
3115
3116 delete [] boolParams;
3117 }
3118 else if(nativeType == GL_FLOAT)
3119 {
3120 GLfloat *floatParams = nullptr;
3121 floatParams = new GLfloat[numParams];
3122
3123 context->getFloatv(pname, floatParams);
3124
3125 for(unsigned int i = 0; i < numParams; ++i)
3126 {
3127 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3128 {
Alexis Hetu60e20282017-12-13 07:42:22 -05003129 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003130 }
3131 else
3132 {
3133 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3134 }
3135 }
3136
3137 delete [] floatParams;
3138 }
3139 }
3140 }
3141}
3142
3143void GetProgramiv(GLuint program, GLenum pname, GLint* params)
3144{
3145 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
3146
3147 es2::Context *context = es2::getContext();
3148
3149 if(context)
3150 {
3151 es2::Program *programObject = context->getProgram(program);
3152
3153 if(!programObject)
3154 {
3155 if(context->getShader(program))
3156 {
3157 return error(GL_INVALID_OPERATION);
3158 }
3159 else
3160 {
3161 return error(GL_INVALID_VALUE);
3162 }
3163 }
3164
3165 GLint clientVersion = egl::getClientVersion();
3166
3167 switch(pname)
3168 {
3169 case GL_DELETE_STATUS:
3170 *params = programObject->isFlaggedForDeletion();
3171 return;
3172 case GL_LINK_STATUS:
3173 *params = programObject->isLinked();
3174 return;
3175 case GL_VALIDATE_STATUS:
3176 *params = programObject->isValidated();
3177 return;
3178 case GL_INFO_LOG_LENGTH:
3179 *params = (GLint)programObject->getInfoLogLength();
3180 return;
3181 case GL_ATTACHED_SHADERS:
3182 *params = programObject->getAttachedShadersCount();
3183 return;
3184 case GL_ACTIVE_ATTRIBUTES:
3185 *params = (GLint)programObject->getActiveAttributeCount();
3186 return;
3187 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3188 *params = programObject->getActiveAttributeMaxLength();
3189 return;
3190 case GL_ACTIVE_UNIFORMS:
3191 *params = (GLint)programObject->getActiveUniformCount();
3192 return;
3193 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3194 *params = programObject->getActiveUniformMaxLength();
3195 return;
3196 case GL_ACTIVE_UNIFORM_BLOCKS:
3197 if(clientVersion >= 3)
3198 {
3199 *params = (GLint)programObject->getActiveUniformBlockCount();
3200 return;
3201 }
3202 else return error(GL_INVALID_ENUM);
3203 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3204 if(clientVersion >= 3)
3205 {
3206 *params = programObject->getActiveUniformBlockMaxLength();
3207 return;
3208 }
3209 else return error(GL_INVALID_ENUM);
3210 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3211 if(clientVersion >= 3)
3212 {
3213 *params = programObject->getTransformFeedbackBufferMode();
3214 return;
3215 }
3216 else return error(GL_INVALID_ENUM);
3217 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3218 if(clientVersion >= 3)
3219 {
3220 *params = programObject->getTransformFeedbackVaryingCount();
3221 return;
3222 }
3223 else return error(GL_INVALID_ENUM);
3224 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3225 if(clientVersion >= 3)
3226 {
3227 *params = programObject->getTransformFeedbackVaryingMaxLength();
3228 return;
3229 }
3230 else return error(GL_INVALID_ENUM);
3231 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3232 if(clientVersion >= 3)
3233 {
3234 *params = programObject->getBinaryRetrievableHint();
3235 return;
3236 }
3237 else return error(GL_INVALID_ENUM);
3238 case GL_PROGRAM_BINARY_LENGTH:
3239 if(clientVersion >= 3)
3240 {
3241 *params = programObject->getBinaryLength();
3242 return;
3243 }
3244 else return error(GL_INVALID_ENUM);
3245 default:
3246 return error(GL_INVALID_ENUM);
3247 }
3248 }
3249}
3250
3251void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3252{
3253 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3254 program, bufsize, length, infolog);
3255
3256 if(bufsize < 0)
3257 {
3258 return error(GL_INVALID_VALUE);
3259 }
3260
3261 es2::Context *context = es2::getContext();
3262
3263 if(context)
3264 {
3265 es2::Program *programObject = context->getProgram(program);
3266
3267 if(!programObject)
3268 {
3269 if(context->getShader(program))
3270 {
3271 return error(GL_INVALID_OPERATION);
3272 }
3273 else
3274 {
3275 return error(GL_INVALID_VALUE);
3276 }
3277 }
3278
3279 programObject->getInfoLog(bufsize, length, infolog);
3280 }
3281}
3282
3283void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3284{
3285 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3286
3287 switch(pname)
3288 {
3289 case GL_CURRENT_QUERY_EXT:
3290 break;
3291 default:
3292 return error(GL_INVALID_ENUM);
3293 }
3294
3295 es2::Context *context = es2::getContext();
3296
3297 if(context)
3298 {
3299 params[0] = context->getActiveQuery(target);
3300 }
3301}
3302
3303void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3304{
3305 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3306
3307 switch(pname)
3308 {
3309 case GL_QUERY_RESULT_EXT:
3310 case GL_QUERY_RESULT_AVAILABLE_EXT:
3311 break;
3312 default:
3313 return error(GL_INVALID_ENUM);
3314 }
3315
3316 es2::Context *context = es2::getContext();
3317
3318 if(context)
3319 {
3320 es2::Query *queryObject = context->getQuery(name);
3321
3322 if(!queryObject)
3323 {
3324 return error(GL_INVALID_OPERATION);
3325 }
3326
3327 if(context->getActiveQuery(queryObject->getType()) == name)
3328 {
3329 return error(GL_INVALID_OPERATION);
3330 }
3331
3332 switch(pname)
3333 {
3334 case GL_QUERY_RESULT_EXT:
3335 params[0] = queryObject->getResult();
3336 break;
3337 case GL_QUERY_RESULT_AVAILABLE_EXT:
3338 params[0] = queryObject->isResultAvailable();
3339 break;
3340 default:
3341 ASSERT(false);
3342 }
3343 }
3344}
3345
3346void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3347{
3348 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3349
3350 es2::Context *context = es2::getContext();
3351
3352 if(context)
3353 {
3354 if(target != GL_RENDERBUFFER)
3355 {
3356 return error(GL_INVALID_ENUM);
3357 }
3358
3359 if(context->getRenderbufferName() == 0)
3360 {
3361 return error(GL_INVALID_OPERATION);
3362 }
3363
3364 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3365
3366 switch(pname)
3367 {
3368 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3369 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003370 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3371 {
3372 GLint internalformat = renderbuffer->getFormat();
3373 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3374 }
3375 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003376 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3377 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3378 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3379 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3380 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3381 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003382 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003383 default:
3384 return error(GL_INVALID_ENUM);
3385 }
3386 }
3387}
3388
3389void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3390{
3391 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3392
3393 es2::Context *context = es2::getContext();
3394
3395 if(context)
3396 {
3397 es2::Shader *shaderObject = context->getShader(shader);
3398
3399 if(!shaderObject)
3400 {
3401 if(context->getProgram(shader))
3402 {
3403 return error(GL_INVALID_OPERATION);
3404 }
3405 else
3406 {
3407 return error(GL_INVALID_VALUE);
3408 }
3409 }
3410
3411 switch(pname)
3412 {
3413 case GL_SHADER_TYPE:
3414 *params = shaderObject->getType();
3415 return;
3416 case GL_DELETE_STATUS:
3417 *params = shaderObject->isFlaggedForDeletion();
3418 return;
3419 case GL_COMPILE_STATUS:
3420 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3421 return;
3422 case GL_INFO_LOG_LENGTH:
3423 *params = (GLint)shaderObject->getInfoLogLength();
3424 return;
3425 case GL_SHADER_SOURCE_LENGTH:
3426 *params = (GLint)shaderObject->getSourceLength();
3427 return;
3428 default:
3429 return error(GL_INVALID_ENUM);
3430 }
3431 }
3432}
3433
3434void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3435{
3436 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3437 shader, bufsize, length, infolog);
3438
3439 if(bufsize < 0)
3440 {
3441 return error(GL_INVALID_VALUE);
3442 }
3443
3444 es2::Context *context = es2::getContext();
3445
3446 if(context)
3447 {
3448 es2::Shader *shaderObject = context->getShader(shader);
3449
3450 if(!shaderObject)
3451 {
3452 if(context->getProgram(shader))
3453 {
3454 return error(GL_INVALID_OPERATION);
3455 }
3456 else
3457 {
3458 return error(GL_INVALID_VALUE);
3459 }
3460 }
3461
3462 shaderObject->getInfoLog(bufsize, length, infolog);
3463 }
3464}
3465
3466void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3467{
3468 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3469 shadertype, precisiontype, range, precision);
3470
3471 switch(shadertype)
3472 {
3473 case GL_VERTEX_SHADER:
3474 case GL_FRAGMENT_SHADER:
3475 break;
3476 default:
3477 return error(GL_INVALID_ENUM);
3478 }
3479
3480 switch(precisiontype)
3481 {
3482 case GL_LOW_FLOAT:
3483 case GL_MEDIUM_FLOAT:
3484 case GL_HIGH_FLOAT:
3485 // IEEE 754 single-precision
3486 range[0] = 127;
3487 range[1] = 127;
3488 *precision = 23;
3489 break;
3490 case GL_LOW_INT:
3491 case GL_MEDIUM_INT:
3492 case GL_HIGH_INT:
3493 // Full integer precision is supported
3494 range[0] = 31;
3495 range[1] = 30;
3496 *precision = 0;
3497 break;
3498 default:
3499 return error(GL_INVALID_ENUM);
3500 }
3501}
3502
3503void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3504{
3505 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3506 shader, bufsize, length, source);
3507
3508 if(bufsize < 0)
3509 {
3510 return error(GL_INVALID_VALUE);
3511 }
3512
3513 es2::Context *context = es2::getContext();
3514
3515 if(context)
3516 {
3517 es2::Shader *shaderObject = context->getShader(shader);
3518
3519 if(!shaderObject)
3520 {
3521 if(context->getProgram(shader))
3522 {
3523 return error(GL_INVALID_OPERATION);
3524 }
3525 else
3526 {
3527 return error(GL_INVALID_VALUE);
3528 }
3529 }
3530
3531 shaderObject->getSource(bufsize, length, source);
3532 }
3533}
3534
3535const GLubyte* GetString(GLenum name)
3536{
3537 TRACE("(GLenum name = 0x%X)", name);
3538
3539 switch(name)
3540 {
3541 case GL_VENDOR:
3542 return (GLubyte*)"Google Inc.";
3543 case GL_RENDERER:
3544 return (GLubyte*)"Google SwiftShader";
3545 case GL_VERSION:
3546 {
3547 es2::Context *context = es2::getContext();
3548 return (context && (context->getClientVersion() >= 3)) ?
3549 (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING :
3550 (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3551 }
3552 case GL_SHADING_LANGUAGE_VERSION:
3553 {
3554 es2::Context *context = es2::getContext();
3555 return (context && (context->getClientVersion() >= 3)) ?
3556 (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING :
3557 (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3558 }
3559 case GL_EXTENSIONS:
3560 {
3561 es2::Context *context = es2::getContext();
3562 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3563 }
3564 default:
3565 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3566 }
3567}
3568
3569void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3570{
3571 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3572
3573 es2::Context *context = es2::getContext();
3574
3575 if(context)
3576 {
3577 es2::Texture *texture;
3578
3579 GLint clientVersion = context->getClientVersion();
3580
3581 switch(target)
3582 {
3583 case GL_TEXTURE_2D:
3584 texture = context->getTexture2D();
3585 break;
3586 case GL_TEXTURE_CUBE_MAP:
3587 texture = context->getTextureCubeMap();
3588 break;
3589 case GL_TEXTURE_EXTERNAL_OES:
3590 texture = context->getTextureExternal();
3591 break;
3592 case GL_TEXTURE_2D_ARRAY:
3593 if(clientVersion < 3)
3594 {
3595 return error(GL_INVALID_ENUM);
3596 }
3597 else
3598 {
3599 texture = context->getTexture2DArray();
3600 }
3601 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003602 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003603 texture = context->getTexture3D();
3604 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003605 case GL_TEXTURE_RECTANGLE_ARB:
3606 texture = context->getTexture2DRect();
3607 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003608 default:
3609 return error(GL_INVALID_ENUM);
3610 }
3611
3612 switch(pname)
3613 {
3614 case GL_TEXTURE_MAG_FILTER:
3615 *params = (GLfloat)texture->getMagFilter();
3616 break;
3617 case GL_TEXTURE_MIN_FILTER:
3618 *params = (GLfloat)texture->getMinFilter();
3619 break;
3620 case GL_TEXTURE_WRAP_S:
3621 *params = (GLfloat)texture->getWrapS();
3622 break;
3623 case GL_TEXTURE_WRAP_T:
3624 *params = (GLfloat)texture->getWrapT();
3625 break;
3626 case GL_TEXTURE_WRAP_R_OES:
3627 *params = (GLfloat)texture->getWrapR();
3628 break;
3629 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3630 *params = texture->getMaxAnisotropy();
3631 break;
3632 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3633 *params = (GLfloat)1;
3634 break;
3635 case GL_TEXTURE_BASE_LEVEL:
3636 if(clientVersion >= 3)
3637 {
3638 *params = (GLfloat)texture->getBaseLevel();
3639 break;
3640 }
3641 else return error(GL_INVALID_ENUM);
3642 case GL_TEXTURE_COMPARE_FUNC:
3643 if(clientVersion >= 3)
3644 {
3645 *params = (GLfloat)texture->getCompareFunc();
3646 break;
3647 }
3648 else return error(GL_INVALID_ENUM);
3649 case GL_TEXTURE_COMPARE_MODE:
3650 if(clientVersion >= 3)
3651 {
3652 *params = (GLfloat)texture->getCompareMode();
3653 break;
3654 }
3655 else return error(GL_INVALID_ENUM);
3656 case GL_TEXTURE_IMMUTABLE_FORMAT:
3657 if(clientVersion >= 3)
3658 {
3659 *params = (GLfloat)texture->getImmutableFormat();
3660 break;
3661 }
3662 else return error(GL_INVALID_ENUM);
3663 case GL_TEXTURE_IMMUTABLE_LEVELS:
3664 if(clientVersion >= 3)
3665 {
3666 *params = (GLfloat)texture->getImmutableLevels();
3667 break;
3668 }
3669 else return error(GL_INVALID_ENUM);
3670 case GL_TEXTURE_MAX_LEVEL:
3671 if(clientVersion >= 3)
3672 {
3673 *params = (GLfloat)texture->getMaxLevel();
3674 break;
3675 }
3676 else return error(GL_INVALID_ENUM);
3677 case GL_TEXTURE_MAX_LOD:
3678 if(clientVersion >= 3)
3679 {
3680 *params = texture->getMaxLOD();
3681 break;
3682 }
3683 else return error(GL_INVALID_ENUM);
3684 case GL_TEXTURE_MIN_LOD:
3685 if(clientVersion >= 3)
3686 {
3687 *params = texture->getMinLOD();
3688 break;
3689 }
3690 else return error(GL_INVALID_ENUM);
3691 case GL_TEXTURE_SWIZZLE_R:
3692 if(clientVersion >= 3)
3693 {
3694 *params = (GLfloat)texture->getSwizzleR();
3695 break;
3696 }
3697 else return error(GL_INVALID_ENUM);
3698 case GL_TEXTURE_SWIZZLE_G:
3699 if(clientVersion >= 3)
3700 {
3701 *params = (GLfloat)texture->getSwizzleG();
3702 break;
3703 }
3704 else return error(GL_INVALID_ENUM);
3705 case GL_TEXTURE_SWIZZLE_B:
3706 if(clientVersion >= 3)
3707 {
3708 *params = (GLfloat)texture->getSwizzleB();
3709 break;
3710 }
3711 else return error(GL_INVALID_ENUM);
3712 case GL_TEXTURE_SWIZZLE_A:
3713 if(clientVersion >= 3)
3714 {
3715 *params = (GLfloat)texture->getSwizzleA();
3716 break;
3717 }
3718 else return error(GL_INVALID_ENUM);
3719 default:
3720 return error(GL_INVALID_ENUM);
3721 }
3722 }
3723}
3724
3725void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3726{
3727 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3728
3729 es2::Context *context = es2::getContext();
3730
3731 if(context)
3732 {
3733 es2::Texture *texture;
3734
3735 GLint clientVersion = context->getClientVersion();
3736
3737 switch(target)
3738 {
3739 case GL_TEXTURE_2D:
3740 texture = context->getTexture2D();
3741 break;
3742 case GL_TEXTURE_CUBE_MAP:
3743 texture = context->getTextureCubeMap();
3744 break;
3745 case GL_TEXTURE_EXTERNAL_OES:
3746 texture = context->getTextureExternal();
3747 break;
3748 case GL_TEXTURE_2D_ARRAY:
3749 if(clientVersion < 3)
3750 {
3751 return error(GL_INVALID_ENUM);
3752 }
3753 else
3754 {
3755 texture = context->getTexture2DArray();
3756 }
3757 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003758 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04003759 texture = context->getTexture3D();
3760 break;
Alexis Hetu46768622018-01-16 22:09:28 -05003761 case GL_TEXTURE_RECTANGLE_ARB:
3762 texture = context->getTexture2DRect();
3763 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003764 default:
3765 return error(GL_INVALID_ENUM);
3766 }
3767
3768 switch(pname)
3769 {
3770 case GL_TEXTURE_MAG_FILTER:
3771 *params = texture->getMagFilter();
3772 break;
3773 case GL_TEXTURE_MIN_FILTER:
3774 *params = texture->getMinFilter();
3775 break;
3776 case GL_TEXTURE_WRAP_S:
3777 *params = texture->getWrapS();
3778 break;
3779 case GL_TEXTURE_WRAP_T:
3780 *params = texture->getWrapT();
3781 break;
3782 case GL_TEXTURE_WRAP_R_OES:
3783 *params = texture->getWrapR();
3784 break;
3785 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3786 *params = (GLint)texture->getMaxAnisotropy();
3787 break;
3788 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3789 *params = 1;
3790 break;
3791 case GL_TEXTURE_BASE_LEVEL:
3792 if(clientVersion >= 3)
3793 {
3794 *params = texture->getBaseLevel();
3795 break;
3796 }
3797 else return error(GL_INVALID_ENUM);
3798 case GL_TEXTURE_COMPARE_FUNC:
3799 if(clientVersion >= 3)
3800 {
3801 *params = (GLint)texture->getCompareFunc();
3802 break;
3803 }
3804 else return error(GL_INVALID_ENUM);
3805 case GL_TEXTURE_COMPARE_MODE:
3806 if(clientVersion >= 3)
3807 {
3808 *params = (GLint)texture->getCompareMode();
3809 break;
3810 }
3811 else return error(GL_INVALID_ENUM);
3812 case GL_TEXTURE_IMMUTABLE_FORMAT:
3813 if(clientVersion >= 3)
3814 {
3815 *params = (GLint)texture->getImmutableFormat();
3816 break;
3817 }
3818 else return error(GL_INVALID_ENUM);
3819 case GL_TEXTURE_IMMUTABLE_LEVELS:
3820 if(clientVersion >= 3)
3821 {
3822 *params = (GLint)texture->getImmutableLevels();
3823 break;
3824 }
3825 else return error(GL_INVALID_ENUM);
3826 case GL_TEXTURE_MAX_LEVEL:
3827 if(clientVersion >= 3)
3828 {
3829 *params = texture->getMaxLevel();
3830 break;
3831 }
3832 else return error(GL_INVALID_ENUM);
3833 case GL_TEXTURE_MAX_LOD:
3834 if(clientVersion >= 3)
3835 {
3836 *params = (GLint)roundf(texture->getMaxLOD());
3837 break;
3838 }
3839 else return error(GL_INVALID_ENUM);
3840 case GL_TEXTURE_MIN_LOD:
3841 if(clientVersion >= 3)
3842 {
3843 *params = (GLint)roundf(texture->getMinLOD());
3844 break;
3845 }
3846 else return error(GL_INVALID_ENUM);
3847 case GL_TEXTURE_SWIZZLE_R:
3848 if(clientVersion >= 3)
3849 {
3850 *params = (GLint)texture->getSwizzleR();
3851 break;
3852 }
3853 else return error(GL_INVALID_ENUM);
3854 case GL_TEXTURE_SWIZZLE_G:
3855 if(clientVersion >= 3)
3856 {
3857 *params = (GLint)texture->getSwizzleG();
3858 break;
3859 }
3860 else return error(GL_INVALID_ENUM);
3861 case GL_TEXTURE_SWIZZLE_B:
3862 if(clientVersion >= 3)
3863 {
3864 *params = (GLint)texture->getSwizzleB();
3865 break;
3866 }
3867 else return error(GL_INVALID_ENUM);
3868 case GL_TEXTURE_SWIZZLE_A:
3869 if(clientVersion >= 3)
3870 {
3871 *params = (GLint)texture->getSwizzleA();
3872 break;
3873 }
3874 else return error(GL_INVALID_ENUM);
3875 default:
3876 return error(GL_INVALID_ENUM);
3877 }
3878 }
3879}
3880
3881void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3882{
3883 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3884 program, location, bufSize, params);
3885
3886 if(bufSize < 0)
3887 {
3888 return error(GL_INVALID_VALUE);
3889 }
3890
3891 es2::Context *context = es2::getContext();
3892
3893 if(context)
3894 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003895 es2::Program *programObject = context->getProgram(program);
3896
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003897 if(!programObject)
3898 {
3899 if(context->getShader(program))
3900 {
3901 return error(GL_INVALID_OPERATION);
3902 }
3903 else
3904 {
3905 return error(GL_INVALID_VALUE);
3906 }
3907 }
3908
3909 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003910 {
3911 return error(GL_INVALID_OPERATION);
3912 }
3913
3914 if(!programObject->getUniformfv(location, &bufSize, params))
3915 {
3916 return error(GL_INVALID_OPERATION);
3917 }
3918 }
3919}
3920
3921void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3922{
3923 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3924
3925 es2::Context *context = es2::getContext();
3926
3927 if(context)
3928 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003929 es2::Program *programObject = context->getProgram(program);
3930
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003931 if(!programObject)
3932 {
3933 if(context->getShader(program))
3934 {
3935 return error(GL_INVALID_OPERATION);
3936 }
3937 else
3938 {
3939 return error(GL_INVALID_VALUE);
3940 }
3941 }
3942
3943 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003944 {
3945 return error(GL_INVALID_OPERATION);
3946 }
3947
3948 if(!programObject->getUniformfv(location, nullptr, params))
3949 {
3950 return error(GL_INVALID_OPERATION);
3951 }
3952 }
3953}
3954
3955void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3956{
3957 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3958 program, location, bufSize, params);
3959
3960 if(bufSize < 0)
3961 {
3962 return error(GL_INVALID_VALUE);
3963 }
3964
3965 es2::Context *context = es2::getContext();
3966
3967 if(context)
3968 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003969 es2::Program *programObject = context->getProgram(program);
3970
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003971 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003972 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003973 if(context->getShader(program))
3974 {
3975 return error(GL_INVALID_OPERATION);
3976 }
3977 else
3978 {
3979 return error(GL_INVALID_VALUE);
3980 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003981 }
3982
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003983 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003984 {
3985 return error(GL_INVALID_OPERATION);
3986 }
3987
3988 if(!programObject->getUniformiv(location, &bufSize, params))
3989 {
3990 return error(GL_INVALID_OPERATION);
3991 }
3992 }
3993}
3994
3995void GetUniformiv(GLuint program, GLint location, GLint* params)
3996{
3997 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3998
3999 es2::Context *context = es2::getContext();
4000
4001 if(context)
4002 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004003 es2::Program *programObject = context->getProgram(program);
4004
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004005 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004006 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004007 if(context->getShader(program))
4008 {
4009 return error(GL_INVALID_OPERATION);
4010 }
4011 else
4012 {
4013 return error(GL_INVALID_VALUE);
4014 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004015 }
4016
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04004017 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04004018 {
4019 return error(GL_INVALID_OPERATION);
4020 }
4021
4022 if(!programObject->getUniformiv(location, nullptr, params))
4023 {
4024 return error(GL_INVALID_OPERATION);
4025 }
4026 }
4027}
4028
4029int GetUniformLocation(GLuint program, const GLchar* name)
4030{
4031 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
4032
4033 es2::Context *context = es2::getContext();
4034
4035 if(strstr(name, "gl_") == name)
4036 {
4037 return -1;
4038 }
4039
4040 if(context)
4041 {
4042 es2::Program *programObject = context->getProgram(program);
4043
4044 if(!programObject)
4045 {
4046 if(context->getShader(program))
4047 {
4048 return error(GL_INVALID_OPERATION, -1);
4049 }
4050 else
4051 {
4052 return error(GL_INVALID_VALUE, -1);
4053 }
4054 }
4055
4056 if(!programObject->isLinked())
4057 {
4058 return error(GL_INVALID_OPERATION, -1);
4059 }
4060
4061 return programObject->getUniformLocation(name);
4062 }
4063
4064 return -1;
4065}
4066
4067void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
4068{
4069 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
4070
4071 es2::Context *context = es2::getContext();
4072
4073 if(context)
4074 {
4075 if(index >= es2::MAX_VERTEX_ATTRIBS)
4076 {
4077 return error(GL_INVALID_VALUE);
4078 }
4079
4080 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4081
4082 GLint clientVersion = context->getClientVersion();
4083
4084 switch(pname)
4085 {
4086 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4087 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4088 break;
4089 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4090 *params = (GLfloat)attribState.mSize;
4091 break;
4092 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4093 *params = (GLfloat)attribState.mStride;
4094 break;
4095 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4096 *params = (GLfloat)attribState.mType;
4097 break;
4098 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4099 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
4100 break;
4101 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4102 *params = (GLfloat)attribState.mBoundBuffer.name();
4103 break;
4104 case GL_CURRENT_VERTEX_ATTRIB:
4105 {
4106 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4107 for(int i = 0; i < 4; ++i)
4108 {
4109 params[i] = attrib.getCurrentValueF(i);
4110 }
4111 }
4112 break;
4113 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4114 if(clientVersion >= 3)
4115 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004116 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004117 break;
4118 }
4119 else return error(GL_INVALID_ENUM);
4120 default: return error(GL_INVALID_ENUM);
4121 }
4122 }
4123}
4124
4125void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
4126{
4127 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
4128
4129 es2::Context *context = es2::getContext();
4130
4131 if(context)
4132 {
4133 if(index >= es2::MAX_VERTEX_ATTRIBS)
4134 {
4135 return error(GL_INVALID_VALUE);
4136 }
4137
4138 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
4139
4140 GLint clientVersion = context->getClientVersion();
4141
4142 switch(pname)
4143 {
4144 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4145 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
4146 break;
4147 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4148 *params = attribState.mSize;
4149 break;
4150 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4151 *params = attribState.mStride;
4152 break;
4153 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4154 *params = attribState.mType;
4155 break;
4156 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4157 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
4158 break;
4159 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4160 *params = attribState.mBoundBuffer.name();
4161 break;
4162 case GL_CURRENT_VERTEX_ATTRIB:
4163 {
4164 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
4165 for(int i = 0; i < 4; ++i)
4166 {
4167 float currentValue = attrib.getCurrentValueF(i);
4168 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
4169 }
4170 }
4171 break;
4172 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
4173 if(clientVersion >= 3)
4174 {
Alexis Hetu6f284032017-12-11 15:19:36 -05004175 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004176 break;
4177 }
4178 else return error(GL_INVALID_ENUM);
4179 default: return error(GL_INVALID_ENUM);
4180 }
4181 }
4182}
4183
4184void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
4185{
4186 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
4187
4188 es2::Context *context = es2::getContext();
4189
4190 if(context)
4191 {
4192 if(index >= es2::MAX_VERTEX_ATTRIBS)
4193 {
4194 return error(GL_INVALID_VALUE);
4195 }
4196
4197 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4198 {
4199 return error(GL_INVALID_ENUM);
4200 }
4201
4202 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
4203 }
4204}
4205
4206void Hint(GLenum target, GLenum mode)
4207{
4208 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
4209
4210 switch(mode)
4211 {
4212 case GL_FASTEST:
4213 case GL_NICEST:
4214 case GL_DONT_CARE:
4215 break;
4216 default:
4217 return error(GL_INVALID_ENUM);
4218 }
4219
4220 es2::Context *context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004221
4222 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004223 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05004224 switch(target)
4225 {
4226 case GL_GENERATE_MIPMAP_HINT:
4227 context->setGenerateMipmapHint(mode);
4228 break;
4229 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4230 context->setFragmentShaderDerivativeHint(mode);
4231 break;
4232 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
4233 context->setTextureFilteringHint(mode);
4234 break;
4235 default:
4236 return error(GL_INVALID_ENUM);
4237 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04004238 }
4239}
4240
4241GLboolean IsBuffer(GLuint buffer)
4242{
4243 TRACE("(GLuint buffer = %d)", buffer);
4244
4245 es2::Context *context = es2::getContext();
4246
4247 if(context && buffer)
4248 {
4249 es2::Buffer *bufferObject = context->getBuffer(buffer);
4250
4251 if(bufferObject)
4252 {
4253 return GL_TRUE;
4254 }
4255 }
4256
4257 return GL_FALSE;
4258}
4259
4260GLboolean IsEnabled(GLenum cap)
4261{
4262 TRACE("(GLenum cap = 0x%X)", cap);
4263
4264 es2::Context *context = es2::getContext();
4265
4266 if(context)
4267 {
4268 GLint clientVersion = context->getClientVersion();
4269
4270 switch(cap)
4271 {
4272 case GL_CULL_FACE: return context->isCullFaceEnabled();
4273 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
4274 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
4275 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
4276 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
4277 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
4278 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
4279 case GL_BLEND: return context->isBlendEnabled();
4280 case GL_DITHER: return context->isDitherEnabled();
4281 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
4282 if(clientVersion >= 3)
4283 {
4284 return context->isPrimitiveRestartFixedIndexEnabled();
4285 }
4286 else return error(GL_INVALID_ENUM, false);
4287 case GL_RASTERIZER_DISCARD:
4288 if(clientVersion >= 3)
4289 {
4290 return context->isRasterizerDiscardEnabled();
4291 }
4292 else return error(GL_INVALID_ENUM, false);
4293 default:
4294 return error(GL_INVALID_ENUM, false);
4295 }
4296 }
4297
4298 return false;
4299}
4300
4301GLboolean IsFenceNV(GLuint fence)
4302{
4303 TRACE("(GLuint fence = %d)", fence);
4304
4305 es2::Context *context = es2::getContext();
4306
4307 if(context)
4308 {
4309 es2::Fence *fenceObject = context->getFence(fence);
4310
4311 if(!fenceObject)
4312 {
4313 return GL_FALSE;
4314 }
4315
4316 return fenceObject->isFence();
4317 }
4318
4319 return GL_FALSE;
4320}
4321
4322GLboolean IsFramebuffer(GLuint framebuffer)
4323{
4324 TRACE("(GLuint framebuffer = %d)", framebuffer);
4325
4326 es2::Context *context = es2::getContext();
4327
4328 if(context && framebuffer)
4329 {
4330 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
4331
4332 if(framebufferObject)
4333 {
4334 return GL_TRUE;
4335 }
4336 }
4337
4338 return GL_FALSE;
4339}
4340
4341GLboolean IsProgram(GLuint program)
4342{
4343 TRACE("(GLuint program = %d)", program);
4344
4345 es2::Context *context = es2::getContext();
4346
4347 if(context && program)
4348 {
4349 es2::Program *programObject = context->getProgram(program);
4350
4351 if(programObject)
4352 {
4353 return GL_TRUE;
4354 }
4355 }
4356
4357 return GL_FALSE;
4358}
4359
4360GLboolean IsQueryEXT(GLuint name)
4361{
4362 TRACE("(GLuint name = %d)", name);
4363
4364 if(name == 0)
4365 {
4366 return GL_FALSE;
4367 }
4368
4369 es2::Context *context = es2::getContext();
4370
4371 if(context)
4372 {
4373 es2::Query *queryObject = context->getQuery(name);
4374
4375 if(queryObject)
4376 {
4377 return GL_TRUE;
4378 }
4379 }
4380
4381 return GL_FALSE;
4382}
4383
4384GLboolean IsRenderbuffer(GLuint renderbuffer)
4385{
4386 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4387
4388 es2::Context *context = es2::getContext();
4389
4390 if(context && renderbuffer)
4391 {
4392 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
4393
4394 if(renderbufferObject)
4395 {
4396 return GL_TRUE;
4397 }
4398 }
4399
4400 return GL_FALSE;
4401}
4402
4403GLboolean IsShader(GLuint shader)
4404{
4405 TRACE("(GLuint shader = %d)", shader);
4406
4407 es2::Context *context = es2::getContext();
4408
4409 if(context && shader)
4410 {
4411 es2::Shader *shaderObject = context->getShader(shader);
4412
4413 if(shaderObject)
4414 {
4415 return GL_TRUE;
4416 }
4417 }
4418
4419 return GL_FALSE;
4420}
4421
4422GLboolean IsTexture(GLuint texture)
4423{
4424 TRACE("(GLuint texture = %d)", texture);
4425
4426 es2::Context *context = es2::getContext();
4427
4428 if(context && texture)
4429 {
4430 es2::Texture *textureObject = context->getTexture(texture);
4431
4432 if(textureObject)
4433 {
4434 return GL_TRUE;
4435 }
4436 }
4437
4438 return GL_FALSE;
4439}
4440
4441void LineWidth(GLfloat width)
4442{
4443 TRACE("(GLfloat width = %f)", width);
4444
4445 if(width <= 0.0f)
4446 {
4447 return error(GL_INVALID_VALUE);
4448 }
4449
4450 es2::Context *context = es2::getContext();
4451
4452 if(context)
4453 {
4454 context->setLineWidth(width);
4455 }
4456}
4457
4458void LinkProgram(GLuint program)
4459{
4460 TRACE("(GLuint program = %d)", program);
4461
4462 es2::Context *context = es2::getContext();
4463
4464 if(context)
4465 {
4466 es2::Program *programObject = context->getProgram(program);
4467
4468 if(!programObject)
4469 {
4470 if(context->getShader(program))
4471 {
4472 return error(GL_INVALID_OPERATION);
4473 }
4474 else
4475 {
4476 return error(GL_INVALID_VALUE);
4477 }
4478 }
4479
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004480 if(programObject == context->getCurrentProgram())
4481 {
4482 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4483 if(transformFeedback && transformFeedback->isActive())
4484 {
4485 return error(GL_INVALID_OPERATION);
4486 }
4487 }
4488
Nicolas Capens0bac2852016-05-07 06:09:58 -04004489 programObject->link();
4490 }
4491}
4492
4493void PixelStorei(GLenum pname, GLint param)
4494{
4495 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4496
4497 es2::Context *context = es2::getContext();
4498
4499 if(context)
4500 {
4501 GLint clientVersion = context->getClientVersion();
4502
4503 switch(pname)
4504 {
4505 case GL_UNPACK_ALIGNMENT:
4506 if(param != 1 && param != 2 && param != 4 && param != 8)
4507 {
4508 return error(GL_INVALID_VALUE);
4509 }
4510 context->setUnpackAlignment(param);
4511 break;
4512 case GL_PACK_ALIGNMENT:
4513 if(param != 1 && param != 2 && param != 4 && param != 8)
4514 {
4515 return error(GL_INVALID_VALUE);
4516 }
4517 context->setPackAlignment(param);
4518 break;
4519 case GL_PACK_ROW_LENGTH:
4520 if(clientVersion >= 3)
4521 {
4522 if(param < 0)
4523 {
4524 return error(GL_INVALID_VALUE);
4525 }
4526 context->setPackRowLength(param);
4527 break;
4528 }
4529 else return error(GL_INVALID_ENUM);
4530 case GL_PACK_SKIP_PIXELS:
4531 if(clientVersion >= 3)
4532 {
4533 if(param < 0)
4534 {
4535 return error(GL_INVALID_VALUE);
4536 }
4537 context->setPackSkipPixels(param);
4538 break;
4539 }
4540 else return error(GL_INVALID_ENUM);
4541 case GL_PACK_SKIP_ROWS:
4542 if(clientVersion >= 3)
4543 {
4544 if(param < 0)
4545 {
4546 return error(GL_INVALID_VALUE);
4547 }
4548 context->setPackSkipRows(param);
4549 break;
4550 }
4551 else return error(GL_INVALID_ENUM);
4552 case GL_UNPACK_ROW_LENGTH:
4553 if(clientVersion >= 3)
4554 {
4555 if(param < 0)
4556 {
4557 return error(GL_INVALID_VALUE);
4558 }
4559 context->setUnpackRowLength(param);
4560 break;
4561 }
4562 else return error(GL_INVALID_ENUM);
4563 case GL_UNPACK_IMAGE_HEIGHT:
4564 if(clientVersion >= 3)
4565 {
4566 if(param < 0)
4567 {
4568 return error(GL_INVALID_VALUE);
4569 }
4570 context->setUnpackImageHeight(param);
4571 break;
4572 }
4573 else return error(GL_INVALID_ENUM);
4574 case GL_UNPACK_SKIP_PIXELS:
4575 if(clientVersion >= 3)
4576 {
4577 if(param < 0)
4578 {
4579 return error(GL_INVALID_VALUE);
4580 }
4581 context->setUnpackSkipPixels(param);
4582 break;
4583 }
4584 else return error(GL_INVALID_ENUM);
4585 case GL_UNPACK_SKIP_ROWS:
4586 if(clientVersion >= 3)
4587 {
4588 if(param < 0)
4589 {
4590 return error(GL_INVALID_VALUE);
4591 }
4592 context->setUnpackSkipRows(param);
4593 break;
4594 }
4595 else return error(GL_INVALID_ENUM);
4596 case GL_UNPACK_SKIP_IMAGES:
4597 if(clientVersion >= 3) {
4598 if(param < 0)
4599 {
4600 return error(GL_INVALID_VALUE);
4601 }
4602 context->setUnpackSkipImages(param);
4603 break;
4604 }
4605 else return error(GL_INVALID_ENUM);
4606 default:
4607 return error(GL_INVALID_ENUM);
4608 }
4609 }
4610}
4611
4612void PolygonOffset(GLfloat factor, GLfloat units)
4613{
4614 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4615
4616 es2::Context *context = es2::getContext();
4617
4618 if(context)
4619 {
4620 context->setPolygonOffsetParams(factor, units);
4621 }
4622}
4623
4624void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4625 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4626{
4627 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4628 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4629 x, y, width, height, format, type, bufSize, data);
4630
4631 if(width < 0 || height < 0 || bufSize < 0)
4632 {
4633 return error(GL_INVALID_VALUE);
4634 }
4635
4636 es2::Context *context = es2::getContext();
4637
4638 if(context)
4639 {
4640 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4641 }
4642}
4643
4644void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4645{
4646 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4647 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4648 x, y, width, height, format, type, pixels);
4649
4650 if(width < 0 || height < 0)
4651 {
4652 return error(GL_INVALID_VALUE);
4653 }
4654
4655 es2::Context *context = es2::getContext();
4656
4657 if(context)
4658 {
4659 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4660 }
4661}
4662
4663void ReleaseShaderCompiler(void)
4664{
4665 TRACE("()");
4666
4667 es2::Shader::releaseCompiler();
4668}
4669
Nicolas Capens400667e2017-03-29 14:40:14 -04004670void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004671{
4672 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4673 target, samples, internalformat, width, height);
4674
4675 switch(target)
4676 {
4677 case GL_RENDERBUFFER:
4678 break;
4679 default:
4680 return error(GL_INVALID_ENUM);
4681 }
4682
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004683 if(width < 0 || height < 0 || samples < 0 ||
4684 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4685 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004686 {
4687 return error(GL_INVALID_VALUE);
4688 }
4689
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004690 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004691 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004692 {
4693 return error(GL_INVALID_OPERATION);
4694 }
4695
Nicolas Capens0bac2852016-05-07 06:09:58 -04004696 es2::Context *context = es2::getContext();
4697
4698 if(context)
4699 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004700 GLuint handle = context->getRenderbufferName();
4701 if(handle == 0)
4702 {
4703 return error(GL_INVALID_OPERATION);
4704 }
4705
4706 GLint clientVersion = context->getClientVersion();
Nicolas Capens400667e2017-03-29 14:40:14 -04004707
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004708 if(IsColorRenderable(internalformat, clientVersion))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004709 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004710 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004711 }
Nicolas Capens400667e2017-03-29 14:40:14 -04004712 else if(IsDepthRenderable(internalformat, clientVersion) && IsStencilRenderable(internalformat, clientVersion))
4713 {
4714 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4715 }
4716 else if(IsDepthRenderable(internalformat, clientVersion))
4717 {
4718 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4719 }
4720 else if(IsStencilRenderable(internalformat, clientVersion))
4721 {
4722 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4723 }
4724 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004725 }
4726}
4727
Nicolas Capens400667e2017-03-29 14:40:14 -04004728void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4729{
4730 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4731}
4732
Nicolas Capens0bac2852016-05-07 06:09:58 -04004733void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4734{
Nicolas Capens400667e2017-03-29 14:40:14 -04004735 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004736}
4737
4738void SampleCoverage(GLclampf value, GLboolean invert)
4739{
4740 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4741
4742 es2::Context* context = es2::getContext();
4743
4744 if(context)
4745 {
4746 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4747 }
4748}
4749
4750void SetFenceNV(GLuint fence, GLenum condition)
4751{
4752 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4753
4754 if(condition != GL_ALL_COMPLETED_NV)
4755 {
4756 return error(GL_INVALID_ENUM);
4757 }
4758
4759 es2::Context *context = es2::getContext();
4760
4761 if(context)
4762 {
4763 es2::Fence *fenceObject = context->getFence(fence);
4764
4765 if(!fenceObject)
4766 {
4767 return error(GL_INVALID_OPERATION);
4768 }
4769
4770 fenceObject->setFence(condition);
4771 }
4772}
4773
4774void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4775{
4776 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4777
4778 if(width < 0 || height < 0)
4779 {
4780 return error(GL_INVALID_VALUE);
4781 }
4782
4783 es2::Context* context = es2::getContext();
4784
4785 if(context)
4786 {
4787 context->setScissorParams(x, y, width, height);
4788 }
4789}
4790
4791void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4792{
4793 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4794 "const GLvoid* binary = %p, GLsizei length = %d)",
4795 n, shaders, binaryformat, binary, length);
4796
4797 // No binary shader formats are supported.
4798 return error(GL_INVALID_ENUM);
4799}
4800
4801void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4802{
4803 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4804 shader, count, string, length);
4805
4806 if(count < 0)
4807 {
4808 return error(GL_INVALID_VALUE);
4809 }
4810
4811 es2::Context *context = es2::getContext();
4812
4813 if(context)
4814 {
4815 es2::Shader *shaderObject = context->getShader(shader);
4816
4817 if(!shaderObject)
4818 {
4819 if(context->getProgram(shader))
4820 {
4821 return error(GL_INVALID_OPERATION);
4822 }
4823 else
4824 {
4825 return error(GL_INVALID_VALUE);
4826 }
4827 }
4828
4829 shaderObject->setSource(count, string, length);
4830 }
4831}
4832
4833void StencilFunc(GLenum func, GLint ref, GLuint mask)
4834{
4835 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4836}
4837
4838void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4839{
4840 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4841
4842 switch(face)
4843 {
4844 case GL_FRONT:
4845 case GL_BACK:
4846 case GL_FRONT_AND_BACK:
4847 break;
4848 default:
4849 return error(GL_INVALID_ENUM);
4850 }
4851
4852 switch(func)
4853 {
4854 case GL_NEVER:
4855 case GL_ALWAYS:
4856 case GL_LESS:
4857 case GL_LEQUAL:
4858 case GL_EQUAL:
4859 case GL_GEQUAL:
4860 case GL_GREATER:
4861 case GL_NOTEQUAL:
4862 break;
4863 default:
4864 return error(GL_INVALID_ENUM);
4865 }
4866
4867 es2::Context *context = es2::getContext();
4868
4869 if(context)
4870 {
4871 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4872 {
4873 context->setStencilParams(func, ref, mask);
4874 }
4875
4876 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4877 {
4878 context->setStencilBackParams(func, ref, mask);
4879 }
4880 }
4881}
4882
4883void StencilMask(GLuint mask)
4884{
4885 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4886}
4887
4888void StencilMaskSeparate(GLenum face, GLuint mask)
4889{
4890 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4891
4892 switch(face)
4893 {
4894 case GL_FRONT:
4895 case GL_BACK:
4896 case GL_FRONT_AND_BACK:
4897 break;
4898 default:
4899 return error(GL_INVALID_ENUM);
4900 }
4901
4902 es2::Context *context = es2::getContext();
4903
4904 if(context)
4905 {
4906 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4907 {
4908 context->setStencilWritemask(mask);
4909 }
4910
4911 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4912 {
4913 context->setStencilBackWritemask(mask);
4914 }
4915 }
4916}
4917
4918void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4919{
4920 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4921}
4922
4923void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4924{
4925 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4926 face, fail, zfail, zpass);
4927
4928 switch(face)
4929 {
4930 case GL_FRONT:
4931 case GL_BACK:
4932 case GL_FRONT_AND_BACK:
4933 break;
4934 default:
4935 return error(GL_INVALID_ENUM);
4936 }
4937
4938 switch(fail)
4939 {
4940 case GL_ZERO:
4941 case GL_KEEP:
4942 case GL_REPLACE:
4943 case GL_INCR:
4944 case GL_DECR:
4945 case GL_INVERT:
4946 case GL_INCR_WRAP:
4947 case GL_DECR_WRAP:
4948 break;
4949 default:
4950 return error(GL_INVALID_ENUM);
4951 }
4952
4953 switch(zfail)
4954 {
4955 case GL_ZERO:
4956 case GL_KEEP:
4957 case GL_REPLACE:
4958 case GL_INCR:
4959 case GL_DECR:
4960 case GL_INVERT:
4961 case GL_INCR_WRAP:
4962 case GL_DECR_WRAP:
4963 break;
4964 default:
4965 return error(GL_INVALID_ENUM);
4966 }
4967
4968 switch(zpass)
4969 {
4970 case GL_ZERO:
4971 case GL_KEEP:
4972 case GL_REPLACE:
4973 case GL_INCR:
4974 case GL_DECR:
4975 case GL_INVERT:
4976 case GL_INCR_WRAP:
4977 case GL_DECR_WRAP:
4978 break;
4979 default:
4980 return error(GL_INVALID_ENUM);
4981 }
4982
4983 es2::Context *context = es2::getContext();
4984
4985 if(context)
4986 {
4987 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4988 {
4989 context->setStencilOperations(fail, zfail, zpass);
4990 }
4991
4992 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4993 {
4994 context->setStencilBackOperations(fail, zfail, zpass);
4995 }
4996 }
4997}
4998
4999GLboolean TestFenceNV(GLuint fence)
5000{
5001 TRACE("(GLuint fence = %d)", fence);
5002
5003 es2::Context *context = es2::getContext();
5004
5005 if(context)
5006 {
5007 es2::Fence *fenceObject = context->getFence(fence);
5008
5009 if(!fenceObject)
5010 {
5011 return error(GL_INVALID_OPERATION, GL_TRUE);
5012 }
5013
5014 return fenceObject->testFence();
5015 }
5016
5017 return GL_TRUE;
5018}
5019
5020void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005021 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005022{
5023 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005024 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
5025 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005026
5027 if(!validImageSize(level, width, height))
5028 {
5029 return error(GL_INVALID_VALUE);
5030 }
5031
5032 es2::Context *context = es2::getContext();
5033
5034 if(context)
5035 {
5036 GLint clientVersion = context->getClientVersion();
5037 if(clientVersion < 3)
5038 {
5039 if(internalformat != (GLint)format)
5040 {
5041 return error(GL_INVALID_OPERATION);
5042 }
5043 }
5044
5045 GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
5046 if(validationError != GL_NONE)
5047 {
5048 return error(validationError);
5049 }
5050
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005051 validationError = ValidateTextureFormatType(format, type, internalformat, context->getClientVersion());
5052 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005053 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005054 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005055 }
5056
5057 if(border != 0)
5058 {
5059 return error(GL_INVALID_VALUE);
5060 }
5061
5062 switch(target)
5063 {
5064 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05005065 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005066 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5067 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
5068 {
5069 return error(GL_INVALID_VALUE);
5070 }
5071 break;
5072 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5073 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5074 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5075 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5076 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5077 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
5078 if(width != height)
5079 {
5080 return error(GL_INVALID_VALUE);
5081 }
5082
5083 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5084 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5085 {
5086 return error(GL_INVALID_VALUE);
5087 }
5088 break;
5089 default:
5090 return error(GL_INVALID_ENUM);
5091 }
5092
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005093 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005094
Nicolas Capens5555af42017-12-14 13:14:03 -05005095 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005096 if(validationError != GL_NONE)
5097 {
5098 return error(validationError);
5099 }
5100
Alexis Hetu46768622018-01-16 22:09:28 -05005101 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005102 {
Alexis Hetu46768622018-01-16 22:09:28 -05005103 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005104
5105 if(!texture)
5106 {
5107 return error(GL_INVALID_OPERATION);
5108 }
5109
Nicolas Capens648b5822018-01-18 00:04:26 -05005110 texture->setImage(context, level, width, height, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005111 }
5112 else
5113 {
5114 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5115
5116 if(!texture)
5117 {
5118 return error(GL_INVALID_OPERATION);
5119 }
5120
Nicolas Capens648b5822018-01-18 00:04:26 -05005121 texture->setImage(context, target, level, width, height, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005122 }
5123 }
5124}
5125
5126void TexParameterf(GLenum target, GLenum pname, GLfloat param)
5127{
5128 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
5129
5130 es2::Context *context = es2::getContext();
5131
5132 if(context)
5133 {
5134 es2::Texture *texture;
5135
5136 GLint clientVersion = context->getClientVersion();
5137
5138 switch(target)
5139 {
5140 case GL_TEXTURE_2D:
5141 texture = context->getTexture2D();
5142 break;
5143 case GL_TEXTURE_2D_ARRAY:
5144 if(clientVersion < 3)
5145 {
5146 return error(GL_INVALID_ENUM);
5147 }
5148 else
5149 {
5150 texture = context->getTexture2DArray();
5151 }
5152 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005153 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005154 texture = context->getTexture3D();
5155 break;
5156 case GL_TEXTURE_CUBE_MAP:
5157 texture = context->getTextureCubeMap();
5158 break;
5159 case GL_TEXTURE_EXTERNAL_OES:
5160 texture = context->getTextureExternal();
5161 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005162 case GL_TEXTURE_RECTANGLE_ARB:
5163 texture = context->getTexture2DRect();
5164 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005165 default:
5166 return error(GL_INVALID_ENUM);
5167 }
5168
5169 switch(pname)
5170 {
5171 case GL_TEXTURE_WRAP_S:
5172 if(!texture->setWrapS((GLenum)param))
5173 {
5174 return error(GL_INVALID_ENUM);
5175 }
5176 break;
5177 case GL_TEXTURE_WRAP_T:
5178 if(!texture->setWrapT((GLenum)param))
5179 {
5180 return error(GL_INVALID_ENUM);
5181 }
5182 break;
5183 case GL_TEXTURE_WRAP_R_OES:
5184 if(!texture->setWrapR((GLenum)param))
5185 {
5186 return error(GL_INVALID_ENUM);
5187 }
5188 break;
5189 case GL_TEXTURE_MIN_FILTER:
5190 if(!texture->setMinFilter((GLenum)param))
5191 {
5192 return error(GL_INVALID_ENUM);
5193 }
5194 break;
5195 case GL_TEXTURE_MAG_FILTER:
5196 if(!texture->setMagFilter((GLenum)param))
5197 {
5198 return error(GL_INVALID_ENUM);
5199 }
5200 break;
5201 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5202 if(!texture->setMaxAnisotropy(param))
5203 {
5204 return error(GL_INVALID_VALUE);
5205 }
5206 break;
5207 case GL_TEXTURE_BASE_LEVEL:
5208 if(clientVersion < 3 || !texture->setBaseLevel((GLint)(roundf(param))))
5209 {
5210 return error(GL_INVALID_VALUE);
5211 }
5212 break;
5213 case GL_TEXTURE_COMPARE_FUNC:
5214 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5215 {
5216 return error(GL_INVALID_VALUE);
5217 }
5218 break;
5219 case GL_TEXTURE_COMPARE_MODE:
5220 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5221 {
5222 return error(GL_INVALID_VALUE);
5223 }
5224 break;
5225 case GL_TEXTURE_MAX_LEVEL:
5226 if(clientVersion < 3 || !texture->setMaxLevel((GLint)(roundf(param))))
5227 {
5228 return error(GL_INVALID_VALUE);
5229 }
5230 break;
5231 case GL_TEXTURE_MAX_LOD:
5232 if(clientVersion < 3 || !texture->setMaxLOD(param))
5233 {
5234 return error(GL_INVALID_VALUE);
5235 }
5236 break;
5237 case GL_TEXTURE_MIN_LOD:
5238 if(clientVersion < 3 || !texture->setMinLOD(param))
5239 {
5240 return error(GL_INVALID_VALUE);
5241 }
5242 break;
5243 case GL_TEXTURE_SWIZZLE_R:
5244 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5245 {
5246 return error(GL_INVALID_VALUE);
5247 }
5248 break;
5249 case GL_TEXTURE_SWIZZLE_G:
5250 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5251 {
5252 return error(GL_INVALID_VALUE);
5253 }
5254 break;
5255 case GL_TEXTURE_SWIZZLE_B:
5256 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5257 {
5258 return error(GL_INVALID_VALUE);
5259 }
5260 break;
5261 case GL_TEXTURE_SWIZZLE_A:
5262 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5263 {
5264 return error(GL_INVALID_VALUE);
5265 }
5266 break;
5267 default:
5268 return error(GL_INVALID_ENUM);
5269 }
5270 }
5271}
5272
5273void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5274{
5275 glTexParameterf(target, pname, *params);
5276}
5277
5278void TexParameteri(GLenum target, GLenum pname, GLint param)
5279{
5280 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5281
5282 es2::Context *context = es2::getContext();
5283
5284 if(context)
5285 {
5286 es2::Texture *texture;
5287
5288 GLint clientVersion = context->getClientVersion();
5289
5290 switch(target)
5291 {
5292 case GL_TEXTURE_2D:
5293 texture = context->getTexture2D();
5294 break;
5295 case GL_TEXTURE_2D_ARRAY:
5296 if(clientVersion < 3)
5297 {
5298 return error(GL_INVALID_ENUM);
5299 }
5300 else
5301 {
5302 texture = context->getTexture2DArray();
5303 }
5304 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005305 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005306 texture = context->getTexture3D();
5307 break;
5308 case GL_TEXTURE_CUBE_MAP:
5309 texture = context->getTextureCubeMap();
5310 break;
5311 case GL_TEXTURE_EXTERNAL_OES:
5312 texture = context->getTextureExternal();
5313 break;
Alexis Hetu46768622018-01-16 22:09:28 -05005314 case GL_TEXTURE_RECTANGLE_ARB:
5315 texture = context->getTexture2DRect();
5316 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005317 default:
5318 return error(GL_INVALID_ENUM);
5319 }
5320
5321 switch(pname)
5322 {
5323 case GL_TEXTURE_WRAP_S:
5324 if(!texture->setWrapS((GLenum)param))
5325 {
5326 return error(GL_INVALID_ENUM);
5327 }
5328 break;
5329 case GL_TEXTURE_WRAP_T:
5330 if(!texture->setWrapT((GLenum)param))
5331 {
5332 return error(GL_INVALID_ENUM);
5333 }
5334 break;
5335 case GL_TEXTURE_WRAP_R_OES:
5336 if(!texture->setWrapR((GLenum)param))
5337 {
5338 return error(GL_INVALID_ENUM);
5339 }
5340 break;
5341 case GL_TEXTURE_MIN_FILTER:
5342 if(!texture->setMinFilter((GLenum)param))
5343 {
5344 return error(GL_INVALID_ENUM);
5345 }
5346 break;
5347 case GL_TEXTURE_MAG_FILTER:
5348 if(!texture->setMagFilter((GLenum)param))
5349 {
5350 return error(GL_INVALID_ENUM);
5351 }
5352 break;
5353 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5354 if(!texture->setMaxAnisotropy((GLfloat)param))
5355 {
5356 return error(GL_INVALID_VALUE);
5357 }
5358 break;
5359 case GL_TEXTURE_BASE_LEVEL:
5360 if(clientVersion < 3 || !texture->setBaseLevel(param))
5361 {
5362 return error(GL_INVALID_VALUE);
5363 }
5364 break;
5365 case GL_TEXTURE_COMPARE_FUNC:
5366 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5367 {
5368 return error(GL_INVALID_VALUE);
5369 }
5370 break;
5371 case GL_TEXTURE_COMPARE_MODE:
5372 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5373 {
5374 return error(GL_INVALID_VALUE);
5375 }
5376 break;
5377 case GL_TEXTURE_MAX_LEVEL:
5378 if(clientVersion < 3 || !texture->setMaxLevel(param))
5379 {
5380 return error(GL_INVALID_VALUE);
5381 }
5382 break;
5383 case GL_TEXTURE_MAX_LOD:
5384 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5385 {
5386 return error(GL_INVALID_VALUE);
5387 }
5388 break;
5389 case GL_TEXTURE_MIN_LOD:
5390 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5391 {
5392 return error(GL_INVALID_VALUE);
5393 }
5394 break;
5395 case GL_TEXTURE_SWIZZLE_R:
5396 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5397 {
5398 return error(GL_INVALID_VALUE);
5399 }
5400 break;
5401 case GL_TEXTURE_SWIZZLE_G:
5402 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5403 {
5404 return error(GL_INVALID_VALUE);
5405 }
5406 break;
5407 case GL_TEXTURE_SWIZZLE_B:
5408 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5409 {
5410 return error(GL_INVALID_VALUE);
5411 }
5412 break;
5413 case GL_TEXTURE_SWIZZLE_A:
5414 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5415 {
5416 return error(GL_INVALID_VALUE);
5417 }
5418 break;
5419 default:
5420 return error(GL_INVALID_ENUM);
5421 }
5422 }
5423}
5424
5425void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
5426{
5427 glTexParameteri(target, pname, *params);
5428}
5429
5430void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04005431 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005432{
5433 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5434 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005435 "const GLvoid* data = %p)",
5436 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005437
5438 if(!es2::IsTextureTarget(target))
5439 {
5440 return error(GL_INVALID_ENUM);
5441 }
5442
5443 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5444 {
5445 return error(GL_INVALID_VALUE);
5446 }
5447
5448 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5449 {
5450 return error(GL_INVALID_VALUE);
5451 }
5452
5453 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5454 {
5455 return error(GL_INVALID_VALUE);
5456 }
5457
Nicolas Capens0bac2852016-05-07 06:09:58 -04005458 es2::Context *context = es2::getContext();
5459
5460 if(context)
5461 {
Alexis Hetu46768622018-01-16 22:09:28 -05005462 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005463 {
Alexis Hetu46768622018-01-16 22:09:28 -05005464 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005465
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005466 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5467 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005468 {
5469 return error(validationError);
5470 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005471
Nicolas Capens5555af42017-12-14 13:14:03 -05005472 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005473 if(validationError != GL_NONE)
5474 {
5475 return error(validationError);
5476 }
5477
Nicolas Capens5555af42017-12-14 13:14:03 -05005478 texture->subImage(context, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005479 }
5480 else if(es2::IsCubemapTextureTarget(target))
5481 {
5482 es2::TextureCubeMap *texture = context->getTextureCubeMap();
5483
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005484 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
5485 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005486 {
5487 return error(validationError);
5488 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005489
Nicolas Capens5555af42017-12-14 13:14:03 -05005490 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005491 if(validationError != GL_NONE)
5492 {
5493 return error(validationError);
5494 }
5495
Nicolas Capens5555af42017-12-14 13:14:03 -05005496 texture->subImage(context, target, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005497 }
5498 else UNREACHABLE(target);
5499 }
5500}
5501
5502void Uniform1f(GLint location, GLfloat x)
5503{
5504 glUniform1fv(location, 1, &x);
5505}
5506
5507void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
5508{
5509 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5510
5511 if(count < 0)
5512 {
5513 return error(GL_INVALID_VALUE);
5514 }
5515
Nicolas Capens0bac2852016-05-07 06:09:58 -04005516 es2::Context *context = es2::getContext();
5517
5518 if(context)
5519 {
5520 es2::Program *program = context->getCurrentProgram();
5521
5522 if(!program)
5523 {
5524 return error(GL_INVALID_OPERATION);
5525 }
5526
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005527 if(location == -1)
5528 {
5529 return;
5530 }
5531
Nicolas Capens0bac2852016-05-07 06:09:58 -04005532 if(!program->setUniform1fv(location, count, v))
5533 {
5534 return error(GL_INVALID_OPERATION);
5535 }
5536 }
5537}
5538
5539void Uniform1i(GLint location, GLint x)
5540{
5541 glUniform1iv(location, 1, &x);
5542}
5543
5544void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5545{
5546 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5547
5548 if(count < 0)
5549 {
5550 return error(GL_INVALID_VALUE);
5551 }
5552
Nicolas Capens0bac2852016-05-07 06:09:58 -04005553 es2::Context *context = es2::getContext();
5554
5555 if(context)
5556 {
5557 es2::Program *program = context->getCurrentProgram();
5558
5559 if(!program)
5560 {
5561 return error(GL_INVALID_OPERATION);
5562 }
5563
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005564 if(location == -1)
5565 {
5566 return;
5567 }
5568
Nicolas Capens0bac2852016-05-07 06:09:58 -04005569 if(!program->setUniform1iv(location, count, v))
5570 {
5571 return error(GL_INVALID_OPERATION);
5572 }
5573 }
5574}
5575
5576void Uniform2f(GLint location, GLfloat x, GLfloat y)
5577{
5578 GLfloat xy[2] = {x, y};
5579
5580 glUniform2fv(location, 1, (GLfloat*)&xy);
5581}
5582
5583void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5584{
5585 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5586
5587 if(count < 0)
5588 {
5589 return error(GL_INVALID_VALUE);
5590 }
5591
Nicolas Capens0bac2852016-05-07 06:09:58 -04005592 es2::Context *context = es2::getContext();
5593
5594 if(context)
5595 {
5596 es2::Program *program = context->getCurrentProgram();
5597
5598 if(!program)
5599 {
5600 return error(GL_INVALID_OPERATION);
5601 }
5602
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005603 if(location == -1)
5604 {
5605 return;
5606 }
5607
Nicolas Capens0bac2852016-05-07 06:09:58 -04005608 if(!program->setUniform2fv(location, count, v))
5609 {
5610 return error(GL_INVALID_OPERATION);
5611 }
5612 }
5613}
5614
5615void Uniform2i(GLint location, GLint x, GLint y)
5616{
5617 GLint xy[4] = {x, y};
5618
5619 glUniform2iv(location, 1, (GLint*)&xy);
5620}
5621
5622void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5623{
5624 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5625
5626 if(count < 0)
5627 {
5628 return error(GL_INVALID_VALUE);
5629 }
5630
Nicolas Capens0bac2852016-05-07 06:09:58 -04005631 es2::Context *context = es2::getContext();
5632
5633 if(context)
5634 {
5635 es2::Program *program = context->getCurrentProgram();
5636
5637 if(!program)
5638 {
5639 return error(GL_INVALID_OPERATION);
5640 }
5641
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005642 if(location == -1)
5643 {
5644 return;
5645 }
5646
Nicolas Capens0bac2852016-05-07 06:09:58 -04005647 if(!program->setUniform2iv(location, count, v))
5648 {
5649 return error(GL_INVALID_OPERATION);
5650 }
5651 }
5652}
5653
5654void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5655{
5656 GLfloat xyz[3] = {x, y, z};
5657
5658 glUniform3fv(location, 1, (GLfloat*)&xyz);
5659}
5660
5661void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5662{
5663 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5664
5665 if(count < 0)
5666 {
5667 return error(GL_INVALID_VALUE);
5668 }
5669
Nicolas Capens0bac2852016-05-07 06:09:58 -04005670 es2::Context *context = es2::getContext();
5671
5672 if(context)
5673 {
5674 es2::Program *program = context->getCurrentProgram();
5675
5676 if(!program)
5677 {
5678 return error(GL_INVALID_OPERATION);
5679 }
5680
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005681 if(location == -1)
5682 {
5683 return;
5684 }
5685
Nicolas Capens0bac2852016-05-07 06:09:58 -04005686 if(!program->setUniform3fv(location, count, v))
5687 {
5688 return error(GL_INVALID_OPERATION);
5689 }
5690 }
5691}
5692
5693void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5694{
5695 GLint xyz[3] = {x, y, z};
5696
5697 glUniform3iv(location, 1, (GLint*)&xyz);
5698}
5699
5700void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5701{
5702 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5703
5704 if(count < 0)
5705 {
5706 return error(GL_INVALID_VALUE);
5707 }
5708
Nicolas Capens0bac2852016-05-07 06:09:58 -04005709 es2::Context *context = es2::getContext();
5710
5711 if(context)
5712 {
5713 es2::Program *program = context->getCurrentProgram();
5714
5715 if(!program)
5716 {
5717 return error(GL_INVALID_OPERATION);
5718 }
5719
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005720 if(location == -1)
5721 {
5722 return;
5723 }
5724
Nicolas Capens0bac2852016-05-07 06:09:58 -04005725 if(!program->setUniform3iv(location, count, v))
5726 {
5727 return error(GL_INVALID_OPERATION);
5728 }
5729 }
5730}
5731
5732void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5733{
5734 GLfloat xyzw[4] = {x, y, z, w};
5735
5736 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5737}
5738
5739void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5740{
5741 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5742
5743 if(count < 0)
5744 {
5745 return error(GL_INVALID_VALUE);
5746 }
5747
Nicolas Capens0bac2852016-05-07 06:09:58 -04005748 es2::Context *context = es2::getContext();
5749
5750 if(context)
5751 {
5752 es2::Program *program = context->getCurrentProgram();
5753
5754 if(!program)
5755 {
5756 return error(GL_INVALID_OPERATION);
5757 }
5758
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005759 if(location == -1)
5760 {
5761 return;
5762 }
5763
Nicolas Capens0bac2852016-05-07 06:09:58 -04005764 if(!program->setUniform4fv(location, count, v))
5765 {
5766 return error(GL_INVALID_OPERATION);
5767 }
5768 }
5769}
5770
5771void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5772{
5773 GLint xyzw[4] = {x, y, z, w};
5774
5775 glUniform4iv(location, 1, (GLint*)&xyzw);
5776}
5777
5778void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5779{
5780 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5781
5782 if(count < 0)
5783 {
5784 return error(GL_INVALID_VALUE);
5785 }
5786
Nicolas Capens0bac2852016-05-07 06:09:58 -04005787 es2::Context *context = es2::getContext();
5788
5789 if(context)
5790 {
5791 es2::Program *program = context->getCurrentProgram();
5792
5793 if(!program)
5794 {
5795 return error(GL_INVALID_OPERATION);
5796 }
5797
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005798 if(location == -1)
5799 {
5800 return;
5801 }
5802
Nicolas Capens0bac2852016-05-07 06:09:58 -04005803 if(!program->setUniform4iv(location, count, v))
5804 {
5805 return error(GL_INVALID_OPERATION);
5806 }
5807 }
5808}
5809
5810void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5811{
5812 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5813 location, count, transpose, value);
5814
5815 if(count < 0)
5816 {
5817 return error(GL_INVALID_VALUE);
5818 }
5819
Nicolas Capens0bac2852016-05-07 06:09:58 -04005820 es2::Context *context = es2::getContext();
5821
5822 if(context)
5823 {
5824 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5825 {
5826 return error(GL_INVALID_VALUE);
5827 }
5828
5829 es2::Program *program = context->getCurrentProgram();
5830
5831 if(!program)
5832 {
5833 return error(GL_INVALID_OPERATION);
5834 }
5835
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005836 if(location == -1)
5837 {
5838 return;
5839 }
5840
Nicolas Capens0bac2852016-05-07 06:09:58 -04005841 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5842 {
5843 return error(GL_INVALID_OPERATION);
5844 }
5845 }
5846}
5847
5848void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5849{
5850 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5851 location, count, transpose, value);
5852
5853 if(count < 0)
5854 {
5855 return error(GL_INVALID_VALUE);
5856 }
5857
Nicolas Capens0bac2852016-05-07 06:09:58 -04005858 es2::Context *context = es2::getContext();
5859
5860 if(context)
5861 {
5862 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5863 {
5864 return error(GL_INVALID_VALUE);
5865 }
5866
5867 es2::Program *program = context->getCurrentProgram();
5868
5869 if(!program)
5870 {
5871 return error(GL_INVALID_OPERATION);
5872 }
5873
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005874 if(location == -1)
5875 {
5876 return;
5877 }
5878
Nicolas Capens0bac2852016-05-07 06:09:58 -04005879 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5880 {
5881 return error(GL_INVALID_OPERATION);
5882 }
5883 }
5884}
5885
5886void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5887{
5888 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5889 location, count, transpose, value);
5890
5891 if(count < 0)
5892 {
5893 return error(GL_INVALID_VALUE);
5894 }
5895
Nicolas Capens0bac2852016-05-07 06:09:58 -04005896 es2::Context *context = es2::getContext();
5897
5898 if(context)
5899 {
5900 if(context->getClientVersion() < 3 && transpose != GL_FALSE)
5901 {
5902 return error(GL_INVALID_VALUE);
5903 }
5904
5905 es2::Program *program = context->getCurrentProgram();
5906
5907 if(!program)
5908 {
5909 return error(GL_INVALID_OPERATION);
5910 }
5911
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005912 if(location == -1)
5913 {
5914 return;
5915 }
5916
Nicolas Capens0bac2852016-05-07 06:09:58 -04005917 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5918 {
5919 return error(GL_INVALID_OPERATION);
5920 }
5921 }
5922}
5923
5924void UseProgram(GLuint program)
5925{
5926 TRACE("(GLuint program = %d)", program);
5927
5928 es2::Context *context = es2::getContext();
5929
5930 if(context)
5931 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005932 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5933 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5934 {
5935 return error(GL_INVALID_OPERATION);
5936 }
5937
Nicolas Capens0bac2852016-05-07 06:09:58 -04005938 es2::Program *programObject = context->getProgram(program);
5939
5940 if(!programObject && program != 0)
5941 {
5942 if(context->getShader(program))
5943 {
5944 return error(GL_INVALID_OPERATION);
5945 }
5946 else
5947 {
5948 return error(GL_INVALID_VALUE);
5949 }
5950 }
5951
5952 if(program != 0 && !programObject->isLinked())
5953 {
5954 return error(GL_INVALID_OPERATION);
5955 }
5956
5957 context->useProgram(program);
5958 }
5959}
5960
5961void ValidateProgram(GLuint program)
5962{
5963 TRACE("(GLuint program = %d)", program);
5964
5965 es2::Context *context = es2::getContext();
5966
5967 if(context)
5968 {
5969 es2::Program *programObject = context->getProgram(program);
5970
5971 if(!programObject)
5972 {
5973 if(context->getShader(program))
5974 {
5975 return error(GL_INVALID_OPERATION);
5976 }
5977 else
5978 {
5979 return error(GL_INVALID_VALUE);
5980 }
5981 }
5982
Ben Vanik1fd3b282017-07-10 14:08:12 -07005983 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005984 }
5985}
5986
5987void VertexAttrib1f(GLuint index, GLfloat x)
5988{
5989 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5990
5991 if(index >= es2::MAX_VERTEX_ATTRIBS)
5992 {
5993 return error(GL_INVALID_VALUE);
5994 }
5995
5996 es2::Context *context = es2::getContext();
5997
5998 if(context)
5999 {
6000 GLfloat vals[4] = { x, 0, 0, 1 };
6001 context->setVertexAttrib(index, vals);
6002 }
6003}
6004
6005void VertexAttrib1fv(GLuint index, const GLfloat* values)
6006{
6007 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6008
6009 if(index >= es2::MAX_VERTEX_ATTRIBS)
6010 {
6011 return error(GL_INVALID_VALUE);
6012 }
6013
6014 es2::Context *context = es2::getContext();
6015
6016 if(context)
6017 {
6018 GLfloat vals[4] = { values[0], 0, 0, 1 };
6019 context->setVertexAttrib(index, vals);
6020 }
6021}
6022
6023void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
6024{
6025 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
6026
6027 if(index >= es2::MAX_VERTEX_ATTRIBS)
6028 {
6029 return error(GL_INVALID_VALUE);
6030 }
6031
6032 es2::Context *context = es2::getContext();
6033
6034 if(context)
6035 {
6036 GLfloat vals[4] = { x, y, 0, 1 };
6037 context->setVertexAttrib(index, vals);
6038 }
6039}
6040
6041void VertexAttrib2fv(GLuint index, const GLfloat* values)
6042{
6043 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6044
6045 if(index >= es2::MAX_VERTEX_ATTRIBS)
6046 {
6047 return error(GL_INVALID_VALUE);
6048 }
6049
6050 es2::Context *context = es2::getContext();
6051
6052 if(context)
6053 {
6054 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6055 context->setVertexAttrib(index, vals);
6056 }
6057}
6058
6059void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6060{
6061 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
6062
6063 if(index >= es2::MAX_VERTEX_ATTRIBS)
6064 {
6065 return error(GL_INVALID_VALUE);
6066 }
6067
6068 es2::Context *context = es2::getContext();
6069
6070 if(context)
6071 {
6072 GLfloat vals[4] = { x, y, z, 1 };
6073 context->setVertexAttrib(index, vals);
6074 }
6075}
6076
6077void VertexAttrib3fv(GLuint index, const GLfloat* values)
6078{
6079 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6080
6081 if(index >= es2::MAX_VERTEX_ATTRIBS)
6082 {
6083 return error(GL_INVALID_VALUE);
6084 }
6085
6086 es2::Context *context = es2::getContext();
6087
6088 if(context)
6089 {
6090 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6091 context->setVertexAttrib(index, vals);
6092 }
6093}
6094
6095void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6096{
6097 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
6098
6099 if(index >= es2::MAX_VERTEX_ATTRIBS)
6100 {
6101 return error(GL_INVALID_VALUE);
6102 }
6103
6104 es2::Context *context = es2::getContext();
6105
6106 if(context)
6107 {
6108 GLfloat vals[4] = { x, y, z, w };
6109 context->setVertexAttrib(index, vals);
6110 }
6111}
6112
6113void VertexAttrib4fv(GLuint index, const GLfloat* values)
6114{
6115 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
6116
6117 if(index >= es2::MAX_VERTEX_ATTRIBS)
6118 {
6119 return error(GL_INVALID_VALUE);
6120 }
6121
6122 es2::Context *context = es2::getContext();
6123
6124 if(context)
6125 {
6126 context->setVertexAttrib(index, values);
6127 }
6128}
6129
6130void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6131{
6132 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6133 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
6134 index, size, type, normalized, stride, ptr);
6135
6136 if(index >= es2::MAX_VERTEX_ATTRIBS)
6137 {
6138 return error(GL_INVALID_VALUE);
6139 }
6140
6141 if(size < 1 || size > 4)
6142 {
6143 return error(GL_INVALID_VALUE);
6144 }
6145
6146 GLint clientVersion = egl::getClientVersion();
6147
6148 switch(type)
6149 {
6150 case GL_BYTE:
6151 case GL_UNSIGNED_BYTE:
6152 case GL_SHORT:
6153 case GL_UNSIGNED_SHORT:
6154 case GL_FIXED:
6155 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04006156 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capens0bac2852016-05-07 06:09:58 -04006157 break;
6158 case GL_INT_2_10_10_10_REV:
6159 case GL_UNSIGNED_INT_2_10_10_10_REV:
6160 if(clientVersion >= 3)
6161 {
6162 if(size != 4)
6163 {
6164 return error(GL_INVALID_OPERATION);
6165 }
6166 break;
6167 }
6168 else return error(GL_INVALID_ENUM);
6169 case GL_INT:
6170 case GL_UNSIGNED_INT:
6171 case GL_HALF_FLOAT:
6172 if(clientVersion >= 3)
6173 {
6174 break;
6175 }
6176 else return error(GL_INVALID_ENUM);
6177 default:
6178 return error(GL_INVALID_ENUM);
6179 }
6180
6181 if(stride < 0)
6182 {
6183 return error(GL_INVALID_VALUE);
6184 }
6185
6186 es2::Context *context = es2::getContext();
6187
6188 if(context)
6189 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05006190 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
6191 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
6192 {
6193 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
6194 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
6195 return error(GL_INVALID_OPERATION);
6196 }
6197
Alexis Hetu6f284032017-12-11 15:19:36 -05006198 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006199 }
6200}
6201
6202void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
6203{
6204 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6205
6206 if(width < 0 || height < 0)
6207 {
6208 return error(GL_INVALID_VALUE);
6209 }
6210
6211 es2::Context *context = es2::getContext();
6212
6213 if(context)
6214 {
6215 context->setViewportParams(x, y, width, height);
6216 }
6217}
6218
Alexis Hetub9dda642016-10-06 11:25:32 -04006219static 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 -04006220{
6221 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6222 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6223 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6224 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6225
6226 switch(filter)
6227 {
6228 case GL_NEAREST:
6229 break;
6230 default:
6231 return error(GL_INVALID_ENUM);
6232 }
6233
6234 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6235 {
6236 return error(GL_INVALID_VALUE);
6237 }
6238
6239 es2::Context *context = es2::getContext();
6240
6241 if(context)
6242 {
6243 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
6244 {
6245 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6246 return error(GL_INVALID_OPERATION);
6247 }
6248
Alexis Hetub9dda642016-10-06 11:25:32 -04006249 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006250 }
6251}
6252
Alexis Hetub9dda642016-10-06 11:25:32 -04006253void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
6254{
6255 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
6256}
6257
Nicolas Capens0bac2852016-05-07 06:09:58 -04006258void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6259 GLbitfield mask, GLenum filter)
6260{
6261 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6262 {
6263 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6264 return error(GL_INVALID_OPERATION);
6265 }
6266
Alexis Hetub9dda642016-10-06 11:25:32 -04006267 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006268}
6269
6270void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04006271 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006272{
6273 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6274 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006275 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6276 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006277
6278 switch(target)
6279 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006280 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006281 switch(format)
6282 {
6283 case GL_DEPTH_COMPONENT:
6284 case GL_DEPTH_STENCIL_OES:
6285 return error(GL_INVALID_OPERATION);
6286 default:
6287 break;
6288 }
6289 break;
6290 default:
6291 return error(GL_INVALID_ENUM);
6292 }
6293
Nicolas Capensc61f46b2017-12-04 16:07:22 -05006294 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006295 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006296 return error(GL_INVALID_OPERATION);
6297 }
6298
6299 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion());
6300 if(validationError != GL_NONE)
6301 {
6302 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006303 }
6304
6305 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6306 {
6307 return error(GL_INVALID_VALUE);
6308 }
6309
6310 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6311 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6312 {
6313 return error(GL_INVALID_VALUE);
6314 }
6315
6316 if(border != 0)
6317 {
6318 return error(GL_INVALID_VALUE);
6319 }
6320
6321 es2::Context *context = es2::getContext();
6322
6323 if(context)
6324 {
6325 es2::Texture3D *texture = context->getTexture3D();
6326
6327 if(!texture)
6328 {
6329 return error(GL_INVALID_OPERATION);
6330 }
6331
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006332 GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006333 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006334 if(validationError != GL_NONE)
6335 {
6336 return error(validationError);
6337 }
6338
Nicolas Capens648b5822018-01-18 00:04:26 -05006339 texture->setImage(context, level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006340 }
6341}
6342
Alexis Hetu53f48092016-06-17 14:08:06 -04006343void 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 -04006344{
6345 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6346 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04006347 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
6348 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006349
6350 switch(target)
6351 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006352 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006353 break;
6354 default:
6355 return error(GL_INVALID_ENUM);
6356 }
6357
6358 if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
6359 {
6360 return;
6361 }
6362
6363 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6364 {
6365 return error(GL_INVALID_VALUE);
6366 }
6367
6368 if((width < 0) || (height < 0) || (depth < 0))
6369 {
6370 return error(GL_INVALID_VALUE);
6371 }
6372
6373 es2::Context *context = es2::getContext();
6374
6375 if(context)
6376 {
6377 es2::Texture3D *texture = context->getTexture3D();
6378
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006379 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
6380 if(validationError != GL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006381 {
6382 return error(validationError);
6383 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006384
Nicolas Capens5555af42017-12-14 13:14:03 -05006385 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006386 if(validationError != GL_NONE)
6387 {
6388 return error(validationError);
6389 }
6390
Nicolas Capens5555af42017-12-14 13:14:03 -05006391 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006392 }
6393}
6394
6395void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6396{
6397 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6398 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
6399 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6400
6401 switch(target)
6402 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006403 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006404 break;
6405 default:
6406 return error(GL_INVALID_ENUM);
6407 }
6408
6409 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6410 {
6411 return error(GL_INVALID_VALUE);
6412 }
6413
6414 es2::Context *context = es2::getContext();
6415
6416 if(context)
6417 {
6418 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6419
6420 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6421 {
6422 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6423 }
6424
6425 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
6426
6427 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
6428 {
6429 return error(GL_INVALID_OPERATION);
6430 }
6431
6432 es2::Texture3D *texture = context->getTexture3D();
6433
Nicolas Capensd2faaa92017-12-04 11:15:51 -05006434 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion());
Nicolas Capens0bac2852016-05-07 06:09:58 -04006435 if(validationError != GL_NONE)
6436 {
6437 return error(validationError);
6438 }
6439
6440 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
6441 }
6442}
6443
6444void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6445{
6446 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6447 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
6448 target, level, internalformat, width, height, depth, border, imageSize, data);
6449
6450 switch(target)
6451 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006452 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006453 break;
6454 default:
6455 return error(GL_INVALID_ENUM);
6456 }
6457
6458 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6459 {
6460 return error(GL_INVALID_VALUE);
6461 }
6462
6463 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6464 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6465 {
6466 return error(GL_INVALID_VALUE);
6467 }
6468
6469 switch(internalformat)
6470 {
6471 case GL_DEPTH_COMPONENT:
6472 case GL_DEPTH_COMPONENT16:
6473 case GL_DEPTH_COMPONENT32_OES:
6474 case GL_DEPTH_STENCIL_OES:
6475 case GL_DEPTH24_STENCIL8_OES:
6476 return error(GL_INVALID_OPERATION);
6477 default:
6478 {
6479 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
6480 if(validationError != GL_NONE)
6481 {
6482 return error(validationError);
6483 }
6484 }
6485 }
6486
6487 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
6488 {
6489 return error(GL_INVALID_VALUE);
6490 }
6491
6492 es2::Context *context = es2::getContext();
6493
6494 if(context)
6495 {
6496 es2::Texture3D *texture = context->getTexture3D();
6497
6498 if(!texture)
6499 {
6500 return error(GL_INVALID_OPERATION);
6501 }
6502
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006503 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006504
6505 if(validationError != GL_NONE)
6506 {
6507 return error(validationError);
6508 }
6509
Nicolas Capens0bac2852016-05-07 06:09:58 -04006510 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
6511 }
6512}
6513
6514void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6515{
6516 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6517 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6518 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
6519 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6520
6521 switch(target)
6522 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006523 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006524 break;
6525 default:
6526 return error(GL_INVALID_ENUM);
6527 }
6528
6529 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
6530 {
6531 return error(GL_INVALID_VALUE);
6532 }
6533
6534 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6535 {
6536 return error(GL_INVALID_VALUE);
6537 }
6538
6539 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
6540 if(validationError != GL_NONE)
6541 {
6542 return error(validationError);
6543 }
6544
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006545 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006546 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05006547 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006548 }
6549
6550 es2::Context *context = es2::getContext();
6551
6552 if(context)
6553 {
6554 es2::Texture3D *texture = context->getTexture3D();
6555
6556 if(!texture)
6557 {
6558 return error(GL_INVALID_OPERATION);
6559 }
6560
Alexis Hetu848aa7f2017-11-17 13:15:32 -05006561 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006562 if(validationError != GL_NONE)
6563 {
6564 return error(validationError);
6565 }
6566
6567 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006568 }
6569}
6570
6571void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6572{
6573 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6574 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6575
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006576 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006577 {
6578 return error(GL_INVALID_ENUM);
6579 }
6580
6581 es2::Context *context = es2::getContext();
6582
6583 if(context)
6584 {
6585 if(texture == 0)
6586 {
6587 textarget = GL_NONE;
6588 }
6589 else
6590 {
6591 es2::Texture *tex = context->getTexture(texture);
6592
6593 if(!tex)
6594 {
6595 return error(GL_INVALID_OPERATION);
6596 }
6597
6598 if(tex->isCompressed(textarget, level))
6599 {
6600 return error(GL_INVALID_OPERATION);
6601 }
6602
6603 switch(textarget)
6604 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006605 case GL_TEXTURE_3D:
6606 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006607 {
6608 return error(GL_INVALID_OPERATION);
6609 }
6610 break;
6611 default:
6612 return error(GL_INVALID_ENUM);
6613 }
6614
6615 if(level != 0)
6616 {
6617 return error(GL_INVALID_VALUE);
6618 }
6619 }
6620
6621 es2::Framebuffer *framebuffer = nullptr;
6622 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006623 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006624 {
6625 framebuffer = context->getReadFramebuffer();
6626 framebufferName = context->getReadFramebufferName();
6627 }
6628 else
6629 {
6630 framebuffer = context->getDrawFramebuffer();
6631 framebufferName = context->getDrawFramebufferName();
6632 }
6633
6634 if(framebufferName == 0 || !framebuffer)
6635 {
6636 return error(GL_INVALID_OPERATION);
6637 }
6638
6639 GLint clientVersion = context->getClientVersion();
6640
6641 switch(attachment)
6642 {
6643 case GL_COLOR_ATTACHMENT1:
6644 case GL_COLOR_ATTACHMENT2:
6645 case GL_COLOR_ATTACHMENT3:
6646 case GL_COLOR_ATTACHMENT4:
6647 case GL_COLOR_ATTACHMENT5:
6648 case GL_COLOR_ATTACHMENT6:
6649 case GL_COLOR_ATTACHMENT7:
6650 case GL_COLOR_ATTACHMENT8:
6651 case GL_COLOR_ATTACHMENT9:
6652 case GL_COLOR_ATTACHMENT10:
6653 case GL_COLOR_ATTACHMENT11:
6654 case GL_COLOR_ATTACHMENT12:
6655 case GL_COLOR_ATTACHMENT13:
6656 case GL_COLOR_ATTACHMENT14:
6657 case GL_COLOR_ATTACHMENT15:
6658 case GL_COLOR_ATTACHMENT16:
6659 case GL_COLOR_ATTACHMENT17:
6660 case GL_COLOR_ATTACHMENT18:
6661 case GL_COLOR_ATTACHMENT19:
6662 case GL_COLOR_ATTACHMENT20:
6663 case GL_COLOR_ATTACHMENT21:
6664 case GL_COLOR_ATTACHMENT22:
6665 case GL_COLOR_ATTACHMENT23:
6666 case GL_COLOR_ATTACHMENT24:
6667 case GL_COLOR_ATTACHMENT25:
6668 case GL_COLOR_ATTACHMENT26:
6669 case GL_COLOR_ATTACHMENT27:
6670 case GL_COLOR_ATTACHMENT28:
6671 case GL_COLOR_ATTACHMENT29:
6672 case GL_COLOR_ATTACHMENT30:
6673 case GL_COLOR_ATTACHMENT31:
6674 if(clientVersion < 3)
6675 {
6676 return error(GL_INVALID_ENUM);
6677 }
6678 // fall through
6679 case GL_COLOR_ATTACHMENT0:
6680 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6681 {
6682 return error(GL_INVALID_ENUM);
6683 }
6684 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);
6685 break;
6686 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6687 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6688 default:
6689 return error(GL_INVALID_ENUM);
6690 }
6691 }
6692}
6693
6694void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6695{
6696 if(egl::getClientVersion() == 1)
6697 {
6698 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6699 }
6700
6701 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6702
6703 switch(target)
6704 {
6705 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006706 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006707 case GL_TEXTURE_EXTERNAL_OES:
6708 break;
6709 default:
6710 return error(GL_INVALID_ENUM);
6711 }
6712
Nicolas Capens0bac2852016-05-07 06:09:58 -04006713 es2::Context *context = es2::getContext();
6714
6715 if(context)
6716 {
Alexis Hetu46768622018-01-16 22:09:28 -05006717 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006718
6719 if(!texture)
6720 {
6721 return error(GL_INVALID_OPERATION);
6722 }
6723
Nicolas Capens58df2f62016-06-07 14:48:56 -04006724 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006725
Nicolas Capens58df2f62016-06-07 14:48:56 -04006726 if(!eglImage)
6727 {
6728 return error(GL_INVALID_OPERATION);
6729 }
6730
6731 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006732 }
6733}
6734
6735void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6736{
6737 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6738
6739 UNIMPLEMENTED();
6740}
6741
6742GLboolean IsRenderbufferOES(GLuint renderbuffer)
6743{
6744 return IsRenderbuffer(renderbuffer);
6745}
6746
6747void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6748{
6749 BindRenderbuffer(target, renderbuffer);
6750}
6751
6752void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6753{
6754 DeleteRenderbuffers(n, renderbuffers);
6755}
6756
6757void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6758{
6759 GenRenderbuffers(n, renderbuffers);
6760}
6761
6762void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6763{
6764 RenderbufferStorage(target, internalformat, width, height);
6765}
6766
6767void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6768{
6769 GetRenderbufferParameteriv(target, pname, params);
6770}
6771
6772GLboolean IsFramebufferOES(GLuint framebuffer)
6773{
6774 return IsFramebuffer(framebuffer);
6775}
6776
6777void BindFramebufferOES(GLenum target, GLuint framebuffer)
6778{
6779 BindFramebuffer(target, framebuffer);
6780}
6781
6782void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6783{
6784 DeleteFramebuffers(n, framebuffers);
6785}
6786
6787void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6788{
6789 GenFramebuffers(n, framebuffers);
6790}
6791
6792GLenum CheckFramebufferStatusOES(GLenum target)
6793{
6794 return CheckFramebufferStatus(target);
6795}
6796
6797void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6798{
6799 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6800}
6801
6802void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6803{
6804 FramebufferTexture2D(target, attachment, textarget, texture, level);
6805}
6806
6807void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6808{
6809 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6810}
6811
6812void GenerateMipmapOES(GLenum target)
6813{
6814 GenerateMipmap(target);
6815}
6816
6817void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6818{
6819 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6820
6821 if(n < 0 || n > MAX_DRAW_BUFFERS)
6822 {
6823 return error(GL_INVALID_VALUE);
6824 }
6825
6826 es2::Context *context = es2::getContext();
6827
6828 if(context)
6829 {
6830 GLuint drawFramebufferName = context->getDrawFramebufferName();
6831
6832 if((drawFramebufferName == 0) && (n != 1))
6833 {
6834 return error(GL_INVALID_OPERATION);
6835 }
6836
6837 for(unsigned int i = 0; i < (unsigned)n; i++)
6838 {
6839 switch(bufs[i])
6840 {
6841 case GL_BACK:
6842 if(drawFramebufferName != 0)
6843 {
6844 return error(GL_INVALID_OPERATION);
6845 }
6846 break;
6847 case GL_NONE:
6848 break;
6849 case GL_COLOR_ATTACHMENT0_EXT:
6850 case GL_COLOR_ATTACHMENT1_EXT:
6851 case GL_COLOR_ATTACHMENT2_EXT:
6852 case GL_COLOR_ATTACHMENT3_EXT:
6853 case GL_COLOR_ATTACHMENT4_EXT:
6854 case GL_COLOR_ATTACHMENT5_EXT:
6855 case GL_COLOR_ATTACHMENT6_EXT:
6856 case GL_COLOR_ATTACHMENT7_EXT:
6857 case GL_COLOR_ATTACHMENT8_EXT:
6858 case GL_COLOR_ATTACHMENT9_EXT:
6859 case GL_COLOR_ATTACHMENT10_EXT:
6860 case GL_COLOR_ATTACHMENT11_EXT:
6861 case GL_COLOR_ATTACHMENT12_EXT:
6862 case GL_COLOR_ATTACHMENT13_EXT:
6863 case GL_COLOR_ATTACHMENT14_EXT:
6864 case GL_COLOR_ATTACHMENT15_EXT:
6865 {
6866 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6867
6868 if(index >= MAX_COLOR_ATTACHMENTS)
6869 {
6870 return error(GL_INVALID_OPERATION);
6871 }
6872
6873 if(index != i)
6874 {
6875 return error(GL_INVALID_OPERATION);
6876 }
6877
6878 if(drawFramebufferName == 0)
6879 {
6880 return error(GL_INVALID_OPERATION);
6881 }
6882 }
6883 break;
6884 default:
6885 return error(GL_INVALID_ENUM);
6886 }
6887 }
6888
6889 context->setFramebufferDrawBuffers(n, bufs);
6890 }
6891}
6892
6893}
6894
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006895extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006896{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006897 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006898 {
6899 const char *name;
6900 __eglMustCastToProperFunctionPointerType address;
6901 };
6902
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006903 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04006904 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006905 bool operator()(const Function &a, const Function &b) const
6906 {
6907 return strcmp(a.name, b.name) < 0;
6908 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006909 };
6910
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006911 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6912 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6913 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006914 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006915 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6916
6917 FUNCTION(glActiveTexture),
6918 FUNCTION(glAttachShader),
6919 FUNCTION(glBeginQuery),
6920 FUNCTION(glBeginQueryEXT),
6921 FUNCTION(glBeginTransformFeedback),
6922 FUNCTION(glBindAttribLocation),
6923 FUNCTION(glBindBuffer),
6924 FUNCTION(glBindBufferBase),
6925 FUNCTION(glBindBufferRange),
6926 FUNCTION(glBindFramebuffer),
6927 FUNCTION(glBindFramebufferOES),
6928 FUNCTION(glBindRenderbuffer),
6929 FUNCTION(glBindRenderbufferOES),
6930 FUNCTION(glBindSampler),
6931 FUNCTION(glBindTexture),
6932 FUNCTION(glBindTransformFeedback),
6933 FUNCTION(glBindVertexArray),
6934 FUNCTION(glBlendColor),
6935 FUNCTION(glBlendEquation),
6936 FUNCTION(glBlendEquationSeparate),
6937 FUNCTION(glBlendFunc),
6938 FUNCTION(glBlendFuncSeparate),
6939 FUNCTION(glBlitFramebuffer),
6940 FUNCTION(glBlitFramebufferANGLE),
6941 FUNCTION(glBufferData),
6942 FUNCTION(glBufferSubData),
6943 FUNCTION(glCheckFramebufferStatus),
6944 FUNCTION(glCheckFramebufferStatusOES),
6945 FUNCTION(glClear),
6946 FUNCTION(glClearBufferfi),
6947 FUNCTION(glClearBufferfv),
6948 FUNCTION(glClearBufferiv),
6949 FUNCTION(glClearBufferuiv),
6950 FUNCTION(glClearColor),
6951 FUNCTION(glClearDepthf),
6952 FUNCTION(glClearStencil),
6953 FUNCTION(glClientWaitSync),
6954 FUNCTION(glColorMask),
6955 FUNCTION(glCompileShader),
6956 FUNCTION(glCompressedTexImage2D),
6957 FUNCTION(glCompressedTexImage3D),
6958 FUNCTION(glCompressedTexSubImage2D),
6959 FUNCTION(glCompressedTexSubImage3D),
6960 FUNCTION(glCopyBufferSubData),
6961 FUNCTION(glCopyTexImage2D),
6962 FUNCTION(glCopyTexSubImage2D),
6963 FUNCTION(glCopyTexSubImage3D),
6964 FUNCTION(glCreateProgram),
6965 FUNCTION(glCreateShader),
6966 FUNCTION(glCullFace),
6967 FUNCTION(glDeleteBuffers),
6968 FUNCTION(glDeleteFencesNV),
6969 FUNCTION(glDeleteFramebuffers),
6970 FUNCTION(glDeleteFramebuffersOES),
6971 FUNCTION(glDeleteProgram),
6972 FUNCTION(glDeleteQueries),
6973 FUNCTION(glDeleteQueriesEXT),
6974 FUNCTION(glDeleteRenderbuffers),
6975 FUNCTION(glDeleteRenderbuffersOES),
6976 FUNCTION(glDeleteSamplers),
6977 FUNCTION(glDeleteShader),
6978 FUNCTION(glDeleteSync),
6979 FUNCTION(glDeleteTextures),
6980 FUNCTION(glDeleteTransformFeedbacks),
6981 FUNCTION(glDeleteVertexArrays),
6982 FUNCTION(glDepthFunc),
6983 FUNCTION(glDepthMask),
6984 FUNCTION(glDepthRangef),
6985 FUNCTION(glDetachShader),
6986 FUNCTION(glDisable),
6987 FUNCTION(glDisableVertexAttribArray),
6988 FUNCTION(glDrawArrays),
6989 FUNCTION(glDrawArraysInstanced),
6990 FUNCTION(glDrawBuffers),
6991 FUNCTION(glDrawBuffersEXT),
6992 FUNCTION(glDrawElements),
6993 FUNCTION(glDrawElementsInstanced),
6994 FUNCTION(glDrawRangeElements),
6995 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6996 FUNCTION(glEGLImageTargetTexture2DOES),
6997 FUNCTION(glEnable),
6998 FUNCTION(glEnableVertexAttribArray),
6999 FUNCTION(glEndQuery),
7000 FUNCTION(glEndQueryEXT),
7001 FUNCTION(glEndTransformFeedback),
7002 FUNCTION(glFenceSync),
7003 FUNCTION(glFinish),
7004 FUNCTION(glFinishFenceNV),
7005 FUNCTION(glFlush),
7006 FUNCTION(glFlushMappedBufferRange),
7007 FUNCTION(glFramebufferRenderbuffer),
7008 FUNCTION(glFramebufferRenderbufferOES),
7009 FUNCTION(glFramebufferTexture2D),
7010 FUNCTION(glFramebufferTexture2DOES),
7011 FUNCTION(glFramebufferTextureLayer),
7012 FUNCTION(glFrontFace),
7013 FUNCTION(glGenBuffers),
7014 FUNCTION(glGenFencesNV),
7015 FUNCTION(glGenFramebuffers),
7016 FUNCTION(glGenFramebuffersOES),
7017 FUNCTION(glGenQueries),
7018 FUNCTION(glGenQueriesEXT),
7019 FUNCTION(glGenRenderbuffers),
7020 FUNCTION(glGenRenderbuffersOES),
7021 FUNCTION(glGenSamplers),
7022 FUNCTION(glGenTextures),
7023 FUNCTION(glGenTransformFeedbacks),
7024 FUNCTION(glGenVertexArrays),
7025 FUNCTION(glGenerateMipmap),
7026 FUNCTION(glGenerateMipmapOES),
7027 FUNCTION(glGetActiveAttrib),
7028 FUNCTION(glGetActiveUniform),
7029 FUNCTION(glGetActiveUniformBlockName),
7030 FUNCTION(glGetActiveUniformBlockiv),
7031 FUNCTION(glGetActiveUniformsiv),
7032 FUNCTION(glGetAttachedShaders),
7033 FUNCTION(glGetAttribLocation),
7034 FUNCTION(glGetBooleanv),
7035 FUNCTION(glGetBufferParameteri64v),
7036 FUNCTION(glGetBufferParameteriv),
7037 FUNCTION(glGetBufferPointerv),
7038 FUNCTION(glGetError),
7039 FUNCTION(glGetFenceivNV),
7040 FUNCTION(glGetFloatv),
7041 FUNCTION(glGetFragDataLocation),
7042 FUNCTION(glGetFramebufferAttachmentParameteriv),
7043 FUNCTION(glGetFramebufferAttachmentParameterivOES),
7044 FUNCTION(glGetGraphicsResetStatusEXT),
7045 FUNCTION(glGetInteger64i_v),
7046 FUNCTION(glGetInteger64v),
7047 FUNCTION(glGetIntegeri_v),
7048 FUNCTION(glGetIntegerv),
7049 FUNCTION(glGetInternalformativ),
7050 FUNCTION(glGetProgramBinary),
7051 FUNCTION(glGetProgramInfoLog),
7052 FUNCTION(glGetProgramiv),
7053 FUNCTION(glGetQueryObjectuiv),
7054 FUNCTION(glGetQueryObjectuivEXT),
7055 FUNCTION(glGetQueryiv),
7056 FUNCTION(glGetQueryivEXT),
7057 FUNCTION(glGetRenderbufferParameteriv),
7058 FUNCTION(glGetRenderbufferParameterivOES),
7059 FUNCTION(glGetSamplerParameterfv),
7060 FUNCTION(glGetSamplerParameteriv),
7061 FUNCTION(glGetShaderInfoLog),
7062 FUNCTION(glGetShaderPrecisionFormat),
7063 FUNCTION(glGetShaderSource),
7064 FUNCTION(glGetShaderiv),
7065 FUNCTION(glGetString),
7066 FUNCTION(glGetStringi),
7067 FUNCTION(glGetSynciv),
7068 FUNCTION(glGetTexParameterfv),
7069 FUNCTION(glGetTexParameteriv),
7070 FUNCTION(glGetTransformFeedbackVarying),
7071 FUNCTION(glGetUniformBlockIndex),
7072 FUNCTION(glGetUniformIndices),
7073 FUNCTION(glGetUniformLocation),
7074 FUNCTION(glGetUniformfv),
7075 FUNCTION(glGetUniformiv),
7076 FUNCTION(glGetUniformuiv),
7077 FUNCTION(glGetVertexAttribIiv),
7078 FUNCTION(glGetVertexAttribIuiv),
7079 FUNCTION(glGetVertexAttribPointerv),
7080 FUNCTION(glGetVertexAttribfv),
7081 FUNCTION(glGetVertexAttribiv),
7082 FUNCTION(glGetnUniformfvEXT),
7083 FUNCTION(glGetnUniformivEXT),
7084 FUNCTION(glHint),
7085 FUNCTION(glInvalidateFramebuffer),
7086 FUNCTION(glInvalidateSubFramebuffer),
7087 FUNCTION(glIsBuffer),
7088 FUNCTION(glIsEnabled),
7089 FUNCTION(glIsFenceNV),
7090 FUNCTION(glIsFramebuffer),
7091 FUNCTION(glIsFramebufferOES),
7092 FUNCTION(glIsProgram),
7093 FUNCTION(glIsQuery),
7094 FUNCTION(glIsQueryEXT),
7095 FUNCTION(glIsRenderbuffer),
7096 FUNCTION(glIsRenderbufferOES),
7097 FUNCTION(glIsSampler),
7098 FUNCTION(glIsShader),
7099 FUNCTION(glIsSync),
7100 FUNCTION(glIsTexture),
7101 FUNCTION(glIsTransformFeedback),
7102 FUNCTION(glIsVertexArray),
7103 FUNCTION(glLineWidth),
7104 FUNCTION(glLinkProgram),
7105 FUNCTION(glMapBufferRange),
7106 FUNCTION(glPauseTransformFeedback),
7107 FUNCTION(glPixelStorei),
7108 FUNCTION(glPolygonOffset),
7109 FUNCTION(glProgramBinary),
7110 FUNCTION(glProgramParameteri),
7111 FUNCTION(glReadBuffer),
7112 FUNCTION(glReadPixels),
7113 FUNCTION(glReadnPixelsEXT),
7114 FUNCTION(glReleaseShaderCompiler),
7115 FUNCTION(glRenderbufferStorage),
7116 FUNCTION(glRenderbufferStorageMultisample),
7117 FUNCTION(glRenderbufferStorageMultisampleANGLE),
7118 FUNCTION(glRenderbufferStorageOES),
7119 FUNCTION(glResumeTransformFeedback),
7120 FUNCTION(glSampleCoverage),
7121 FUNCTION(glSamplerParameterf),
7122 FUNCTION(glSamplerParameterfv),
7123 FUNCTION(glSamplerParameteri),
7124 FUNCTION(glSamplerParameteriv),
7125 FUNCTION(glScissor),
7126 FUNCTION(glSetFenceNV),
7127 FUNCTION(glShaderBinary),
7128 FUNCTION(glShaderSource),
7129 FUNCTION(glStencilFunc),
7130 FUNCTION(glStencilFuncSeparate),
7131 FUNCTION(glStencilMask),
7132 FUNCTION(glStencilMaskSeparate),
7133 FUNCTION(glStencilOp),
7134 FUNCTION(glStencilOpSeparate),
7135 FUNCTION(glTestFenceNV),
7136 FUNCTION(glTexImage2D),
7137 FUNCTION(glTexImage3D),
7138 FUNCTION(glTexImage3DOES),
7139 FUNCTION(glTexParameterf),
7140 FUNCTION(glTexParameterfv),
7141 FUNCTION(glTexParameteri),
7142 FUNCTION(glTexParameteriv),
7143 FUNCTION(glTexStorage2D),
7144 FUNCTION(glTexStorage3D),
7145 FUNCTION(glTexSubImage2D),
7146 FUNCTION(glTexSubImage3D),
7147 FUNCTION(glTransformFeedbackVaryings),
7148 FUNCTION(glUniform1f),
7149 FUNCTION(glUniform1fv),
7150 FUNCTION(glUniform1i),
7151 FUNCTION(glUniform1iv),
7152 FUNCTION(glUniform1ui),
7153 FUNCTION(glUniform1uiv),
7154 FUNCTION(glUniform2f),
7155 FUNCTION(glUniform2fv),
7156 FUNCTION(glUniform2i),
7157 FUNCTION(glUniform2iv),
7158 FUNCTION(glUniform2ui),
7159 FUNCTION(glUniform2uiv),
7160 FUNCTION(glUniform3f),
7161 FUNCTION(glUniform3fv),
7162 FUNCTION(glUniform3i),
7163 FUNCTION(glUniform3iv),
7164 FUNCTION(glUniform3ui),
7165 FUNCTION(glUniform3uiv),
7166 FUNCTION(glUniform4f),
7167 FUNCTION(glUniform4fv),
7168 FUNCTION(glUniform4i),
7169 FUNCTION(glUniform4iv),
7170 FUNCTION(glUniform4ui),
7171 FUNCTION(glUniform4uiv),
7172 FUNCTION(glUniformBlockBinding),
7173 FUNCTION(glUniformMatrix2fv),
7174 FUNCTION(glUniformMatrix2x3fv),
7175 FUNCTION(glUniformMatrix2x4fv),
7176 FUNCTION(glUniformMatrix3fv),
7177 FUNCTION(glUniformMatrix3x2fv),
7178 FUNCTION(glUniformMatrix3x4fv),
7179 FUNCTION(glUniformMatrix4fv),
7180 FUNCTION(glUniformMatrix4x2fv),
7181 FUNCTION(glUniformMatrix4x3fv),
7182 FUNCTION(glUnmapBuffer),
7183 FUNCTION(glUseProgram),
7184 FUNCTION(glValidateProgram),
7185 FUNCTION(glVertexAttrib1f),
7186 FUNCTION(glVertexAttrib1fv),
7187 FUNCTION(glVertexAttrib2f),
7188 FUNCTION(glVertexAttrib2fv),
7189 FUNCTION(glVertexAttrib3f),
7190 FUNCTION(glVertexAttrib3fv),
7191 FUNCTION(glVertexAttrib4f),
7192 FUNCTION(glVertexAttrib4fv),
7193 FUNCTION(glVertexAttribDivisor),
7194 FUNCTION(glVertexAttribI4i),
7195 FUNCTION(glVertexAttribI4iv),
7196 FUNCTION(glVertexAttribI4ui),
7197 FUNCTION(glVertexAttribI4uiv),
7198 FUNCTION(glVertexAttribIPointer),
7199 FUNCTION(glVertexAttribPointer),
7200 FUNCTION(glViewport),
7201 FUNCTION(glWaitSync),
7202
7203 #undef FUNCTION
7204 };
7205
7206 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
7207 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
7208
7209 Function needle;
7210 needle.name = procname;
7211
7212 if(procname && strncmp("gl", procname, 2) == 0)
7213 {
7214 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
7215 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04007216 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01007217 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04007218 }
7219 }
7220
7221 return nullptr;
7222}