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