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