blob: 8474c4ed2b767cb12dc2fc035fe73248d870b311 [file] [log] [blame]
Nicolas Capens264f1522015-01-09 17:21:17 -05001// SwiftShader Software Renderer
2//
3// Copyright(c) 2005-2013 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
Nicolas Capens79eef882015-01-09 17:38:27 -050011// libGL.cpp: Implements the exported OpenGL functions.
Nicolas Capens264f1522015-01-09 17:21:17 -050012
13#include "main.h"
14#include "mathutil.h"
15#include "utilities.h"
16#include "Buffer.h"
17#include "Context.h"
18#include "Fence.h"
19#include "Framebuffer.h"
20#include "Program.h"
21#include "Renderbuffer.h"
22#include "Shader.h"
23#include "Texture.h"
24#include "Query.h"
25#include "common/debug.h"
26#include "Common/Version.h"
27#include "Main/Register.hpp"
28
29#define GL_APICALL
30#include <GLES2/gl2.h>
31#include <GLES2/gl2ext.h>
32
33#include <exception>
34#include <limits>
35
36static bool validImageSize(GLint level, GLsizei width, GLsizei height)
37{
38 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
39 {
40 return false;
41 }
42
43 return true;
44}
45
46static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)
47{
48 if(!texture)
49 {
50 return error(GL_INVALID_OPERATION, false);
51 }
52
53 if(compressed != texture->isCompressed(target, level))
54 {
55 return error(GL_INVALID_OPERATION, false);
56 }
57
58 if(format != GL_NONE && format != texture->getFormat(target, level))
59 {
60 return error(GL_INVALID_OPERATION, false);
61 }
62
63 if(compressed)
64 {
65 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
66 (height % 4 != 0 && height != texture->getHeight(target, 0)))
67 {
68 return error(GL_INVALID_OPERATION, false);
69 }
70 }
71
72 if(xoffset + width > texture->getWidth(target, level) ||
73 yoffset + height > texture->getHeight(target, level))
74 {
75 return error(GL_INVALID_VALUE, false);
76 }
77
78 return true;
79}
80
81// Check for combinations of format and type that are valid for ReadPixels
82static bool validReadFormatType(GLenum format, GLenum type)
83{
84 switch(format)
85 {
86 case GL_RGBA:
87 switch(type)
88 {
89 case GL_UNSIGNED_BYTE:
90 break;
91 default:
92 return false;
93 }
94 break;
95 case GL_BGRA_EXT:
96 switch(type)
97 {
98 case GL_UNSIGNED_BYTE:
99 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
100 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
101 break;
102 default:
103 return false;
104 }
105 break;
106 case es2::IMPLEMENTATION_COLOR_READ_FORMAT:
107 switch(type)
108 {
109 case es2::IMPLEMENTATION_COLOR_READ_TYPE:
110 break;
111 default:
112 return false;
113 }
114 break;
115 default:
116 return false;
117 }
118
119 return true;
120}
121
122extern "C"
123{
124
125void GL_APIENTRY glActiveTexture(GLenum texture)
126{
127 TRACE("(GLenum texture = 0x%X)", texture);
128
129 es2::Context *context = es2::getContext();
130
131 if(context)
132 {
133 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
134 {
135 return error(GL_INVALID_ENUM);
136 }
137
138 context->setActiveSampler(texture - GL_TEXTURE0);
139 }
140}
141
142void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
143{
144 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
145
146 es2::Context *context = es2::getContext();
147
148 if(context)
149 {
150 es2::Program *programObject = context->getProgram(program);
151 es2::Shader *shaderObject = context->getShader(shader);
152
153 if(!programObject)
154 {
155 if(context->getShader(program))
156 {
157 return error(GL_INVALID_OPERATION);
158 }
159 else
160 {
161 return error(GL_INVALID_VALUE);
162 }
163 }
164
165 if(!shaderObject)
166 {
167 if(context->getProgram(shader))
168 {
169 return error(GL_INVALID_OPERATION);
170 }
171 else
172 {
173 return error(GL_INVALID_VALUE);
174 }
175 }
176
177 if(!programObject->attachShader(shaderObject))
178 {
179 return error(GL_INVALID_OPERATION);
180 }
181 }
182}
183
184void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
185{
186 TRACE("(GLenum target = 0x%X, GLuint %d)", target, id);
187
188 switch(target)
189 {
190 case GL_ANY_SAMPLES_PASSED_EXT:
191 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
192 break;
193 default:
194 return error(GL_INVALID_ENUM);
195 }
196
197 if(id == 0)
198 {
199 return error(GL_INVALID_OPERATION);
200 }
201
202 es2::Context *context = es2::getContext();
203
204 if(context)
205 {
206 context->beginQuery(target, id);
207 }
208}
209
210void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
211{
212 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
213
214 if(index >= es2::MAX_VERTEX_ATTRIBS)
215 {
216 return error(GL_INVALID_VALUE);
217 }
218
219 es2::Context *context = es2::getContext();
220
221 if(context)
222 {
223 es2::Program *programObject = context->getProgram(program);
224
225 if(!programObject)
226 {
227 if(context->getShader(program))
228 {
229 return error(GL_INVALID_OPERATION);
230 }
231 else
232 {
233 return error(GL_INVALID_VALUE);
234 }
235 }
236
237 if(strncmp(name, "gl_", 3) == 0)
238 {
239 return error(GL_INVALID_OPERATION);
240 }
241
242 programObject->bindAttributeLocation(index, name);
243 }
244}
245
246void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
247{
248 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
249
250 es2::Context *context = es2::getContext();
251
252 if(context)
253 {
254 switch(target)
255 {
256 case GL_ARRAY_BUFFER:
257 context->bindArrayBuffer(buffer);
258 return;
259 case GL_ELEMENT_ARRAY_BUFFER:
260 context->bindElementArrayBuffer(buffer);
261 return;
262 default:
263 return error(GL_INVALID_ENUM);
264 }
265 }
266}
267
268void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
269{
270 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
271
272 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
273 {
274 return error(GL_INVALID_ENUM);
275 }
276
277 es2::Context *context = es2::getContext();
278
279 if(context)
280 {
281 if(target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
282 {
283 context->bindReadFramebuffer(framebuffer);
284 }
285
286 if(target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
287 {
288 context->bindDrawFramebuffer(framebuffer);
289 }
290 }
291}
292
293void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
294{
295 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
296
297 if(target != GL_RENDERBUFFER)
298 {
299 return error(GL_INVALID_ENUM);
300 }
301
302 es2::Context *context = es2::getContext();
303
304 if(context)
305 {
306 if(renderbuffer != 0 && !context->getRenderbuffer(renderbuffer))
307 {
308 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
309 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
310 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
311 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
312 return error(GL_INVALID_OPERATION);
313 }
314
315 context->bindRenderbuffer(renderbuffer);
316 }
317}
318
319void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
320{
321 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
322
323 es2::Context *context = es2::getContext();
324
325 if(context)
326 {
327 es2::Texture *textureObject = context->getTexture(texture);
328
329 if(textureObject && textureObject->getTarget() != target && texture != 0)
330 {
331 return error(GL_INVALID_OPERATION);
332 }
333
334 switch(target)
335 {
336 case GL_TEXTURE_2D:
337 context->bindTexture2D(texture);
338 return;
339 case GL_TEXTURE_CUBE_MAP:
340 context->bindTextureCubeMap(texture);
341 return;
342 case GL_TEXTURE_EXTERNAL_OES:
343 context->bindTextureExternal(texture);
344 return;
345 default:
346 return error(GL_INVALID_ENUM);
347 }
348 }
349}
350
351void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
352{
353 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
354 red, green, blue, alpha);
355
356 es2::Context* context = es2::getContext();
357
358 if(context)
359 {
360 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
361 }
362}
363
364void GL_APIENTRY glBlendEquation(GLenum mode)
365{
366 glBlendEquationSeparate(mode, mode);
367}
368
369void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
370{
371 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
372
373 switch(modeRGB)
374 {
375 case GL_FUNC_ADD:
376 case GL_FUNC_SUBTRACT:
377 case GL_FUNC_REVERSE_SUBTRACT:
378 case GL_MIN_EXT:
379 case GL_MAX_EXT:
380 break;
381 default:
382 return error(GL_INVALID_ENUM);
383 }
384
385 switch(modeAlpha)
386 {
387 case GL_FUNC_ADD:
388 case GL_FUNC_SUBTRACT:
389 case GL_FUNC_REVERSE_SUBTRACT:
390 case GL_MIN_EXT:
391 case GL_MAX_EXT:
392 break;
393 default:
394 return error(GL_INVALID_ENUM);
395 }
396
397 es2::Context *context = es2::getContext();
398
399 if(context)
400 {
401 context->setBlendEquation(modeRGB, modeAlpha);
402 }
403}
404
405void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
406{
407 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
408}
409
410void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
411{
412 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
413 srcRGB, dstRGB, srcAlpha, dstAlpha);
414
415 switch(srcRGB)
416 {
417 case GL_ZERO:
418 case GL_ONE:
419 case GL_SRC_COLOR:
420 case GL_ONE_MINUS_SRC_COLOR:
421 case GL_DST_COLOR:
422 case GL_ONE_MINUS_DST_COLOR:
423 case GL_SRC_ALPHA:
424 case GL_ONE_MINUS_SRC_ALPHA:
425 case GL_DST_ALPHA:
426 case GL_ONE_MINUS_DST_ALPHA:
427 case GL_CONSTANT_COLOR:
428 case GL_ONE_MINUS_CONSTANT_COLOR:
429 case GL_CONSTANT_ALPHA:
430 case GL_ONE_MINUS_CONSTANT_ALPHA:
431 case GL_SRC_ALPHA_SATURATE:
432 break;
433 default:
434 return error(GL_INVALID_ENUM);
435 }
436
437 switch(dstRGB)
438 {
439 case GL_ZERO:
440 case GL_ONE:
441 case GL_SRC_COLOR:
442 case GL_ONE_MINUS_SRC_COLOR:
443 case GL_DST_COLOR:
444 case GL_ONE_MINUS_DST_COLOR:
445 case GL_SRC_ALPHA:
446 case GL_ONE_MINUS_SRC_ALPHA:
447 case GL_DST_ALPHA:
448 case GL_ONE_MINUS_DST_ALPHA:
449 case GL_CONSTANT_COLOR:
450 case GL_ONE_MINUS_CONSTANT_COLOR:
451 case GL_CONSTANT_ALPHA:
452 case GL_ONE_MINUS_CONSTANT_ALPHA:
453 break;
454 default:
455 return error(GL_INVALID_ENUM);
456 }
457
458 switch(srcAlpha)
459 {
460 case GL_ZERO:
461 case GL_ONE:
462 case GL_SRC_COLOR:
463 case GL_ONE_MINUS_SRC_COLOR:
464 case GL_DST_COLOR:
465 case GL_ONE_MINUS_DST_COLOR:
466 case GL_SRC_ALPHA:
467 case GL_ONE_MINUS_SRC_ALPHA:
468 case GL_DST_ALPHA:
469 case GL_ONE_MINUS_DST_ALPHA:
470 case GL_CONSTANT_COLOR:
471 case GL_ONE_MINUS_CONSTANT_COLOR:
472 case GL_CONSTANT_ALPHA:
473 case GL_ONE_MINUS_CONSTANT_ALPHA:
474 case GL_SRC_ALPHA_SATURATE:
475 break;
476 default:
477 return error(GL_INVALID_ENUM);
478 }
479
480 switch(dstAlpha)
481 {
482 case GL_ZERO:
483 case GL_ONE:
484 case GL_SRC_COLOR:
485 case GL_ONE_MINUS_SRC_COLOR:
486 case GL_DST_COLOR:
487 case GL_ONE_MINUS_DST_COLOR:
488 case GL_SRC_ALPHA:
489 case GL_ONE_MINUS_SRC_ALPHA:
490 case GL_DST_ALPHA:
491 case GL_ONE_MINUS_DST_ALPHA:
492 case GL_CONSTANT_COLOR:
493 case GL_ONE_MINUS_CONSTANT_COLOR:
494 case GL_CONSTANT_ALPHA:
495 case GL_ONE_MINUS_CONSTANT_ALPHA:
496 break;
497 default:
498 return error(GL_INVALID_ENUM);
499 }
500
501 es2::Context *context = es2::getContext();
502
503 if(context)
504 {
505 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
506 }
507}
508
509void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
510{
511 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
512
513 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
514 target, size, data, usage);
515
516 if(size < 0)
517 {
518 return error(GL_INVALID_VALUE);
519 }
520
521 switch(usage)
522 {
523 case GL_STREAM_DRAW:
524 case GL_STATIC_DRAW:
525 case GL_DYNAMIC_DRAW:
526 break;
527 default:
528 return error(GL_INVALID_ENUM);
529 }
530
531 es2::Context *context = es2::getContext();
532
533 if(context)
534 {
535 es2::Buffer *buffer;
536
537 switch(target)
538 {
539 case GL_ARRAY_BUFFER:
540 buffer = context->getArrayBuffer();
541 break;
542 case GL_ELEMENT_ARRAY_BUFFER:
543 buffer = context->getElementArrayBuffer();
544 break;
545 default:
546 return error(GL_INVALID_ENUM);
547 }
548
549 if(!buffer)
550 {
551 return error(GL_INVALID_OPERATION);
552 }
553
554 buffer->bufferData(data, size, usage);
555 }
556}
557
558void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
559{
560 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
561 offset = static_cast<GLint>(offset);
562
563 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
564 target, offset, size, data);
565
566 if(size < 0 || offset < 0)
567 {
568 return error(GL_INVALID_VALUE);
569 }
570
571 if(data == NULL)
572 {
573 return;
574 }
575
576 es2::Context *context = es2::getContext();
577
578 if(context)
579 {
580 es2::Buffer *buffer;
581
582 switch(target)
583 {
584 case GL_ARRAY_BUFFER:
585 buffer = context->getArrayBuffer();
586 break;
587 case GL_ELEMENT_ARRAY_BUFFER:
588 buffer = context->getElementArrayBuffer();
589 break;
590 default:
591 return error(GL_INVALID_ENUM);
592 }
593
594 if(!buffer)
595 {
596 return error(GL_INVALID_OPERATION);
597 }
598
599 if((size_t)size + offset > buffer->size())
600 {
601 return error(GL_INVALID_VALUE);
602 }
603
604 buffer->bufferSubData(data, size, offset);
605 }
606}
607
608GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
609{
610 TRACE("(GLenum target = 0x%X)", target);
611
612 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
613 {
614 return error(GL_INVALID_ENUM, 0);
615 }
616
617 es2::Context *context = es2::getContext();
618
619 if(context)
620 {
621 es2::Framebuffer *framebuffer = NULL;
622 if(target == GL_READ_FRAMEBUFFER_ANGLE)
623 {
624 framebuffer = context->getReadFramebuffer();
625 }
626 else
627 {
628 framebuffer = context->getDrawFramebuffer();
629 }
630
631 return framebuffer->completeness();
632 }
633
634 return 0;
635}
636
637void GL_APIENTRY glClear(GLbitfield mask)
638{
639 TRACE("(GLbitfield mask = %X)", mask);
640
641 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
642 {
643 return error(GL_INVALID_VALUE);
644 }
645
646 es2::Context *context = es2::getContext();
647
648 if(context)
649 {
650 context->clear(mask);
651 }
652}
653
654void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
655{
656 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
657 red, green, blue, alpha);
658
659 es2::Context *context = es2::getContext();
660
661 if(context)
662 {
663 context->setClearColor(red, green, blue, alpha);
664 }
665}
666
667void GL_APIENTRY glClearDepthf(GLclampf depth)
668{
669 TRACE("(GLclampf depth = %f)", depth);
670
671 es2::Context *context = es2::getContext();
672
673 if(context)
674 {
675 context->setClearDepth(depth);
676 }
677}
678
679void GL_APIENTRY glClearStencil(GLint s)
680{
681 TRACE("(GLint s = %d)", s);
682
683 es2::Context *context = es2::getContext();
684
685 if(context)
686 {
687 context->setClearStencil(s);
688 }
689}
690
691void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
692{
693 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
694 red, green, blue, alpha);
695
696 es2::Context *context = es2::getContext();
697
698 if(context)
699 {
700 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
701 }
702}
703
704void GL_APIENTRY glCompileShader(GLuint shader)
705{
706 TRACE("(GLuint shader = %d)", shader);
707
708 es2::Context *context = es2::getContext();
709
710 if(context)
711 {
712 es2::Shader *shaderObject = context->getShader(shader);
713
714 if(!shaderObject)
715 {
716 if(context->getProgram(shader))
717 {
718 return error(GL_INVALID_OPERATION);
719 }
720 else
721 {
722 return error(GL_INVALID_VALUE);
723 }
724 }
725
726 shaderObject->compile();
727 }
728}
729
730void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
731 GLint border, GLsizei imageSize, const GLvoid* data)
732{
733 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
734 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
735 target, level, internalformat, width, height, border, imageSize, data);
736
737 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
738 {
739 return error(GL_INVALID_VALUE);
740 }
741
742 switch(internalformat)
743 {
744 case GL_ETC1_RGB8_OES:
745 break;
746 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
747 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
748 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
749 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
750 if(!S3TC_SUPPORT)
751 {
752 return error(GL_INVALID_ENUM);
753 }
754 break;
755 case GL_DEPTH_COMPONENT:
756 case GL_DEPTH_COMPONENT16:
757 case GL_DEPTH_COMPONENT32_OES:
758 case GL_DEPTH_STENCIL_OES:
759 case GL_DEPTH24_STENCIL8_OES:
760 return error(GL_INVALID_OPERATION);
761 default:
762 return error(GL_INVALID_ENUM);
763 }
764
765 if(border != 0)
766 {
767 return error(GL_INVALID_VALUE);
768 }
769
770 es2::Context *context = es2::getContext();
771
772 if(context)
773 {
774 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
775 {
776 return error(GL_INVALID_VALUE);
777 }
778
779 switch(target)
780 {
781 case GL_TEXTURE_2D:
782 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
783 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
784 {
785 return error(GL_INVALID_VALUE);
786 }
787 break;
788 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
789 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
790 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
791 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
792 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
793 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
794 if(width != height)
795 {
796 return error(GL_INVALID_VALUE);
797 }
798
799 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
800 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
801 {
802 return error(GL_INVALID_VALUE);
803 }
804 break;
805 default:
806 return error(GL_INVALID_ENUM);
807 }
808
809 if(imageSize != es2::ComputeCompressedSize(width, height, internalformat))
810 {
811 return error(GL_INVALID_VALUE);
812 }
813
814 if(target == GL_TEXTURE_2D)
815 {
816 es2::Texture2D *texture = context->getTexture2D();
817
818 if(!texture)
819 {
820 return error(GL_INVALID_OPERATION);
821 }
822
823 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
824 }
825 else
826 {
827 es2::TextureCubeMap *texture = context->getTextureCubeMap();
828
829 if(!texture)
830 {
831 return error(GL_INVALID_OPERATION);
832 }
833
834 switch(target)
835 {
836 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
838 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
839 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
840 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
841 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
842 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
843 break;
844 default: UNREACHABLE();
845 }
846 }
847 }
848}
849
850void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
851 GLenum format, GLsizei imageSize, const GLvoid* data)
852{
853 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
854 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
855 "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
856 target, level, xoffset, yoffset, width, height, format, imageSize, data);
857
858 if(!es2::IsTextureTarget(target))
859 {
860 return error(GL_INVALID_ENUM);
861 }
862
863 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
864 {
865 return error(GL_INVALID_VALUE);
866 }
867
868 switch(format)
869 {
870 case GL_ETC1_RGB8_OES:
871 break;
872 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
873 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
874 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
875 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
876 if(!S3TC_SUPPORT)
877 {
878 return error(GL_INVALID_ENUM);
879 }
880 break;
881 default:
882 return error(GL_INVALID_ENUM);
883 }
884
885 if(width == 0 || height == 0 || data == NULL)
886 {
887 return;
888 }
889
890 es2::Context *context = es2::getContext();
891
892 if(context)
893 {
894 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
895 {
896 return error(GL_INVALID_VALUE);
897 }
898
899 if(imageSize != es2::ComputeCompressedSize(width, height, format))
900 {
901 return error(GL_INVALID_VALUE);
902 }
903
904 if(xoffset % 4 != 0 || yoffset % 4 != 0)
905 {
906 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
907 return error(GL_INVALID_OPERATION);
908 }
909
910 if(target == GL_TEXTURE_2D)
911 {
912 es2::Texture2D *texture = context->getTexture2D();
913
914 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
915 {
916 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
917 }
918 }
919 else if(es2::IsCubemapTextureTarget(target))
920 {
921 es2::TextureCubeMap *texture = context->getTextureCubeMap();
922
923 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
924 {
925 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
926 }
927 }
928 else
929 {
930 UNREACHABLE();
931 }
932 }
933}
934
935void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
936{
937 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
938 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
939 target, level, internalformat, x, y, width, height, border);
940
941 if(!validImageSize(level, width, height))
942 {
943 return error(GL_INVALID_VALUE);
944 }
945
946 if(border != 0)
947 {
948 return error(GL_INVALID_VALUE);
949 }
950
951 es2::Context *context = es2::getContext();
952
953 if(context)
954 {
955 switch(target)
956 {
957 case GL_TEXTURE_2D:
958 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
959 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
960 {
961 return error(GL_INVALID_VALUE);
962 }
963 break;
964 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
970 if(width != height)
971 {
972 return error(GL_INVALID_VALUE);
973 }
974
975 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
976 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
977 {
978 return error(GL_INVALID_VALUE);
979 }
980 break;
981 default:
982 return error(GL_INVALID_ENUM);
983 }
984
985 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
986
987 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
988 {
989 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
990 }
991
992 if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
993 {
994 return error(GL_INVALID_OPERATION);
995 }
996
997 es2::Renderbuffer *source = framebuffer->getColorbuffer();
998 GLenum colorbufferFormat = source->getFormat();
999
1000 // [OpenGL ES 2.0.24] table 3.9
1001 switch(internalformat)
1002 {
1003 case GL_ALPHA:
1004 if(colorbufferFormat != GL_ALPHA &&
1005 colorbufferFormat != GL_RGBA &&
1006 colorbufferFormat != GL_RGBA4 &&
1007 colorbufferFormat != GL_RGB5_A1 &&
1008 colorbufferFormat != GL_RGBA8_OES)
1009 {
1010 return error(GL_INVALID_OPERATION);
1011 }
1012 break;
1013 case GL_LUMINANCE:
1014 case GL_RGB:
1015 if(colorbufferFormat != GL_RGB &&
1016 colorbufferFormat != GL_RGB565 &&
1017 colorbufferFormat != GL_RGB8_OES &&
1018 colorbufferFormat != GL_RGBA &&
1019 colorbufferFormat != GL_RGBA4 &&
1020 colorbufferFormat != GL_RGB5_A1 &&
1021 colorbufferFormat != GL_RGBA8_OES)
1022 {
1023 return error(GL_INVALID_OPERATION);
1024 }
1025 break;
1026 case GL_LUMINANCE_ALPHA:
1027 case GL_RGBA:
1028 if(colorbufferFormat != GL_RGBA &&
1029 colorbufferFormat != GL_RGBA4 &&
1030 colorbufferFormat != GL_RGB5_A1 &&
1031 colorbufferFormat != GL_RGBA8_OES)
1032 {
1033 return error(GL_INVALID_OPERATION);
1034 }
1035 break;
1036 case GL_ETC1_RGB8_OES:
1037 return error(GL_INVALID_OPERATION);
1038 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1039 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1040 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1041 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1042 if(S3TC_SUPPORT)
1043 {
1044 return error(GL_INVALID_OPERATION);
1045 }
1046 else
1047 {
1048 return error(GL_INVALID_ENUM);
1049 }
1050 default:
1051 return error(GL_INVALID_ENUM);
1052 }
1053
1054 if(target == GL_TEXTURE_2D)
1055 {
1056 es2::Texture2D *texture = context->getTexture2D();
1057
1058 if(!texture)
1059 {
1060 return error(GL_INVALID_OPERATION);
1061 }
1062
1063 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
1064 }
1065 else if(es2::IsCubemapTextureTarget(target))
1066 {
1067 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1068
1069 if(!texture)
1070 {
1071 return error(GL_INVALID_OPERATION);
1072 }
1073
1074 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1075 }
1076 else UNREACHABLE();
1077 }
1078}
1079
1080void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1081{
1082 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1083 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1084 target, level, xoffset, yoffset, x, y, width, height);
1085
1086 if(!es2::IsTextureTarget(target))
1087 {
1088 return error(GL_INVALID_ENUM);
1089 }
1090
1091 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1092 {
1093 return error(GL_INVALID_VALUE);
1094 }
1095
1096 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1097 {
1098 return error(GL_INVALID_VALUE);
1099 }
1100
1101 if(width == 0 || height == 0)
1102 {
1103 return;
1104 }
1105
1106 es2::Context *context = es2::getContext();
1107
1108 if(context)
1109 {
1110 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1111 {
1112 return error(GL_INVALID_VALUE);
1113 }
1114
1115 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1116
1117 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1118 {
1119 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1120 }
1121
1122 if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
1123 {
1124 return error(GL_INVALID_OPERATION);
1125 }
1126
1127 es2::Renderbuffer *source = framebuffer->getColorbuffer();
1128 GLenum colorbufferFormat = source->getFormat();
1129 es2::Texture *texture = NULL;
1130
1131 if(target == GL_TEXTURE_2D)
1132 {
1133 texture = context->getTexture2D();
1134 }
1135 else if(es2::IsCubemapTextureTarget(target))
1136 {
1137 texture = context->getTextureCubeMap();
1138 }
1139 else UNREACHABLE();
1140
1141 if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture))
1142 {
1143 return;
1144 }
1145
1146 GLenum textureFormat = texture->getFormat(target, level);
1147
1148 // [OpenGL ES 2.0.24] table 3.9
1149 switch(textureFormat)
1150 {
1151 case GL_ALPHA:
1152 if(colorbufferFormat != GL_ALPHA &&
1153 colorbufferFormat != GL_RGBA &&
1154 colorbufferFormat != GL_RGBA4 &&
1155 colorbufferFormat != GL_RGB5_A1 &&
1156 colorbufferFormat != GL_RGBA8_OES)
1157 {
1158 return error(GL_INVALID_OPERATION);
1159 }
1160 break;
1161 case GL_LUMINANCE:
1162 case GL_RGB:
1163 if(colorbufferFormat != GL_RGB &&
1164 colorbufferFormat != GL_RGB565 &&
1165 colorbufferFormat != GL_RGB8_OES &&
1166 colorbufferFormat != GL_RGBA &&
1167 colorbufferFormat != GL_RGBA4 &&
1168 colorbufferFormat != GL_RGB5_A1 &&
1169 colorbufferFormat != GL_RGBA8_OES)
1170 {
1171 return error(GL_INVALID_OPERATION);
1172 }
1173 break;
1174 case GL_LUMINANCE_ALPHA:
1175 case GL_RGBA:
1176 if(colorbufferFormat != GL_RGBA &&
1177 colorbufferFormat != GL_RGBA4 &&
1178 colorbufferFormat != GL_RGB5_A1 &&
1179 colorbufferFormat != GL_RGBA8_OES)
1180 {
1181 return error(GL_INVALID_OPERATION);
1182 }
1183 break;
1184 case GL_ETC1_RGB8_OES:
1185 return error(GL_INVALID_OPERATION);
1186 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1187 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1188 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1189 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1190 if(S3TC_SUPPORT)
1191 {
1192 return error(GL_INVALID_OPERATION);
1193 }
1194 else
1195 {
1196 return error(GL_INVALID_ENUM);
1197 }
1198 case GL_DEPTH_COMPONENT:
1199 case GL_DEPTH_STENCIL_OES:
1200 return error(GL_INVALID_OPERATION);
1201 default:
1202 return error(GL_INVALID_ENUM);
1203 }
1204
1205 texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
1206 }
1207}
1208
1209GLuint GL_APIENTRY glCreateProgram(void)
1210{
1211 TRACE("()");
1212
1213 es2::Context *context = es2::getContext();
1214
1215 if(context)
1216 {
1217 return context->createProgram();
1218 }
1219
1220 return 0;
1221}
1222
1223GLuint GL_APIENTRY glCreateShader(GLenum type)
1224{
1225 TRACE("(GLenum type = 0x%X)", type);
1226
1227 es2::Context *context = es2::getContext();
1228
1229 if(context)
1230 {
1231 switch(type)
1232 {
1233 case GL_FRAGMENT_SHADER:
1234 case GL_VERTEX_SHADER:
1235 return context->createShader(type);
1236 default:
1237 return error(GL_INVALID_ENUM, 0);
1238 }
1239 }
1240
1241 return 0;
1242}
1243
1244void GL_APIENTRY glCullFace(GLenum mode)
1245{
1246 TRACE("(GLenum mode = 0x%X)", mode);
1247
1248 switch(mode)
1249 {
1250 case GL_FRONT:
1251 case GL_BACK:
1252 case GL_FRONT_AND_BACK:
1253 {
1254 es2::Context *context = es2::getContext();
1255
1256 if(context)
1257 {
1258 context->setCullMode(mode);
1259 }
1260 }
1261 break;
1262 default:
1263 return error(GL_INVALID_ENUM);
1264 }
1265}
1266
1267void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
1268{
1269 TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
1270
1271 if(n < 0)
1272 {
1273 return error(GL_INVALID_VALUE);
1274 }
1275
1276 es2::Context *context = es2::getContext();
1277
1278 if(context)
1279 {
1280 for(int i = 0; i < n; i++)
1281 {
1282 context->deleteBuffer(buffers[i]);
1283 }
1284 }
1285}
1286
1287void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
1288{
1289 TRACE("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
1290
1291 if(n < 0)
1292 {
1293 return error(GL_INVALID_VALUE);
1294 }
1295
1296 es2::Context *context = es2::getContext();
1297
1298 if(context)
1299 {
1300 for(int i = 0; i < n; i++)
1301 {
1302 context->deleteFence(fences[i]);
1303 }
1304 }
1305}
1306
1307void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1308{
1309 TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
1310
1311 if(n < 0)
1312 {
1313 return error(GL_INVALID_VALUE);
1314 }
1315
1316 es2::Context *context = es2::getContext();
1317
1318 if(context)
1319 {
1320 for(int i = 0; i < n; i++)
1321 {
1322 if(framebuffers[i] != 0)
1323 {
1324 context->deleteFramebuffer(framebuffers[i]);
1325 }
1326 }
1327 }
1328}
1329
1330void GL_APIENTRY glDeleteProgram(GLuint program)
1331{
1332 TRACE("(GLuint program = %d)", program);
1333
1334 if(program == 0)
1335 {
1336 return;
1337 }
1338
1339 es2::Context *context = es2::getContext();
1340
1341 if(context)
1342 {
1343 if(!context->getProgram(program))
1344 {
1345 if(context->getShader(program))
1346 {
1347 return error(GL_INVALID_OPERATION);
1348 }
1349 else
1350 {
1351 return error(GL_INVALID_VALUE);
1352 }
1353 }
1354
1355 context->deleteProgram(program);
1356 }
1357}
1358
1359void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
1360{
1361 TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
1362
1363 if(n < 0)
1364 {
1365 return error(GL_INVALID_VALUE);
1366 }
1367
1368 es2::Context *context = es2::getContext();
1369
1370 if(context)
1371 {
1372 for(int i = 0; i < n; i++)
1373 {
1374 context->deleteQuery(ids[i]);
1375 }
1376 }
1377}
1378
1379void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1380{
1381 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
1382
1383 if(n < 0)
1384 {
1385 return error(GL_INVALID_VALUE);
1386 }
1387
1388 es2::Context *context = es2::getContext();
1389
1390 if(context)
1391 {
1392 for(int i = 0; i < n; i++)
1393 {
1394 context->deleteRenderbuffer(renderbuffers[i]);
1395 }
1396 }
1397}
1398
1399void GL_APIENTRY glDeleteShader(GLuint shader)
1400{
1401 TRACE("(GLuint shader = %d)", shader);
1402
1403 if(shader == 0)
1404 {
1405 return;
1406 }
1407
1408 es2::Context *context = es2::getContext();
1409
1410 if(context)
1411 {
1412 if(!context->getShader(shader))
1413 {
1414 if(context->getProgram(shader))
1415 {
1416 return error(GL_INVALID_OPERATION);
1417 }
1418 else
1419 {
1420 return error(GL_INVALID_VALUE);
1421 }
1422 }
1423
1424 context->deleteShader(shader);
1425 }
1426}
1427
1428void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
1429{
1430 TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
1431
1432 if(n < 0)
1433 {
1434 return error(GL_INVALID_VALUE);
1435 }
1436
1437 es2::Context *context = es2::getContext();
1438
1439 if(context)
1440 {
1441 for(int i = 0; i < n; i++)
1442 {
1443 if(textures[i] != 0)
1444 {
1445 context->deleteTexture(textures[i]);
1446 }
1447 }
1448 }
1449}
1450
1451void GL_APIENTRY glDepthFunc(GLenum func)
1452{
1453 TRACE("(GLenum func = 0x%X)", func);
1454
1455 switch(func)
1456 {
1457 case GL_NEVER:
1458 case GL_ALWAYS:
1459 case GL_LESS:
1460 case GL_LEQUAL:
1461 case GL_EQUAL:
1462 case GL_GREATER:
1463 case GL_GEQUAL:
1464 case GL_NOTEQUAL:
1465 break;
1466 default:
1467 return error(GL_INVALID_ENUM);
1468 }
1469
1470 es2::Context *context = es2::getContext();
1471
1472 if(context)
1473 {
1474 context->setDepthFunc(func);
1475 }
1476}
1477
1478void GL_APIENTRY glDepthMask(GLboolean flag)
1479{
1480 TRACE("(GLboolean flag = %d)", flag);
1481
1482 es2::Context *context = es2::getContext();
1483
1484 if(context)
1485 {
1486 context->setDepthMask(flag != GL_FALSE);
1487 }
1488}
1489
1490void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)
1491{
1492 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1493
1494 es2::Context *context = es2::getContext();
1495
1496 if(context)
1497 {
1498 context->setDepthRange(zNear, zFar);
1499 }
1500}
1501
1502void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
1503{
1504 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1505
1506 es2::Context *context = es2::getContext();
1507
1508 if(context)
1509 {
1510
1511 es2::Program *programObject = context->getProgram(program);
1512 es2::Shader *shaderObject = context->getShader(shader);
1513
1514 if(!programObject)
1515 {
1516 es2::Shader *shaderByProgramHandle;
1517 shaderByProgramHandle = context->getShader(program);
1518 if(!shaderByProgramHandle)
1519 {
1520 return error(GL_INVALID_VALUE);
1521 }
1522 else
1523 {
1524 return error(GL_INVALID_OPERATION);
1525 }
1526 }
1527
1528 if(!shaderObject)
1529 {
1530 es2::Program *programByShaderHandle = context->getProgram(shader);
1531 if(!programByShaderHandle)
1532 {
1533 return error(GL_INVALID_VALUE);
1534 }
1535 else
1536 {
1537 return error(GL_INVALID_OPERATION);
1538 }
1539 }
1540
1541 if(!programObject->detachShader(shaderObject))
1542 {
1543 return error(GL_INVALID_OPERATION);
1544 }
1545 }
1546}
1547
1548void GL_APIENTRY glDisable(GLenum cap)
1549{
1550 TRACE("(GLenum cap = 0x%X)", cap);
1551
1552 es2::Context *context = es2::getContext();
1553
1554 if(context)
1555 {
1556 switch(cap)
1557 {
1558 case GL_CULL_FACE: context->setCullFace(false); break;
1559 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
1560 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
1561 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
1562 case GL_SCISSOR_TEST: context->setScissorTest(false); break;
1563 case GL_STENCIL_TEST: context->setStencilTest(false); break;
1564 case GL_DEPTH_TEST: context->setDepthTest(false); break;
1565 case GL_BLEND: context->setBlend(false); break;
1566 case GL_DITHER: context->setDither(false); break;
1567 default:
1568 return error(GL_INVALID_ENUM);
1569 }
1570 }
1571}
1572
1573void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
1574{
1575 TRACE("(GLuint index = %d)", index);
1576
1577 if(index >= es2::MAX_VERTEX_ATTRIBS)
1578 {
1579 return error(GL_INVALID_VALUE);
1580 }
1581
1582 es2::Context *context = es2::getContext();
1583
1584 if(context)
1585 {
1586 context->setEnableVertexAttribArray(index, false);
1587 }
1588}
1589
1590void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
1591{
1592 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1593
1594 if(count < 0 || first < 0)
1595 {
1596 return error(GL_INVALID_VALUE);
1597 }
1598
1599 es2::Context *context = es2::getContext();
1600
1601 if(context)
1602 {
1603 context->drawArrays(mode, first, count);
1604 }
1605}
1606
1607void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1608{
1609 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
1610 mode, count, type, indices);
1611
1612 if(count < 0)
1613 {
1614 return error(GL_INVALID_VALUE);
1615 }
1616
1617 es2::Context *context = es2::getContext();
1618
1619 if(context)
1620 {
1621 switch(type)
1622 {
1623 case GL_UNSIGNED_BYTE:
1624 case GL_UNSIGNED_SHORT:
1625 case GL_UNSIGNED_INT:
1626 break;
1627 default:
1628 return error(GL_INVALID_ENUM);
1629 }
1630
1631 context->drawElements(mode, count, type, indices);
1632 }
1633}
1634
1635void GL_APIENTRY glEnable(GLenum cap)
1636{
1637 TRACE("(GLenum cap = 0x%X)", cap);
1638
1639 es2::Context *context = es2::getContext();
1640
1641 if(context)
1642 {
1643 switch(cap)
1644 {
1645 case GL_CULL_FACE: context->setCullFace(true); break;
1646 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break;
1647 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
1648 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break;
1649 case GL_SCISSOR_TEST: context->setScissorTest(true); break;
1650 case GL_STENCIL_TEST: context->setStencilTest(true); break;
1651 case GL_DEPTH_TEST: context->setDepthTest(true); break;
1652 case GL_BLEND: context->setBlend(true); break;
1653 case GL_DITHER: context->setDither(true); break;
1654 default:
1655 return error(GL_INVALID_ENUM);
1656 }
1657 }
1658}
1659
1660void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
1661{
1662 TRACE("(GLuint index = %d)", index);
1663
1664 if(index >= es2::MAX_VERTEX_ATTRIBS)
1665 {
1666 return error(GL_INVALID_VALUE);
1667 }
1668
1669 es2::Context *context = es2::getContext();
1670
1671 if(context)
1672 {
1673 context->setEnableVertexAttribArray(index, true);
1674 }
1675}
1676
1677void GL_APIENTRY glEndQueryEXT(GLenum target)
1678{
1679 TRACE("GLenum target = 0x%X)", target);
1680
1681 switch(target)
1682 {
1683 case GL_ANY_SAMPLES_PASSED_EXT:
1684 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1685 break;
1686 default:
1687 return error(GL_INVALID_ENUM);
1688 }
1689
1690 es2::Context *context = es2::getContext();
1691
1692 if(context)
1693 {
1694 context->endQuery(target);
1695 }
1696}
1697
1698void GL_APIENTRY glFinishFenceNV(GLuint fence)
1699{
1700 TRACE("(GLuint fence = %d)", fence);
1701
1702 es2::Context *context = es2::getContext();
1703
1704 if(context)
1705 {
1706 es2::Fence* fenceObject = context->getFence(fence);
1707
1708 if(fenceObject == NULL)
1709 {
1710 return error(GL_INVALID_OPERATION);
1711 }
1712
1713 fenceObject->finishFence();
1714 }
1715}
1716
1717void GL_APIENTRY glFinish(void)
1718{
1719 TRACE("()");
1720
1721 es2::Context *context = es2::getContext();
1722
1723 if(context)
1724 {
1725 context->finish();
1726 }
1727}
1728
1729void GL_APIENTRY glFlush(void)
1730{
1731 TRACE("()");
1732
1733 es2::Context *context = es2::getContext();
1734
1735 if(context)
1736 {
1737 context->flush();
1738 }
1739}
1740
1741void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1742{
1743 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1744 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1745
1746 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) ||
1747 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1748 {
1749 return error(GL_INVALID_ENUM);
1750 }
1751
1752 es2::Context *context = es2::getContext();
1753
1754 if(context)
1755 {
1756 es2::Framebuffer *framebuffer = NULL;
1757 GLuint framebufferHandle = 0;
1758 if(target == GL_READ_FRAMEBUFFER_ANGLE)
1759 {
1760 framebuffer = context->getReadFramebuffer();
1761 framebufferHandle = context->getReadFramebufferHandle();
1762 }
1763 else
1764 {
1765 framebuffer = context->getDrawFramebuffer();
1766 framebufferHandle = context->getDrawFramebufferHandle();
1767 }
1768
1769 if(!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
1770 {
1771 return error(GL_INVALID_OPERATION);
1772 }
1773
1774 switch(attachment)
1775 {
1776 case GL_COLOR_ATTACHMENT0:
1777 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
1778 break;
1779 case GL_DEPTH_ATTACHMENT:
1780 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1781 break;
1782 case GL_STENCIL_ATTACHMENT:
1783 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1784 break;
1785 default:
1786 return error(GL_INVALID_ENUM);
1787 }
1788 }
1789}
1790
1791void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1792{
1793 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1794 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1795
1796 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
1797 {
1798 return error(GL_INVALID_ENUM);
1799 }
1800
1801 switch(attachment)
1802 {
1803 case GL_COLOR_ATTACHMENT0:
1804 case GL_DEPTH_ATTACHMENT:
1805 case GL_STENCIL_ATTACHMENT:
1806 break;
1807 default:
1808 return error(GL_INVALID_ENUM);
1809 }
1810
1811 es2::Context *context = es2::getContext();
1812
1813 if(context)
1814 {
1815 if(texture == 0)
1816 {
1817 textarget = GL_NONE;
1818 }
1819 else
1820 {
1821 es2::Texture *tex = context->getTexture(texture);
1822
1823 if(tex == NULL)
1824 {
1825 return error(GL_INVALID_OPERATION);
1826 }
1827
1828 if(tex->isCompressed(textarget, level))
1829 {
1830 return error(GL_INVALID_OPERATION);
1831 }
1832
1833 switch(textarget)
1834 {
1835 case GL_TEXTURE_2D:
1836 if(tex->getTarget() != GL_TEXTURE_2D)
1837 {
1838 return error(GL_INVALID_OPERATION);
1839 }
1840 break;
1841 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1842 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1843 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1844 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1845 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1846 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1847 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1848 {
1849 return error(GL_INVALID_OPERATION);
1850 }
1851 break;
1852 default:
1853 return error(GL_INVALID_ENUM);
1854 }
1855
1856 if(level != 0)
1857 {
1858 return error(GL_INVALID_VALUE);
1859 }
1860 }
1861
1862 es2::Framebuffer *framebuffer = NULL;
1863 GLuint framebufferHandle = 0;
1864 if(target == GL_READ_FRAMEBUFFER_ANGLE)
1865 {
1866 framebuffer = context->getReadFramebuffer();
1867 framebufferHandle = context->getReadFramebufferHandle();
1868 }
1869 else
1870 {
1871 framebuffer = context->getDrawFramebuffer();
1872 framebufferHandle = context->getDrawFramebufferHandle();
1873 }
1874
1875 if(framebufferHandle == 0 || !framebuffer)
1876 {
1877 return error(GL_INVALID_OPERATION);
1878 }
1879
1880 switch(attachment)
1881 {
1882 case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break;
1883 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
1884 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
1885 }
1886 }
1887}
1888
1889void GL_APIENTRY glFrontFace(GLenum mode)
1890{
1891 TRACE("(GLenum mode = 0x%X)", mode);
1892
1893 switch(mode)
1894 {
1895 case GL_CW:
1896 case GL_CCW:
1897 {
1898 es2::Context *context = es2::getContext();
1899
1900 if(context)
1901 {
1902 context->setFrontFace(mode);
1903 }
1904 }
1905 break;
1906 default:
1907 return error(GL_INVALID_ENUM);
1908 }
1909}
1910
1911void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
1912{
1913 TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
1914
1915 if(n < 0)
1916 {
1917 return error(GL_INVALID_VALUE);
1918 }
1919
1920 es2::Context *context = es2::getContext();
1921
1922 if(context)
1923 {
1924 for(int i = 0; i < n; i++)
1925 {
1926 buffers[i] = context->createBuffer();
1927 }
1928 }
1929}
1930
1931void GL_APIENTRY glGenerateMipmap(GLenum target)
1932{
1933 TRACE("(GLenum target = 0x%X)", target);
1934
1935 es2::Context *context = es2::getContext();
1936
1937 if(context)
1938 {
1939 es2::Texture *texture;
1940
1941 switch(target)
1942 {
1943 case GL_TEXTURE_2D:
1944 texture = context->getTexture2D();
1945 break;
1946 case GL_TEXTURE_CUBE_MAP:
1947 texture = context->getTextureCubeMap();
1948 break;
1949 default:
1950 return error(GL_INVALID_ENUM);
1951 }
1952
1953 if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
1954 {
1955 return error(GL_INVALID_OPERATION);
1956 }
1957
1958 texture->generateMipmaps();
1959 }
1960}
1961
1962void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
1963{
1964 TRACE("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
1965
1966 if(n < 0)
1967 {
1968 return error(GL_INVALID_VALUE);
1969 }
1970
1971 es2::Context *context = es2::getContext();
1972
1973 if(context)
1974 {
1975 for(int i = 0; i < n; i++)
1976 {
1977 fences[i] = context->createFence();
1978 }
1979 }
1980}
1981
1982void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
1983{
1984 TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
1985
1986 if(n < 0)
1987 {
1988 return error(GL_INVALID_VALUE);
1989 }
1990
1991 es2::Context *context = es2::getContext();
1992
1993 if(context)
1994 {
1995 for(int i = 0; i < n; i++)
1996 {
1997 framebuffers[i] = context->createFramebuffer();
1998 }
1999 }
2000}
2001
2002void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)
2003{
2004 TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
2005
2006 if(n < 0)
2007 {
2008 return error(GL_INVALID_VALUE);
2009 }
2010
2011 es2::Context *context = es2::getContext();
2012
2013 if(context)
2014 {
2015 for(int i = 0; i < n; i++)
2016 {
2017 ids[i] = context->createQuery();
2018 }
2019 }
2020}
2021
2022void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2023{
2024 TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
2025
2026 if(n < 0)
2027 {
2028 return error(GL_INVALID_VALUE);
2029 }
2030
2031 es2::Context *context = es2::getContext();
2032
2033 if(context)
2034 {
2035 for(int i = 0; i < n; i++)
2036 {
2037 renderbuffers[i] = context->createRenderbuffer();
2038 }
2039 }
2040}
2041
2042void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
2043{
2044 TRACE("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
2045
2046 if(n < 0)
2047 {
2048 return error(GL_INVALID_VALUE);
2049 }
2050
2051 es2::Context *context = es2::getContext();
2052
2053 if(context)
2054 {
2055 for(int i = 0; i < n; i++)
2056 {
2057 textures[i] = context->createTexture();
2058 }
2059 }
2060}
2061
2062void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2063{
2064 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
2065 "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
2066 program, index, bufsize, length, size, type, name);
2067
2068 if(bufsize < 0)
2069 {
2070 return error(GL_INVALID_VALUE);
2071 }
2072
2073 es2::Context *context = es2::getContext();
2074
2075 if(context)
2076 {
2077 es2::Program *programObject = context->getProgram(program);
2078
2079 if(!programObject)
2080 {
2081 if(context->getShader(program))
2082 {
2083 return error(GL_INVALID_OPERATION);
2084 }
2085 else
2086 {
2087 return error(GL_INVALID_VALUE);
2088 }
2089 }
2090
2091 if(index >= (GLuint)programObject->getActiveAttributeCount())
2092 {
2093 return error(GL_INVALID_VALUE);
2094 }
2095
2096 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2097 }
2098}
2099
2100void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2101{
2102 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2103 "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = %s)",
2104 program, index, bufsize, length, size, type, name);
2105
2106 if(bufsize < 0)
2107 {
2108 return error(GL_INVALID_VALUE);
2109 }
2110
2111 es2::Context *context = es2::getContext();
2112
2113 if(context)
2114 {
2115 es2::Program *programObject = context->getProgram(program);
2116
2117 if(!programObject)
2118 {
2119 if(context->getShader(program))
2120 {
2121 return error(GL_INVALID_OPERATION);
2122 }
2123 else
2124 {
2125 return error(GL_INVALID_VALUE);
2126 }
2127 }
2128
2129 if(index >= (GLuint)programObject->getActiveUniformCount())
2130 {
2131 return error(GL_INVALID_VALUE);
2132 }
2133
2134 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2135 }
2136}
2137
2138void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2139{
2140 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
2141 program, maxcount, count, shaders);
2142
2143 if(maxcount < 0)
2144 {
2145 return error(GL_INVALID_VALUE);
2146 }
2147
2148 es2::Context *context = es2::getContext();
2149
2150 if(context)
2151 {
2152 es2::Program *programObject = context->getProgram(program);
2153
2154 if(!programObject)
2155 {
2156 if(context->getShader(program))
2157 {
2158 return error(GL_INVALID_OPERATION);
2159 }
2160 else
2161 {
2162 return error(GL_INVALID_VALUE);
2163 }
2164 }
2165
2166 return programObject->getAttachedShaders(maxcount, count, shaders);
2167 }
2168}
2169
2170int GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
2171{
2172 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2173
2174 es2::Context *context = es2::getContext();
2175
2176 if(context)
2177 {
2178
2179 es2::Program *programObject = context->getProgram(program);
2180
2181 if(!programObject)
2182 {
2183 if(context->getShader(program))
2184 {
2185 return error(GL_INVALID_OPERATION, -1);
2186 }
2187 else
2188 {
2189 return error(GL_INVALID_VALUE, -1);
2190 }
2191 }
2192
2193 if(!programObject->isLinked())
2194 {
2195 return error(GL_INVALID_OPERATION, -1);
2196 }
2197
2198 return programObject->getAttributeLocation(name);
2199 }
2200
2201 return -1;
2202}
2203
2204void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
2205{
2206 TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
2207
2208 es2::Context *context = es2::getContext();
2209
2210 if(context)
2211 {
2212 if(!(context->getBooleanv(pname, params)))
2213 {
2214 GLenum nativeType;
2215 unsigned int numParams = 0;
2216 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2217 return error(GL_INVALID_ENUM);
2218
2219 if(numParams == 0)
2220 return; // it is known that the pname is valid, but there are no parameters to return
2221
2222 if(nativeType == GL_FLOAT)
2223 {
2224 GLfloat *floatParams = NULL;
2225 floatParams = new GLfloat[numParams];
2226
2227 context->getFloatv(pname, floatParams);
2228
2229 for(unsigned int i = 0; i < numParams; ++i)
2230 {
2231 if(floatParams[i] == 0.0f)
2232 params[i] = GL_FALSE;
2233 else
2234 params[i] = GL_TRUE;
2235 }
2236
2237 delete [] floatParams;
2238 }
2239 else if(nativeType == GL_INT)
2240 {
2241 GLint *intParams = NULL;
2242 intParams = new GLint[numParams];
2243
2244 context->getIntegerv(pname, intParams);
2245
2246 for(unsigned int i = 0; i < numParams; ++i)
2247 {
2248 if(intParams[i] == 0)
2249 params[i] = GL_FALSE;
2250 else
2251 params[i] = GL_TRUE;
2252 }
2253
2254 delete [] intParams;
2255 }
2256 }
2257 }
2258}
2259
2260void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2261{
2262 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
2263
2264 es2::Context *context = es2::getContext();
2265
2266 if(context)
2267 {
2268 es2::Buffer *buffer;
2269
2270 switch(target)
2271 {
2272 case GL_ARRAY_BUFFER:
2273 buffer = context->getArrayBuffer();
2274 break;
2275 case GL_ELEMENT_ARRAY_BUFFER:
2276 buffer = context->getElementArrayBuffer();
2277 break;
2278 default:
2279 return error(GL_INVALID_ENUM);
2280 }
2281
2282 if(!buffer)
2283 {
2284 // A null buffer means that "0" is bound to the requested buffer target
2285 return error(GL_INVALID_OPERATION);
2286 }
2287
2288 switch(pname)
2289 {
2290 case GL_BUFFER_USAGE:
2291 *params = buffer->usage();
2292 break;
2293 case GL_BUFFER_SIZE:
2294 *params = buffer->size();
2295 break;
2296 default:
2297 return error(GL_INVALID_ENUM);
2298 }
2299 }
2300}
2301
2302GLenum GL_APIENTRY glGetError(void)
2303{
2304 TRACE("()");
2305
2306 es2::Context *context = es2::getContext();
2307
2308 if(context)
2309 {
2310 return context->getError();
2311 }
2312
2313 return GL_NO_ERROR;
2314}
2315
2316void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2317{
2318 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
2319
2320 es2::Context *context = es2::getContext();
2321
2322 if(context)
2323 {
2324 es2::Fence *fenceObject = context->getFence(fence);
2325
2326 if(fenceObject == NULL)
2327 {
2328 return error(GL_INVALID_OPERATION);
2329 }
2330
2331 fenceObject->getFenceiv(pname, params);
2332 }
2333}
2334
2335void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
2336{
2337 TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
2338
2339 es2::Context *context = es2::getContext();
2340
2341 if(context)
2342 {
2343 if(!(context->getFloatv(pname, params)))
2344 {
2345 GLenum nativeType;
2346 unsigned int numParams = 0;
2347 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2348 return error(GL_INVALID_ENUM);
2349
2350 if(numParams == 0)
2351 return; // it is known that the pname is valid, but that there are no parameters to return.
2352
2353 if(nativeType == GL_BOOL)
2354 {
2355 GLboolean *boolParams = NULL;
2356 boolParams = new GLboolean[numParams];
2357
2358 context->getBooleanv(pname, boolParams);
2359
2360 for(unsigned int i = 0; i < numParams; ++i)
2361 {
2362 if(boolParams[i] == GL_FALSE)
2363 params[i] = 0.0f;
2364 else
2365 params[i] = 1.0f;
2366 }
2367
2368 delete [] boolParams;
2369 }
2370 else if(nativeType == GL_INT)
2371 {
2372 GLint *intParams = NULL;
2373 intParams = new GLint[numParams];
2374
2375 context->getIntegerv(pname, intParams);
2376
2377 for(unsigned int i = 0; i < numParams; ++i)
2378 {
2379 params[i] = (GLfloat)intParams[i];
2380 }
2381
2382 delete [] intParams;
2383 }
2384 }
2385 }
2386}
2387
2388void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2389{
2390 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
2391 target, attachment, pname, params);
2392
2393 es2::Context *context = es2::getContext();
2394
2395 if(context)
2396 {
2397 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2398 {
2399 return error(GL_INVALID_ENUM);
2400 }
2401
2402 es2::Framebuffer *framebuffer = NULL;
2403 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2404 {
2405 if(context->getReadFramebufferHandle() == 0)
2406 {
2407 return error(GL_INVALID_OPERATION);
2408 }
2409
2410 framebuffer = context->getReadFramebuffer();
2411 }
2412 else
2413 {
2414 if(context->getDrawFramebufferHandle() == 0)
2415 {
2416 return error(GL_INVALID_OPERATION);
2417 }
2418
2419 framebuffer = context->getDrawFramebuffer();
2420 }
2421
2422 GLenum attachmentType;
2423 GLuint attachmentHandle;
2424 switch(attachment)
2425 {
2426 case GL_COLOR_ATTACHMENT0:
2427 attachmentType = framebuffer->getColorbufferType();
2428 attachmentHandle = framebuffer->getColorbufferHandle();
2429 break;
2430 case GL_DEPTH_ATTACHMENT:
2431 attachmentType = framebuffer->getDepthbufferType();
2432 attachmentHandle = framebuffer->getDepthbufferHandle();
2433 break;
2434 case GL_STENCIL_ATTACHMENT:
2435 attachmentType = framebuffer->getStencilbufferType();
2436 attachmentHandle = framebuffer->getStencilbufferHandle();
2437 break;
2438 default:
2439 return error(GL_INVALID_ENUM);
2440 }
2441
2442 GLenum attachmentObjectType; // Type category
2443 if(attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
2444 {
2445 attachmentObjectType = attachmentType;
2446 }
2447 else if(es2::IsTextureTarget(attachmentType))
2448 {
2449 attachmentObjectType = GL_TEXTURE;
2450 }
2451 else UNREACHABLE();
2452
2453 switch(pname)
2454 {
2455 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2456 *params = attachmentObjectType;
2457 break;
2458 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2459 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
2460 {
2461 *params = attachmentHandle;
2462 }
2463 else
2464 {
2465 return error(GL_INVALID_ENUM);
2466 }
2467 break;
2468 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2469 if(attachmentObjectType == GL_TEXTURE)
2470 {
2471 *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
2472 }
2473 else
2474 {
2475 return error(GL_INVALID_ENUM);
2476 }
2477 break;
2478 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2479 if(attachmentObjectType == GL_TEXTURE)
2480 {
2481 if(es2::IsCubemapTextureTarget(attachmentType))
2482 {
2483 *params = attachmentType;
2484 }
2485 else
2486 {
2487 *params = 0;
2488 }
2489 }
2490 else
2491 {
2492 return error(GL_INVALID_ENUM);
2493 }
2494 break;
2495 default:
2496 return error(GL_INVALID_ENUM);
2497 }
2498 }
2499}
2500
2501GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
2502{
2503 TRACE("()");
2504
2505 return GL_NO_ERROR;
2506}
2507
2508void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
2509{
2510 TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
2511
2512 es2::Context *context = es2::getContext();
2513
2514 if(context)
2515 {
2516 if(!(context->getIntegerv(pname, params)))
2517 {
2518 GLenum nativeType;
2519 unsigned int numParams = 0;
2520 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2521 return error(GL_INVALID_ENUM);
2522
2523 if(numParams == 0)
2524 return; // it is known that pname is valid, but there are no parameters to return
2525
2526 if(nativeType == GL_BOOL)
2527 {
2528 GLboolean *boolParams = NULL;
2529 boolParams = new GLboolean[numParams];
2530
2531 context->getBooleanv(pname, boolParams);
2532
2533 for(unsigned int i = 0; i < numParams; ++i)
2534 {
2535 if(boolParams[i] == GL_FALSE)
2536 params[i] = 0;
2537 else
2538 params[i] = 1;
2539 }
2540
2541 delete [] boolParams;
2542 }
2543 else if(nativeType == GL_FLOAT)
2544 {
2545 GLfloat *floatParams = NULL;
2546 floatParams = new GLfloat[numParams];
2547
2548 context->getFloatv(pname, floatParams);
2549
2550 for(unsigned int i = 0; i < numParams; ++i)
2551 {
2552 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2553 {
2554 params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
2555 }
2556 else
2557 {
2558 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2559 }
2560 }
2561
2562 delete [] floatParams;
2563 }
2564 }
2565 }
2566}
2567
2568void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
2569{
2570 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, pname, params);
2571
2572 es2::Context *context = es2::getContext();
2573
2574 if(context)
2575 {
2576 es2::Program *programObject = context->getProgram(program);
2577
2578 if(!programObject)
2579 {
2580 return error(GL_INVALID_VALUE);
2581 }
2582
2583 switch(pname)
2584 {
2585 case GL_DELETE_STATUS:
2586 *params = programObject->isFlaggedForDeletion();
2587 return;
2588 case GL_LINK_STATUS:
2589 *params = programObject->isLinked();
2590 return;
2591 case GL_VALIDATE_STATUS:
2592 *params = programObject->isValidated();
2593 return;
2594 case GL_INFO_LOG_LENGTH:
2595 *params = programObject->getInfoLogLength();
2596 return;
2597 case GL_ATTACHED_SHADERS:
2598 *params = programObject->getAttachedShadersCount();
2599 return;
2600 case GL_ACTIVE_ATTRIBUTES:
2601 *params = programObject->getActiveAttributeCount();
2602 return;
2603 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2604 *params = programObject->getActiveAttributeMaxLength();
2605 return;
2606 case GL_ACTIVE_UNIFORMS:
2607 *params = programObject->getActiveUniformCount();
2608 return;
2609 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2610 *params = programObject->getActiveUniformMaxLength();
2611 return;
2612 default:
2613 return error(GL_INVALID_ENUM);
2614 }
2615 }
2616}
2617
2618void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2619{
2620 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
2621 program, bufsize, length, infolog);
2622
2623 if(bufsize < 0)
2624 {
2625 return error(GL_INVALID_VALUE);
2626 }
2627
2628 es2::Context *context = es2::getContext();
2629
2630 if(context)
2631 {
2632 es2::Program *programObject = context->getProgram(program);
2633
2634 if(!programObject)
2635 {
2636 return error(GL_INVALID_VALUE);
2637 }
2638
2639 programObject->getInfoLog(bufsize, length, infolog);
2640 }
2641}
2642
2643void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2644{
2645 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
2646
2647 switch(pname)
2648 {
2649 case GL_CURRENT_QUERY_EXT:
2650 break;
2651 default:
2652 return error(GL_INVALID_ENUM);
2653 }
2654
2655 es2::Context *context = es2::getContext();
2656
2657 if(context)
2658 {
2659 params[0] = context->getActiveQuery(target);
2660 }
2661}
2662
2663void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
2664{
2665 TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
2666
2667 switch(pname)
2668 {
2669 case GL_QUERY_RESULT_EXT:
2670 case GL_QUERY_RESULT_AVAILABLE_EXT:
2671 break;
2672 default:
2673 return error(GL_INVALID_ENUM);
2674 }
2675
2676 es2::Context *context = es2::getContext();
2677
2678 if(context)
2679 {
2680 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);
2681
2682 if(!queryObject)
2683 {
2684 return error(GL_INVALID_OPERATION);
2685 }
2686
2687 if(context->getActiveQuery(queryObject->getType()) == id)
2688 {
2689 return error(GL_INVALID_OPERATION);
2690 }
2691
2692 switch(pname)
2693 {
2694 case GL_QUERY_RESULT_EXT:
2695 params[0] = queryObject->getResult();
2696 break;
2697 case GL_QUERY_RESULT_AVAILABLE_EXT:
2698 params[0] = queryObject->isResultAvailable();
2699 break;
2700 default:
2701 ASSERT(false);
2702 }
2703 }
2704}
2705
2706void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
2707{
2708 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
2709
2710 es2::Context *context = es2::getContext();
2711
2712 if(context)
2713 {
2714 if(target != GL_RENDERBUFFER)
2715 {
2716 return error(GL_INVALID_ENUM);
2717 }
2718
2719 if(context->getRenderbufferHandle() == 0)
2720 {
2721 return error(GL_INVALID_OPERATION);
2722 }
2723
2724 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
2725
2726 switch(pname)
2727 {
2728 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
2729 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
2730 case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat(); break;
2731 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
2732 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
2733 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
2734 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
2735 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
2736 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
2737 case GL_RENDERBUFFER_SAMPLES_ANGLE: *params = renderbuffer->getSamples(); break;
2738 default:
2739 return error(GL_INVALID_ENUM);
2740 }
2741 }
2742}
2743
2744void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
2745{
2746 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
2747
2748 es2::Context *context = es2::getContext();
2749
2750 if(context)
2751 {
2752 es2::Shader *shaderObject = context->getShader(shader);
2753
2754 if(!shaderObject)
2755 {
2756 return error(GL_INVALID_VALUE);
2757 }
2758
2759 switch(pname)
2760 {
2761 case GL_SHADER_TYPE:
2762 *params = shaderObject->getType();
2763 return;
2764 case GL_DELETE_STATUS:
2765 *params = shaderObject->isFlaggedForDeletion();
2766 return;
2767 case GL_COMPILE_STATUS:
2768 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
2769 return;
2770 case GL_INFO_LOG_LENGTH:
2771 *params = shaderObject->getInfoLogLength();
2772 return;
2773 case GL_SHADER_SOURCE_LENGTH:
2774 *params = shaderObject->getSourceLength();
2775 return;
2776 default:
2777 return error(GL_INVALID_ENUM);
2778 }
2779 }
2780}
2781
2782void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2783{
2784 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
2785 shader, bufsize, length, infolog);
2786
2787 if(bufsize < 0)
2788 {
2789 return error(GL_INVALID_VALUE);
2790 }
2791
2792 es2::Context *context = es2::getContext();
2793
2794 if(context)
2795 {
2796 es2::Shader *shaderObject = context->getShader(shader);
2797
2798 if(!shaderObject)
2799 {
2800 return error(GL_INVALID_VALUE);
2801 }
2802
2803 shaderObject->getInfoLog(bufsize, length, infolog);
2804 }
2805}
2806
2807void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
2808{
2809 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
2810 shadertype, precisiontype, range, precision);
2811
2812 switch(shadertype)
2813 {
2814 case GL_VERTEX_SHADER:
2815 case GL_FRAGMENT_SHADER:
2816 break;
2817 default:
2818 return error(GL_INVALID_ENUM);
2819 }
2820
2821 switch(precisiontype)
2822 {
2823 case GL_LOW_FLOAT:
2824 case GL_MEDIUM_FLOAT:
2825 case GL_HIGH_FLOAT:
2826 // IEEE 754 single-precision
2827 range[0] = 127;
2828 range[1] = 127;
2829 *precision = 23;
2830 break;
2831 case GL_LOW_INT:
2832 case GL_MEDIUM_INT:
2833 case GL_HIGH_INT:
2834 // Single-precision floating-point numbers can accurately represent integers up to +/-16777216
2835 range[0] = 24;
2836 range[1] = 24;
2837 *precision = 0;
2838 break;
2839 default:
2840 return error(GL_INVALID_ENUM);
2841 }
2842}
2843
2844void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
2845{
2846 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
2847 shader, bufsize, length, source);
2848
2849 if(bufsize < 0)
2850 {
2851 return error(GL_INVALID_VALUE);
2852 }
2853
2854 es2::Context *context = es2::getContext();
2855
2856 if(context)
2857 {
2858 es2::Shader *shaderObject = context->getShader(shader);
2859
2860 if(!shaderObject)
2861 {
2862 return error(GL_INVALID_OPERATION);
2863 }
2864
2865 shaderObject->getSource(bufsize, length, source);
2866 }
2867}
2868
2869const GLubyte* GL_APIENTRY glGetString(GLenum name)
2870{
2871 TRACE("(GLenum name = 0x%X)", name);
2872
2873 es2::Context *context = es2::getContext();
2874
2875 switch(name)
2876 {
2877 case GL_VENDOR:
2878 return (GLubyte*)"TransGaming Inc.";
2879 case GL_RENDERER:
2880 return (GLubyte*)"SwiftShader";
2881 case GL_VERSION:
2882 return (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
2883 case GL_SHADING_LANGUAGE_VERSION:
2884 return (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
2885 case GL_EXTENSIONS:
2886 // Keep list sorted in following order:
2887 // OES extensions
2888 // EXT extensions
2889 // Vendor extensions
2890 return (GLubyte*)
2891 "GL_OES_compressed_ETC1_RGB8_texture "
2892 "GL_OES_depth_texture "
2893 "GL_OES_depth_texture_cube_map "
2894 "GL_OES_EGL_image "
2895 "GL_OES_EGL_image_external "
2896 "GL_OES_element_index_uint "
2897 "GL_OES_packed_depth_stencil "
2898 "GL_OES_rgb8_rgba8 "
2899 "GL_OES_standard_derivatives "
2900 "GL_OES_texture_float "
2901 "GL_OES_texture_float_linear "
2902 "GL_OES_texture_half_float "
2903 "GL_OES_texture_half_float_linear "
2904 "GL_OES_texture_npot "
2905 "GL_EXT_blend_minmax "
2906 "GL_EXT_occlusion_query_boolean "
2907 "GL_EXT_read_format_bgra "
2908 #if (S3TC_SUPPORT)
2909 "GL_EXT_texture_compression_dxt1 "
2910 #endif
2911 "GL_EXT_texture_filter_anisotropic "
2912 "GL_EXT_texture_format_BGRA8888 "
2913 "GL_ANGLE_framebuffer_blit "
2914 "GL_ANGLE_framebuffer_multisample "
2915 #if (S3TC_SUPPORT)
2916 "GL_ANGLE_texture_compression_dxt3 "
2917 "GL_ANGLE_texture_compression_dxt5 "
2918 #endif
2919 "GL_NV_fence";
2920 default:
2921 return error(GL_INVALID_ENUM, (GLubyte*)NULL);
2922 }
2923}
2924
2925void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
2926{
2927 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
2928
2929 es2::Context *context = es2::getContext();
2930
2931 if(context)
2932 {
2933 es2::Texture *texture;
2934
2935 switch(target)
2936 {
2937 case GL_TEXTURE_2D:
2938 texture = context->getTexture2D();
2939 break;
2940 case GL_TEXTURE_CUBE_MAP:
2941 texture = context->getTextureCubeMap();
2942 break;
2943 case GL_TEXTURE_EXTERNAL_OES:
2944 texture = context->getTextureExternal();
2945 break;
2946 default:
2947 return error(GL_INVALID_ENUM);
2948 }
2949
2950 switch(pname)
2951 {
2952 case GL_TEXTURE_MAG_FILTER:
2953 *params = (GLfloat)texture->getMagFilter();
2954 break;
2955 case GL_TEXTURE_MIN_FILTER:
2956 *params = (GLfloat)texture->getMinFilter();
2957 break;
2958 case GL_TEXTURE_WRAP_S:
2959 *params = (GLfloat)texture->getWrapS();
2960 break;
2961 case GL_TEXTURE_WRAP_T:
2962 *params = (GLfloat)texture->getWrapT();
2963 break;
2964 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
2965 *params = texture->getMaxAnisotropy();
2966 break;
2967 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
2968 *params = (GLfloat)1;
2969 break;
2970 default:
2971 return error(GL_INVALID_ENUM);
2972 }
2973 }
2974}
2975
2976void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
2977{
2978 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
2979
2980 es2::Context *context = es2::getContext();
2981
2982 if(context)
2983 {
2984 es2::Texture *texture;
2985
2986 switch(target)
2987 {
2988 case GL_TEXTURE_2D:
2989 texture = context->getTexture2D();
2990 break;
2991 case GL_TEXTURE_CUBE_MAP:
2992 texture = context->getTextureCubeMap();
2993 break;
2994 case GL_TEXTURE_EXTERNAL_OES:
2995 texture = context->getTextureExternal();
2996 break;
2997 default:
2998 return error(GL_INVALID_ENUM);
2999 }
3000
3001 switch(pname)
3002 {
3003 case GL_TEXTURE_MAG_FILTER:
3004 *params = texture->getMagFilter();
3005 break;
3006 case GL_TEXTURE_MIN_FILTER:
3007 *params = texture->getMinFilter();
3008 break;
3009 case GL_TEXTURE_WRAP_S:
3010 *params = texture->getWrapS();
3011 break;
3012 case GL_TEXTURE_WRAP_T:
3013 *params = texture->getWrapT();
3014 break;
3015 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3016 *params = (GLint)texture->getMaxAnisotropy();
3017 break;
3018 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3019 *params = 1;
3020 break;
3021 default:
3022 return error(GL_INVALID_ENUM);
3023 }
3024 }
3025}
3026
3027void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3028{
3029 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
3030 program, location, bufSize, params);
3031
3032 if(bufSize < 0)
3033 {
3034 return error(GL_INVALID_VALUE);
3035 }
3036
3037 es2::Context *context = es2::getContext();
3038
3039 if(context)
3040 {
3041 if(program == 0)
3042 {
3043 return error(GL_INVALID_VALUE);
3044 }
3045
3046 es2::Program *programObject = context->getProgram(program);
3047
3048 if(!programObject || !programObject->isLinked())
3049 {
3050 return error(GL_INVALID_OPERATION);
3051 }
3052
3053 if(!programObject->getUniformfv(location, &bufSize, params))
3054 {
3055 return error(GL_INVALID_OPERATION);
3056 }
3057 }
3058}
3059
3060void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
3061{
3062 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
3063
3064 es2::Context *context = es2::getContext();
3065
3066 if(context)
3067 {
3068 if(program == 0)
3069 {
3070 return error(GL_INVALID_VALUE);
3071 }
3072
3073 es2::Program *programObject = context->getProgram(program);
3074
3075 if(!programObject || !programObject->isLinked())
3076 {
3077 return error(GL_INVALID_OPERATION);
3078 }
3079
3080 if(!programObject->getUniformfv(location, NULL, params))
3081 {
3082 return error(GL_INVALID_OPERATION);
3083 }
3084 }
3085}
3086
3087void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3088{
3089 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
3090 program, location, bufSize, params);
3091
3092 if(bufSize < 0)
3093 {
3094 return error(GL_INVALID_VALUE);
3095 }
3096
3097 es2::Context *context = es2::getContext();
3098
3099 if(context)
3100 {
3101 if(program == 0)
3102 {
3103 return error(GL_INVALID_VALUE);
3104 }
3105
3106 es2::Program *programObject = context->getProgram(program);
3107
3108 if(!programObject || !programObject->isLinked())
3109 {
3110 return error(GL_INVALID_OPERATION);
3111 }
3112
3113 if(!programObject)
3114 {
3115 return error(GL_INVALID_OPERATION);
3116 }
3117
3118 if(!programObject->getUniformiv(location, &bufSize, params))
3119 {
3120 return error(GL_INVALID_OPERATION);
3121 }
3122 }
3123}
3124
3125void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
3126{
3127 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
3128
3129 es2::Context *context = es2::getContext();
3130
3131 if(context)
3132 {
3133 if(program == 0)
3134 {
3135 return error(GL_INVALID_VALUE);
3136 }
3137
3138 es2::Program *programObject = context->getProgram(program);
3139
3140 if(!programObject || !programObject->isLinked())
3141 {
3142 return error(GL_INVALID_OPERATION);
3143 }
3144
3145 if(!programObject)
3146 {
3147 return error(GL_INVALID_OPERATION);
3148 }
3149
3150 if(!programObject->getUniformiv(location, NULL, params))
3151 {
3152 return error(GL_INVALID_OPERATION);
3153 }
3154 }
3155}
3156
3157int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
3158{
3159 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3160
3161 es2::Context *context = es2::getContext();
3162
3163 if(strstr(name, "gl_") == name)
3164 {
3165 return -1;
3166 }
3167
3168 if(context)
3169 {
3170 es2::Program *programObject = context->getProgram(program);
3171
3172 if(!programObject)
3173 {
3174 if(context->getShader(program))
3175 {
3176 return error(GL_INVALID_OPERATION, -1);
3177 }
3178 else
3179 {
3180 return error(GL_INVALID_VALUE, -1);
3181 }
3182 }
3183
3184 if(!programObject->isLinked())
3185 {
3186 return error(GL_INVALID_OPERATION, -1);
3187 }
3188
3189 return programObject->getUniformLocation(name);
3190 }
3191
3192 return -1;
3193}
3194
3195void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3196{
3197 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
3198
3199 es2::Context *context = es2::getContext();
3200
3201 if(context)
3202 {
3203 if(index >= es2::MAX_VERTEX_ATTRIBS)
3204 {
3205 return error(GL_INVALID_VALUE);
3206 }
3207
3208 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3209
3210 switch(pname)
3211 {
3212 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3213 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3214 break;
3215 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3216 *params = (GLfloat)attribState.mSize;
3217 break;
3218 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3219 *params = (GLfloat)attribState.mStride;
3220 break;
3221 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3222 *params = (GLfloat)attribState.mType;
3223 break;
3224 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3225 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3226 break;
3227 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3228 *params = (GLfloat)attribState.mBoundBuffer.id();
3229 break;
3230 case GL_CURRENT_VERTEX_ATTRIB:
3231 for(int i = 0; i < 4; ++i)
3232 {
3233 params[i] = attribState.mCurrentValue[i];
3234 }
3235 break;
3236 default: return error(GL_INVALID_ENUM);
3237 }
3238 }
3239}
3240
3241void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3242{
3243 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
3244
3245 es2::Context *context = es2::getContext();
3246
3247 if(context)
3248 {
3249 if(index >= es2::MAX_VERTEX_ATTRIBS)
3250 {
3251 return error(GL_INVALID_VALUE);
3252 }
3253
3254 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3255
3256 switch(pname)
3257 {
3258 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3259 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3260 break;
3261 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3262 *params = attribState.mSize;
3263 break;
3264 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3265 *params = attribState.mStride;
3266 break;
3267 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3268 *params = attribState.mType;
3269 break;
3270 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3271 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3272 break;
3273 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3274 *params = attribState.mBoundBuffer.id();
3275 break;
3276 case GL_CURRENT_VERTEX_ATTRIB:
3277 for(int i = 0; i < 4; ++i)
3278 {
3279 float currentValue = attribState.mCurrentValue[i];
3280 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3281 }
3282 break;
3283 default: return error(GL_INVALID_ENUM);
3284 }
3285 }
3286}
3287
3288void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3289{
3290 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
3291
3292 es2::Context *context = es2::getContext();
3293
3294 if(context)
3295 {
3296 if(index >= es2::MAX_VERTEX_ATTRIBS)
3297 {
3298 return error(GL_INVALID_VALUE);
3299 }
3300
3301 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3302 {
3303 return error(GL_INVALID_ENUM);
3304 }
3305
3306 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3307 }
3308}
3309
3310void GL_APIENTRY glHint(GLenum target, GLenum mode)
3311{
3312 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3313
3314 switch(mode)
3315 {
3316 case GL_FASTEST:
3317 case GL_NICEST:
3318 case GL_DONT_CARE:
3319 break;
3320 default:
3321 return error(GL_INVALID_ENUM);
3322 }
3323
3324 es2::Context *context = es2::getContext();
3325 switch(target)
3326 {
3327 case GL_GENERATE_MIPMAP_HINT:
3328 if(context) context->setGenerateMipmapHint(mode);
3329 break;
3330 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3331 if(context) context->setFragmentShaderDerivativeHint(mode);
3332 break;
3333 default:
3334 return error(GL_INVALID_ENUM);
3335 }
3336}
3337
3338GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
3339{
3340 TRACE("(GLuint buffer = %d)", buffer);
3341
3342 es2::Context *context = es2::getContext();
3343
3344 if(context && buffer)
3345 {
3346 es2::Buffer *bufferObject = context->getBuffer(buffer);
3347
3348 if(bufferObject)
3349 {
3350 return GL_TRUE;
3351 }
3352 }
3353
3354 return GL_FALSE;
3355}
3356
3357GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
3358{
3359 TRACE("(GLenum cap = 0x%X)", cap);
3360
3361 es2::Context *context = es2::getContext();
3362
3363 if(context)
3364 {
3365 switch(cap)
3366 {
3367 case GL_CULL_FACE: return context->isCullFaceEnabled();
3368 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3369 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3370 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3371 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3372 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3373 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3374 case GL_BLEND: return context->isBlendEnabled();
3375 case GL_DITHER: return context->isDitherEnabled();
3376 default:
3377 return error(GL_INVALID_ENUM, false);
3378 }
3379 }
3380
3381 return false;
3382}
3383
3384GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
3385{
3386 TRACE("(GLuint fence = %d)", fence);
3387
3388 es2::Context *context = es2::getContext();
3389
3390 if(context)
3391 {
3392 es2::Fence *fenceObject = context->getFence(fence);
3393
3394 if(fenceObject == NULL)
3395 {
3396 return GL_FALSE;
3397 }
3398
3399 return fenceObject->isFence();
3400 }
3401
3402 return GL_FALSE;
3403}
3404
3405GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
3406{
3407 TRACE("(GLuint framebuffer = %d)", framebuffer);
3408
3409 es2::Context *context = es2::getContext();
3410
3411 if(context && framebuffer)
3412 {
3413 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3414
3415 if(framebufferObject)
3416 {
3417 return GL_TRUE;
3418 }
3419 }
3420
3421 return GL_FALSE;
3422}
3423
3424GLboolean GL_APIENTRY glIsProgram(GLuint program)
3425{
3426 TRACE("(GLuint program = %d)", program);
3427
3428 es2::Context *context = es2::getContext();
3429
3430 if(context && program)
3431 {
3432 es2::Program *programObject = context->getProgram(program);
3433
3434 if(programObject)
3435 {
3436 return GL_TRUE;
3437 }
3438 }
3439
3440 return GL_FALSE;
3441}
3442
3443GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
3444{
3445 TRACE("(GLuint id = %d)", id);
3446
3447 if(id == 0)
3448 {
3449 return GL_FALSE;
3450 }
3451
3452 es2::Context *context = es2::getContext();
3453
3454 if(context)
3455 {
3456 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);
3457
3458 if(queryObject)
3459 {
3460 return GL_TRUE;
3461 }
3462 }
3463
3464 return GL_FALSE;
3465}
3466
3467GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
3468{
3469 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3470
3471 es2::Context *context = es2::getContext();
3472
3473 if(context && renderbuffer)
3474 {
3475 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3476
3477 if(renderbufferObject)
3478 {
3479 return GL_TRUE;
3480 }
3481 }
3482
3483 return GL_FALSE;
3484}
3485
3486GLboolean GL_APIENTRY glIsShader(GLuint shader)
3487{
3488 TRACE("(GLuint shader = %d)", shader);
3489
3490 es2::Context *context = es2::getContext();
3491
3492 if(context && shader)
3493 {
3494 es2::Shader *shaderObject = context->getShader(shader);
3495
3496 if(shaderObject)
3497 {
3498 return GL_TRUE;
3499 }
3500 }
3501
3502 return GL_FALSE;
3503}
3504
3505GLboolean GL_APIENTRY glIsTexture(GLuint texture)
3506{
3507 TRACE("(GLuint texture = %d)", texture);
3508
3509 es2::Context *context = es2::getContext();
3510
3511 if(context && texture)
3512 {
3513 es2::Texture *textureObject = context->getTexture(texture);
3514
3515 if(textureObject)
3516 {
3517 return GL_TRUE;
3518 }
3519 }
3520
3521 return GL_FALSE;
3522}
3523
3524void GL_APIENTRY glLineWidth(GLfloat width)
3525{
3526 TRACE("(GLfloat width = %f)", width);
3527
3528 if(width <= 0.0f)
3529 {
3530 return error(GL_INVALID_VALUE);
3531 }
3532
3533 es2::Context *context = es2::getContext();
3534
3535 if(context)
3536 {
3537 context->setLineWidth(width);
3538 }
3539}
3540
3541void GL_APIENTRY glLinkProgram(GLuint program)
3542{
3543 TRACE("(GLuint program = %d)", program);
3544
3545 es2::Context *context = es2::getContext();
3546
3547 if(context)
3548 {
3549 es2::Program *programObject = context->getProgram(program);
3550
3551 if(!programObject)
3552 {
3553 if(context->getShader(program))
3554 {
3555 return error(GL_INVALID_OPERATION);
3556 }
3557 else
3558 {
3559 return error(GL_INVALID_VALUE);
3560 }
3561 }
3562
3563 programObject->link();
3564 }
3565}
3566
3567void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
3568{
3569 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
3570
3571 es2::Context *context = es2::getContext();
3572
3573 if(context)
3574 {
3575 switch(pname)
3576 {
3577 case GL_UNPACK_ALIGNMENT:
3578 if(param != 1 && param != 2 && param != 4 && param != 8)
3579 {
3580 return error(GL_INVALID_VALUE);
3581 }
3582 context->setUnpackAlignment(param);
3583 break;
3584 case GL_PACK_ALIGNMENT:
3585 if(param != 1 && param != 2 && param != 4 && param != 8)
3586 {
3587 return error(GL_INVALID_VALUE);
3588 }
3589 context->setPackAlignment(param);
3590 break;
3591 default:
3592 return error(GL_INVALID_ENUM);
3593 }
3594 }
3595}
3596
3597void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
3598{
3599 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
3600
3601 es2::Context *context = es2::getContext();
3602
3603 if(context)
3604 {
3605 context->setPolygonOffsetParams(factor, units);
3606 }
3607}
3608
3609void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
3610 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
3611{
3612 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
3613 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
3614 x, y, width, height, format, type, bufSize, data);
3615
3616 if(width < 0 || height < 0 || bufSize < 0)
3617 {
3618 return error(GL_INVALID_VALUE);
3619 }
3620
3621 if(!validReadFormatType(format, type))
3622 {
3623 return error(GL_INVALID_OPERATION);
3624 }
3625
3626 es2::Context *context = es2::getContext();
3627
3628 if(context)
3629 {
3630 context->readPixels(x, y, width, height, format, type, &bufSize, data);
3631 }
3632}
3633
3634void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
3635{
3636 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
3637 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
3638 x, y, width, height, format, type, pixels);
3639
3640 if(width < 0 || height < 0)
3641 {
3642 return error(GL_INVALID_VALUE);
3643 }
3644
3645 if(!validReadFormatType(format, type))
3646 {
3647 return error(GL_INVALID_OPERATION);
3648 }
3649
3650 es2::Context *context = es2::getContext();
3651
3652 if(context)
3653 {
3654 context->readPixels(x, y, width, height, format, type, NULL, pixels);
3655 }
3656}
3657
3658void GL_APIENTRY glReleaseShaderCompiler(void)
3659{
3660 TRACE("()");
3661
3662 es2::Shader::releaseCompiler();
3663}
3664
3665void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
3666{
3667 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
3668 target, samples, internalformat, width, height);
3669
3670 switch(target)
3671 {
3672 case GL_RENDERBUFFER:
3673 break;
3674 default:
3675 return error(GL_INVALID_ENUM);
3676 }
3677
3678 if(!es2::IsColorRenderable(internalformat) && !es2::IsDepthRenderable(internalformat) && !es2::IsStencilRenderable(internalformat))
3679 {
3680 return error(GL_INVALID_ENUM);
3681 }
3682
3683 if(width < 0 || height < 0 || samples < 0)
3684 {
3685 return error(GL_INVALID_VALUE);
3686 }
3687
3688 es2::Context *context = es2::getContext();
3689
3690 if(context)
3691 {
3692 if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
3693 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
3694 samples > es2::IMPLEMENTATION_MAX_SAMPLES)
3695 {
3696 return error(GL_INVALID_VALUE);
3697 }
3698
3699 GLuint handle = context->getRenderbufferHandle();
3700 if(handle == 0)
3701 {
3702 return error(GL_INVALID_OPERATION);
3703 }
3704
3705 switch(internalformat)
3706 {
3707 case GL_DEPTH_COMPONENT16:
3708 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, samples));
3709 break;
3710 case GL_RGBA4:
3711 case GL_RGB5_A1:
3712 case GL_RGB565:
3713 case GL_RGB8_OES:
3714 case GL_RGBA8_OES:
3715 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
3716 break;
3717 case GL_STENCIL_INDEX8:
3718 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
3719 break;
3720 case GL_DEPTH24_STENCIL8_OES:
3721 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, samples));
3722 break;
3723 default:
3724 return error(GL_INVALID_ENUM);
3725 }
3726 }
3727}
3728
3729void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
3730{
3731 glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
3732}
3733
3734void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)
3735{
3736 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
3737
3738 es2::Context* context = es2::getContext();
3739
3740 if(context)
3741 {
3742 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
3743 }
3744}
3745
3746void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
3747{
3748 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
3749
3750 if(condition != GL_ALL_COMPLETED_NV)
3751 {
3752 return error(GL_INVALID_ENUM);
3753 }
3754
3755 es2::Context *context = es2::getContext();
3756
3757 if(context)
3758 {
3759 es2::Fence *fenceObject = context->getFence(fence);
3760
3761 if(fenceObject == NULL)
3762 {
3763 return error(GL_INVALID_OPERATION);
3764 }
3765
3766 fenceObject->setFence(condition);
3767 }
3768}
3769
3770void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
3771{
3772 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
3773
3774 if(width < 0 || height < 0)
3775 {
3776 return error(GL_INVALID_VALUE);
3777 }
3778
3779 es2::Context* context = es2::getContext();
3780
3781 if(context)
3782 {
3783 context->setScissorParams(x, y, width, height);
3784 }
3785}
3786
3787void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
3788{
3789 TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
3790 "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
3791 n, shaders, binaryformat, binary, length);
3792
3793 // No binary shader formats are supported.
3794 return error(GL_INVALID_ENUM);
3795}
3796
3797void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
3798{
3799 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
3800 shader, count, string, length);
3801
3802 if(count < 0)
3803 {
3804 return error(GL_INVALID_VALUE);
3805 }
3806
3807 es2::Context *context = es2::getContext();
3808
3809 if(context)
3810 {
3811 es2::Shader *shaderObject = context->getShader(shader);
3812
3813 if(!shaderObject)
3814 {
3815 if(context->getProgram(shader))
3816 {
3817 return error(GL_INVALID_OPERATION);
3818 }
3819 else
3820 {
3821 return error(GL_INVALID_VALUE);
3822 }
3823 }
3824
3825 shaderObject->setSource(count, string, length);
3826 }
3827}
3828
3829void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
3830{
3831 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
3832}
3833
3834void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
3835{
3836 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
3837
3838 switch(face)
3839 {
3840 case GL_FRONT:
3841 case GL_BACK:
3842 case GL_FRONT_AND_BACK:
3843 break;
3844 default:
3845 return error(GL_INVALID_ENUM);
3846 }
3847
3848 switch(func)
3849 {
3850 case GL_NEVER:
3851 case GL_ALWAYS:
3852 case GL_LESS:
3853 case GL_LEQUAL:
3854 case GL_EQUAL:
3855 case GL_GEQUAL:
3856 case GL_GREATER:
3857 case GL_NOTEQUAL:
3858 break;
3859 default:
3860 return error(GL_INVALID_ENUM);
3861 }
3862
3863 es2::Context *context = es2::getContext();
3864
3865 if(context)
3866 {
3867 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
3868 {
3869 context->setStencilParams(func, ref, mask);
3870 }
3871
3872 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
3873 {
3874 context->setStencilBackParams(func, ref, mask);
3875 }
3876 }
3877}
3878
3879void GL_APIENTRY glStencilMask(GLuint mask)
3880{
3881 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
3882}
3883
3884void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
3885{
3886 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
3887
3888 switch(face)
3889 {
3890 case GL_FRONT:
3891 case GL_BACK:
3892 case GL_FRONT_AND_BACK:
3893 break;
3894 default:
3895 return error(GL_INVALID_ENUM);
3896 }
3897
3898 es2::Context *context = es2::getContext();
3899
3900 if(context)
3901 {
3902 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
3903 {
3904 context->setStencilWritemask(mask);
3905 }
3906
3907 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
3908 {
3909 context->setStencilBackWritemask(mask);
3910 }
3911 }
3912}
3913
3914void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
3915{
3916 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
3917}
3918
3919void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
3920{
3921 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
3922 face, fail, zfail, zpass);
3923
3924 switch(face)
3925 {
3926 case GL_FRONT:
3927 case GL_BACK:
3928 case GL_FRONT_AND_BACK:
3929 break;
3930 default:
3931 return error(GL_INVALID_ENUM);
3932 }
3933
3934 switch(fail)
3935 {
3936 case GL_ZERO:
3937 case GL_KEEP:
3938 case GL_REPLACE:
3939 case GL_INCR:
3940 case GL_DECR:
3941 case GL_INVERT:
3942 case GL_INCR_WRAP:
3943 case GL_DECR_WRAP:
3944 break;
3945 default:
3946 return error(GL_INVALID_ENUM);
3947 }
3948
3949 switch(zfail)
3950 {
3951 case GL_ZERO:
3952 case GL_KEEP:
3953 case GL_REPLACE:
3954 case GL_INCR:
3955 case GL_DECR:
3956 case GL_INVERT:
3957 case GL_INCR_WRAP:
3958 case GL_DECR_WRAP:
3959 break;
3960 default:
3961 return error(GL_INVALID_ENUM);
3962 }
3963
3964 switch(zpass)
3965 {
3966 case GL_ZERO:
3967 case GL_KEEP:
3968 case GL_REPLACE:
3969 case GL_INCR:
3970 case GL_DECR:
3971 case GL_INVERT:
3972 case GL_INCR_WRAP:
3973 case GL_DECR_WRAP:
3974 break;
3975 default:
3976 return error(GL_INVALID_ENUM);
3977 }
3978
3979 es2::Context *context = es2::getContext();
3980
3981 if(context)
3982 {
3983 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
3984 {
3985 context->setStencilOperations(fail, zfail, zpass);
3986 }
3987
3988 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
3989 {
3990 context->setStencilBackOperations(fail, zfail, zpass);
3991 }
3992 }
3993}
3994
3995GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
3996{
3997 TRACE("(GLuint fence = %d)", fence);
3998
3999 es2::Context *context = es2::getContext();
4000
4001 if(context)
4002 {
4003 es2::Fence *fenceObject = context->getFence(fence);
4004
4005 if(fenceObject == NULL)
4006 {
4007 return error(GL_INVALID_OPERATION, GL_TRUE);
4008 }
4009
4010 return fenceObject->testFence();
4011 }
4012
4013 return GL_TRUE;
4014}
4015
4016void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4017 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
4018{
4019 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
4020 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
4021 target, level, internalformat, width, height, border, format, type, pixels);
4022
4023 if(!validImageSize(level, width, height))
4024 {
4025 return error(GL_INVALID_VALUE);
4026 }
4027
4028 if(internalformat != format)
4029 {
4030 return error(GL_INVALID_OPERATION);
4031 }
4032
4033 switch(format)
4034 {
4035 case GL_ALPHA:
4036 case GL_LUMINANCE:
4037 case GL_LUMINANCE_ALPHA:
4038 switch(type)
4039 {
4040 case GL_UNSIGNED_BYTE:
4041 case GL_FLOAT:
4042 case GL_HALF_FLOAT_OES:
4043 break;
4044 default:
4045 return error(GL_INVALID_ENUM);
4046 }
4047 break;
4048 case GL_RGB:
4049 switch(type)
4050 {
4051 case GL_UNSIGNED_BYTE:
4052 case GL_UNSIGNED_SHORT_5_6_5:
4053 case GL_FLOAT:
4054 case GL_HALF_FLOAT_OES:
4055 break;
4056 default:
4057 return error(GL_INVALID_ENUM);
4058 }
4059 break;
4060 case GL_RGBA:
4061 switch(type)
4062 {
4063 case GL_UNSIGNED_BYTE:
4064 case GL_UNSIGNED_SHORT_4_4_4_4:
4065 case GL_UNSIGNED_SHORT_5_5_5_1:
4066 case GL_FLOAT:
4067 case GL_HALF_FLOAT_OES:
4068 break;
4069 default:
4070 return error(GL_INVALID_ENUM);
4071 }
4072 break;
4073 case GL_BGRA_EXT:
4074 switch(type)
4075 {
4076 case GL_UNSIGNED_BYTE:
4077 break;
4078 default:
4079 return error(GL_INVALID_ENUM);
4080 }
4081 break;
4082 case GL_ETC1_RGB8_OES:
4083 return error(GL_INVALID_OPERATION);
4084 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
4085 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
4086 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
4087 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
4088 if(S3TC_SUPPORT)
4089 {
4090 return error(GL_INVALID_OPERATION);
4091 }
4092 else
4093 {
4094 return error(GL_INVALID_ENUM);
4095 }
4096 case GL_DEPTH_COMPONENT:
4097 switch(type)
4098 {
4099 case GL_UNSIGNED_SHORT:
4100 case GL_UNSIGNED_INT:
4101 break;
4102 default:
4103 return error(GL_INVALID_ENUM);
4104 }
4105 break;
4106 case GL_DEPTH_STENCIL_OES:
4107 switch(type)
4108 {
4109 case GL_UNSIGNED_INT_24_8_OES:
4110 break;
4111 default:
4112 return error(GL_INVALID_ENUM);
4113 }
4114 break;
4115 default:
4116 return error(GL_INVALID_VALUE);
4117 }
4118
4119 if(border != 0)
4120 {
4121 return error(GL_INVALID_VALUE);
4122 }
4123
4124 es2::Context *context = es2::getContext();
4125
4126 if(context)
4127 {
4128 switch(target)
4129 {
4130 case GL_TEXTURE_2D:
4131 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4132 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4133 {
4134 return error(GL_INVALID_VALUE);
4135 }
4136 break;
4137 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4138 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4139 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4140 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4141 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4142 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4143 if(width != height)
4144 {
4145 return error(GL_INVALID_VALUE);
4146 }
4147
4148 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4149 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4150 {
4151 return error(GL_INVALID_VALUE);
4152 }
4153 break;
4154 default:
4155 return error(GL_INVALID_ENUM);
4156 }
4157
4158 if(target == GL_TEXTURE_2D)
4159 {
4160 es2::Texture2D *texture = context->getTexture2D();
4161
4162 if(!texture)
4163 {
4164 return error(GL_INVALID_OPERATION);
4165 }
4166
4167 texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
4168 }
4169 else
4170 {
4171 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4172
4173 if(!texture)
4174 {
4175 return error(GL_INVALID_OPERATION);
4176 }
4177
4178 texture->setImage(target, level, width, height, format, type, context->getUnpackAlignment(), pixels);
4179 }
4180 }
4181}
4182
4183void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
4184{
4185 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4186
4187 es2::Context *context = es2::getContext();
4188
4189 if(context)
4190 {
4191 es2::Texture *texture;
4192
4193 switch(target)
4194 {
4195 case GL_TEXTURE_2D:
4196 texture = context->getTexture2D();
4197 break;
4198 case GL_TEXTURE_CUBE_MAP:
4199 texture = context->getTextureCubeMap();
4200 break;
4201 case GL_TEXTURE_EXTERNAL_OES:
4202 texture = context->getTextureExternal();
4203 break;
4204 default:
4205 return error(GL_INVALID_ENUM);
4206 }
4207
4208 switch(pname)
4209 {
4210 case GL_TEXTURE_WRAP_S:
4211 if(!texture->setWrapS((GLenum)param))
4212 {
4213 return error(GL_INVALID_ENUM);
4214 }
4215 break;
4216 case GL_TEXTURE_WRAP_T:
4217 if(!texture->setWrapT((GLenum)param))
4218 {
4219 return error(GL_INVALID_ENUM);
4220 }
4221 break;
4222 case GL_TEXTURE_MIN_FILTER:
4223 if(!texture->setMinFilter((GLenum)param))
4224 {
4225 return error(GL_INVALID_ENUM);
4226 }
4227 break;
4228 case GL_TEXTURE_MAG_FILTER:
4229 if(!texture->setMagFilter((GLenum)param))
4230 {
4231 return error(GL_INVALID_ENUM);
4232 }
4233 break;
4234 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4235 if(!texture->setMaxAnisotropy(param))
4236 {
4237 return error(GL_INVALID_VALUE);
4238 }
4239 break;
4240 default:
4241 return error(GL_INVALID_ENUM);
4242 }
4243 }
4244}
4245
4246void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4247{
4248 glTexParameterf(target, pname, *params);
4249}
4250
4251void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
4252{
4253 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4254
4255 es2::Context *context = es2::getContext();
4256
4257 if(context)
4258 {
4259 es2::Texture *texture;
4260
4261 switch(target)
4262 {
4263 case GL_TEXTURE_2D:
4264 texture = context->getTexture2D();
4265 break;
4266 case GL_TEXTURE_CUBE_MAP:
4267 texture = context->getTextureCubeMap();
4268 break;
4269 case GL_TEXTURE_EXTERNAL_OES:
4270 texture = context->getTextureExternal();
4271 break;
4272 default:
4273 return error(GL_INVALID_ENUM);
4274 }
4275
4276 switch(pname)
4277 {
4278 case GL_TEXTURE_WRAP_S:
4279 if(!texture->setWrapS((GLenum)param))
4280 {
4281 return error(GL_INVALID_ENUM);
4282 }
4283 break;
4284 case GL_TEXTURE_WRAP_T:
4285 if(!texture->setWrapT((GLenum)param))
4286 {
4287 return error(GL_INVALID_ENUM);
4288 }
4289 break;
4290 case GL_TEXTURE_MIN_FILTER:
4291 if(!texture->setMinFilter((GLenum)param))
4292 {
4293 return error(GL_INVALID_ENUM);
4294 }
4295 break;
4296 case GL_TEXTURE_MAG_FILTER:
4297 if(!texture->setMagFilter((GLenum)param))
4298 {
4299 return error(GL_INVALID_ENUM);
4300 }
4301 break;
4302 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4303 if(!texture->setMaxAnisotropy((GLfloat)param))
4304 {
4305 return error(GL_INVALID_VALUE);
4306 }
4307 break;
4308 default:
4309 return error(GL_INVALID_ENUM);
4310 }
4311 }
4312}
4313
4314void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
4315{
4316 glTexParameteri(target, pname, *params);
4317}
4318
4319void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
4320 GLenum format, GLenum type, const GLvoid* pixels)
4321{
4322 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4323 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
4324 "const GLvoid* pixels = 0x%0.8p)",
4325 target, level, xoffset, yoffset, width, height, format, type, pixels);
4326
4327 if(!es2::IsTextureTarget(target))
4328 {
4329 return error(GL_INVALID_ENUM);
4330 }
4331
4332 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4333 {
4334 return error(GL_INVALID_VALUE);
4335 }
4336
4337 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4338 {
4339 return error(GL_INVALID_VALUE);
4340 }
4341
4342 if(!es2::CheckTextureFormatType(format, type))
4343 {
4344 return error(GL_INVALID_ENUM);
4345 }
4346
4347 if(width == 0 || height == 0 || pixels == NULL)
4348 {
4349 return;
4350 }
4351
4352 es2::Context *context = es2::getContext();
4353
4354 if(context)
4355 {
4356 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4357 {
4358 return error(GL_INVALID_VALUE);
4359 }
4360
4361 if(target == GL_TEXTURE_2D)
4362 {
4363 es2::Texture2D *texture = context->getTexture2D();
4364
4365 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
4366 {
4367 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
4368 }
4369 }
4370 else if(es2::IsCubemapTextureTarget(target))
4371 {
4372 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4373
4374 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
4375 {
4376 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
4377 }
4378 }
4379 else
4380 {
4381 UNREACHABLE();
4382 }
4383 }
4384}
4385
4386void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
4387{
4388 glUniform1fv(location, 1, &x);
4389}
4390
4391void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
4392{
4393 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
4394
4395 if(count < 0)
4396 {
4397 return error(GL_INVALID_VALUE);
4398 }
4399
4400 if(location == -1)
4401 {
4402 return;
4403 }
4404
4405 es2::Context *context = es2::getContext();
4406
4407 if(context)
4408 {
4409 es2::Program *program = context->getCurrentProgram();
4410
4411 if(!program)
4412 {
4413 return error(GL_INVALID_OPERATION);
4414 }
4415
4416 if(!program->setUniform1fv(location, count, v))
4417 {
4418 return error(GL_INVALID_OPERATION);
4419 }
4420 }
4421}
4422
4423void GL_APIENTRY glUniform1i(GLint location, GLint x)
4424{
4425 glUniform1iv(location, 1, &x);
4426}
4427
4428void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
4429{
4430 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
4431
4432 if(count < 0)
4433 {
4434 return error(GL_INVALID_VALUE);
4435 }
4436
4437 if(location == -1)
4438 {
4439 return;
4440 }
4441
4442 es2::Context *context = es2::getContext();
4443
4444 if(context)
4445 {
4446 es2::Program *program = context->getCurrentProgram();
4447
4448 if(!program)
4449 {
4450 return error(GL_INVALID_OPERATION);
4451 }
4452
4453 if(!program->setUniform1iv(location, count, v))
4454 {
4455 return error(GL_INVALID_OPERATION);
4456 }
4457 }
4458}
4459
4460void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
4461{
4462 GLfloat xy[2] = {x, y};
4463
4464 glUniform2fv(location, 1, (GLfloat*)&xy);
4465}
4466
4467void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
4468{
4469 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
4470
4471 if(count < 0)
4472 {
4473 return error(GL_INVALID_VALUE);
4474 }
4475
4476 if(location == -1)
4477 {
4478 return;
4479 }
4480
4481 es2::Context *context = es2::getContext();
4482
4483 if(context)
4484 {
4485 es2::Program *program = context->getCurrentProgram();
4486
4487 if(!program)
4488 {
4489 return error(GL_INVALID_OPERATION);
4490 }
4491
4492 if(!program->setUniform2fv(location, count, v))
4493 {
4494 return error(GL_INVALID_OPERATION);
4495 }
4496 }
4497}
4498
4499void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
4500{
4501 GLint xy[4] = {x, y};
4502
4503 glUniform2iv(location, 1, (GLint*)&xy);
4504}
4505
4506void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
4507{
4508 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
4509
4510 if(count < 0)
4511 {
4512 return error(GL_INVALID_VALUE);
4513 }
4514
4515 if(location == -1)
4516 {
4517 return;
4518 }
4519
4520 es2::Context *context = es2::getContext();
4521
4522 if(context)
4523 {
4524 es2::Program *program = context->getCurrentProgram();
4525
4526 if(!program)
4527 {
4528 return error(GL_INVALID_OPERATION);
4529 }
4530
4531 if(!program->setUniform2iv(location, count, v))
4532 {
4533 return error(GL_INVALID_OPERATION);
4534 }
4535 }
4536}
4537
4538void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
4539{
4540 GLfloat xyz[3] = {x, y, z};
4541
4542 glUniform3fv(location, 1, (GLfloat*)&xyz);
4543}
4544
4545void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
4546{
4547 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
4548
4549 if(count < 0)
4550 {
4551 return error(GL_INVALID_VALUE);
4552 }
4553
4554 if(location == -1)
4555 {
4556 return;
4557 }
4558
4559 es2::Context *context = es2::getContext();
4560
4561 if(context)
4562 {
4563 es2::Program *program = context->getCurrentProgram();
4564
4565 if(!program)
4566 {
4567 return error(GL_INVALID_OPERATION);
4568 }
4569
4570 if(!program->setUniform3fv(location, count, v))
4571 {
4572 return error(GL_INVALID_OPERATION);
4573 }
4574 }
4575}
4576
4577void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
4578{
4579 GLint xyz[3] = {x, y, z};
4580
4581 glUniform3iv(location, 1, (GLint*)&xyz);
4582}
4583
4584void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
4585{
4586 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
4587
4588 if(count < 0)
4589 {
4590 return error(GL_INVALID_VALUE);
4591 }
4592
4593 if(location == -1)
4594 {
4595 return;
4596 }
4597
4598 es2::Context *context = es2::getContext();
4599
4600 if(context)
4601 {
4602 es2::Program *program = context->getCurrentProgram();
4603
4604 if(!program)
4605 {
4606 return error(GL_INVALID_OPERATION);
4607 }
4608
4609 if(!program->setUniform3iv(location, count, v))
4610 {
4611 return error(GL_INVALID_OPERATION);
4612 }
4613 }
4614}
4615
4616void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
4617{
4618 GLfloat xyzw[4] = {x, y, z, w};
4619
4620 glUniform4fv(location, 1, (GLfloat*)&xyzw);
4621}
4622
4623void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
4624{
4625 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
4626
4627 if(count < 0)
4628 {
4629 return error(GL_INVALID_VALUE);
4630 }
4631
4632 if(location == -1)
4633 {
4634 return;
4635 }
4636
4637 es2::Context *context = es2::getContext();
4638
4639 if(context)
4640 {
4641 es2::Program *program = context->getCurrentProgram();
4642
4643 if(!program)
4644 {
4645 return error(GL_INVALID_OPERATION);
4646 }
4647
4648 if(!program->setUniform4fv(location, count, v))
4649 {
4650 return error(GL_INVALID_OPERATION);
4651 }
4652 }
4653}
4654
4655void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
4656{
4657 GLint xyzw[4] = {x, y, z, w};
4658
4659 glUniform4iv(location, 1, (GLint*)&xyzw);
4660}
4661
4662void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
4663{
4664 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
4665
4666 if(count < 0)
4667 {
4668 return error(GL_INVALID_VALUE);
4669 }
4670
4671 if(location == -1)
4672 {
4673 return;
4674 }
4675
4676 es2::Context *context = es2::getContext();
4677
4678 if(context)
4679 {
4680 es2::Program *program = context->getCurrentProgram();
4681
4682 if(!program)
4683 {
4684 return error(GL_INVALID_OPERATION);
4685 }
4686
4687 if(!program->setUniform4iv(location, count, v))
4688 {
4689 return error(GL_INVALID_OPERATION);
4690 }
4691 }
4692}
4693
4694void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
4695{
4696 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
4697 location, count, transpose, value);
4698
4699 if(count < 0 || transpose != GL_FALSE)
4700 {
4701 return error(GL_INVALID_VALUE);
4702 }
4703
4704 if(location == -1)
4705 {
4706 return;
4707 }
4708
4709 es2::Context *context = es2::getContext();
4710
4711 if(context)
4712 {
4713 es2::Program *program = context->getCurrentProgram();
4714
4715 if(!program)
4716 {
4717 return error(GL_INVALID_OPERATION);
4718 }
4719
4720 if(!program->setUniformMatrix2fv(location, count, value))
4721 {
4722 return error(GL_INVALID_OPERATION);
4723 }
4724 }
4725}
4726
4727void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
4728{
4729 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
4730 location, count, transpose, value);
4731
4732 if(count < 0 || transpose != GL_FALSE)
4733 {
4734 return error(GL_INVALID_VALUE);
4735 }
4736
4737 if(location == -1)
4738 {
4739 return;
4740 }
4741
4742 es2::Context *context = es2::getContext();
4743
4744 if(context)
4745 {
4746 es2::Program *program = context->getCurrentProgram();
4747
4748 if(!program)
4749 {
4750 return error(GL_INVALID_OPERATION);
4751 }
4752
4753 if(!program->setUniformMatrix3fv(location, count, value))
4754 {
4755 return error(GL_INVALID_OPERATION);
4756 }
4757 }
4758}
4759
4760void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
4761{
4762 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
4763 location, count, transpose, value);
4764
4765 if(count < 0 || transpose != GL_FALSE)
4766 {
4767 return error(GL_INVALID_VALUE);
4768 }
4769
4770 if(location == -1)
4771 {
4772 return;
4773 }
4774
4775 es2::Context *context = es2::getContext();
4776
4777 if(context)
4778 {
4779 es2::Program *program = context->getCurrentProgram();
4780
4781 if(!program)
4782 {
4783 return error(GL_INVALID_OPERATION);
4784 }
4785
4786 if(!program->setUniformMatrix4fv(location, count, value))
4787 {
4788 return error(GL_INVALID_OPERATION);
4789 }
4790 }
4791}
4792
4793void GL_APIENTRY glUseProgram(GLuint program)
4794{
4795 TRACE("(GLuint program = %d)", program);
4796
4797 es2::Context *context = es2::getContext();
4798
4799 if(context)
4800 {
4801 es2::Program *programObject = context->getProgram(program);
4802
4803 if(!programObject && program != 0)
4804 {
4805 if(context->getShader(program))
4806 {
4807 return error(GL_INVALID_OPERATION);
4808 }
4809 else
4810 {
4811 return error(GL_INVALID_VALUE);
4812 }
4813 }
4814
4815 if(program != 0 && !programObject->isLinked())
4816 {
4817 return error(GL_INVALID_OPERATION);
4818 }
4819
4820 context->useProgram(program);
4821 }
4822}
4823
4824void GL_APIENTRY glValidateProgram(GLuint program)
4825{
4826 TRACE("(GLuint program = %d)", program);
4827
4828 es2::Context *context = es2::getContext();
4829
4830 if(context)
4831 {
4832 es2::Program *programObject = context->getProgram(program);
4833
4834 if(!programObject)
4835 {
4836 if(context->getShader(program))
4837 {
4838 return error(GL_INVALID_OPERATION);
4839 }
4840 else
4841 {
4842 return error(GL_INVALID_VALUE);
4843 }
4844 }
4845
4846 programObject->validate();
4847 }
4848}
4849
4850void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)
4851{
4852 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
4853
4854 if(index >= es2::MAX_VERTEX_ATTRIBS)
4855 {
4856 return error(GL_INVALID_VALUE);
4857 }
4858
4859 es2::Context *context = es2::getContext();
4860
4861 if(context)
4862 {
4863 GLfloat vals[4] = { x, 0, 0, 1 };
4864 context->setVertexAttrib(index, vals);
4865 }
4866}
4867
4868void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)
4869{
4870 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
4871
4872 if(index >= es2::MAX_VERTEX_ATTRIBS)
4873 {
4874 return error(GL_INVALID_VALUE);
4875 }
4876
4877 es2::Context *context = es2::getContext();
4878
4879 if(context)
4880 {
4881 GLfloat vals[4] = { values[0], 0, 0, 1 };
4882 context->setVertexAttrib(index, vals);
4883 }
4884}
4885
4886void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
4887{
4888 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
4889
4890 if(index >= es2::MAX_VERTEX_ATTRIBS)
4891 {
4892 return error(GL_INVALID_VALUE);
4893 }
4894
4895 es2::Context *context = es2::getContext();
4896
4897 if(context)
4898 {
4899 GLfloat vals[4] = { x, y, 0, 1 };
4900 context->setVertexAttrib(index, vals);
4901 }
4902}
4903
4904void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)
4905{
4906 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
4907
4908 if(index >= es2::MAX_VERTEX_ATTRIBS)
4909 {
4910 return error(GL_INVALID_VALUE);
4911 }
4912
4913 es2::Context *context = es2::getContext();
4914
4915 if(context)
4916 {
4917 GLfloat vals[4] = { values[0], values[1], 0, 1 };
4918 context->setVertexAttrib(index, vals);
4919 }
4920}
4921
4922void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
4923{
4924 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
4925
4926 if(index >= es2::MAX_VERTEX_ATTRIBS)
4927 {
4928 return error(GL_INVALID_VALUE);
4929 }
4930
4931 es2::Context *context = es2::getContext();
4932
4933 if(context)
4934 {
4935 GLfloat vals[4] = { x, y, z, 1 };
4936 context->setVertexAttrib(index, vals);
4937 }
4938}
4939
4940void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)
4941{
4942 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
4943
4944 if(index >= es2::MAX_VERTEX_ATTRIBS)
4945 {
4946 return error(GL_INVALID_VALUE);
4947 }
4948
4949 es2::Context *context = es2::getContext();
4950
4951 if(context)
4952 {
4953 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
4954 context->setVertexAttrib(index, vals);
4955 }
4956}
4957
4958void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
4959{
4960 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
4961
4962 if(index >= es2::MAX_VERTEX_ATTRIBS)
4963 {
4964 return error(GL_INVALID_VALUE);
4965 }
4966
4967 es2::Context *context = es2::getContext();
4968
4969 if(context)
4970 {
4971 GLfloat vals[4] = { x, y, z, w };
4972 context->setVertexAttrib(index, vals);
4973 }
4974}
4975
4976void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)
4977{
4978 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
4979
4980 if(index >= es2::MAX_VERTEX_ATTRIBS)
4981 {
4982 return error(GL_INVALID_VALUE);
4983 }
4984
4985 es2::Context *context = es2::getContext();
4986
4987 if(context)
4988 {
4989 context->setVertexAttrib(index, values);
4990 }
4991}
4992
4993void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
4994{
4995 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
4996 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
4997 index, size, type, normalized, stride, ptr);
4998
4999 if(index >= es2::MAX_VERTEX_ATTRIBS)
5000 {
5001 return error(GL_INVALID_VALUE);
5002 }
5003
5004 if(size < 1 || size > 4)
5005 {
5006 return error(GL_INVALID_VALUE);
5007 }
5008
5009 switch(type)
5010 {
5011 case GL_BYTE:
5012 case GL_UNSIGNED_BYTE:
5013 case GL_SHORT:
5014 case GL_UNSIGNED_SHORT:
5015 case GL_FIXED:
5016 case GL_FLOAT:
5017 break;
5018 default:
5019 return error(GL_INVALID_ENUM);
5020 }
5021
5022 if(stride < 0)
5023 {
5024 return error(GL_INVALID_VALUE);
5025 }
5026
5027 es2::Context *context = es2::getContext();
5028
5029 if(context)
5030 {
5031 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
5032 }
5033}
5034
5035void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
5036{
5037 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5038
5039 if(width < 0 || height < 0)
5040 {
5041 return error(GL_INVALID_VALUE);
5042 }
5043
5044 es2::Context *context = es2::getContext();
5045
5046 if(context)
5047 {
5048 context->setViewportParams(x, y, width, height);
5049 }
5050}
5051
5052void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5053 GLbitfield mask, GLenum filter)
5054{
5055 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5056 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5057 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5058 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5059
5060 switch(filter)
5061 {
5062 case GL_NEAREST:
5063 break;
5064 default:
5065 return error(GL_INVALID_ENUM);
5066 }
5067
5068 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5069 {
5070 return error(GL_INVALID_VALUE);
5071 }
5072
5073 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5074 {
5075 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5076 return error(GL_INVALID_OPERATION);
5077 }
5078
5079 es2::Context *context = es2::getContext();
5080
5081 if(context)
5082 {
5083 if(context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
5084 {
5085 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5086 return error(GL_INVALID_OPERATION);
5087 }
5088
5089 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
5090 }
5091}
5092
5093void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
5094 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
5095{
5096 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5097 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
5098 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
5099 target, level, internalformat, width, height, depth, border, format, type, pixels);
5100
5101 UNIMPLEMENTED(); // FIXME
5102}
5103
5104void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
5105{
5106 if(egl::getClientVersion() == 1)
5107 {
5108 static auto glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)es1::getProcAddress("glEGLImageTargetTexture2DOES");
5109 return glEGLImageTargetTexture2DOES(target, image);
5110 }
5111
5112 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
5113
5114 switch(target)
5115 {
5116 case GL_TEXTURE_2D:
5117 case GL_TEXTURE_EXTERNAL_OES:
5118 break;
5119 default:
5120 return error(GL_INVALID_ENUM);
5121 }
5122
5123 if(!image)
5124 {
5125 return error(GL_INVALID_OPERATION);
5126 }
5127
5128 es2::Context *context = es2::getContext();
5129
5130 if(context)
5131 {
5132 es2::Texture2D *texture = 0;
5133
5134 switch(target)
5135 {
5136 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
5137 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
5138 default: UNREACHABLE();
5139 }
5140
5141 if(!texture)
5142 {
5143 return error(GL_INVALID_OPERATION);
5144 }
5145
5146 egl::Image *glImage = static_cast<egl::Image*>(image);
5147
5148 texture->setImage(glImage);
5149 }
5150}
5151
5152void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
5153{
5154 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
5155
5156 UNIMPLEMENTED();
5157}
5158
5159__eglMustCastToProperFunctionPointerType glGetProcAddress(const char *procname)
5160{
5161 struct Extension
5162 {
5163 const char *name;
5164 __eglMustCastToProperFunctionPointerType address;
5165 };
5166
5167 static const Extension glExtensions[] =
5168 {
5169 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
5170
5171 EXTENSION(glTexImage3DOES),
5172 EXTENSION(glBlitFramebufferANGLE),
5173 EXTENSION(glRenderbufferStorageMultisampleANGLE),
5174 EXTENSION(glDeleteFencesNV),
5175 EXTENSION(glGenFencesNV),
5176 EXTENSION(glIsFenceNV),
5177 EXTENSION(glTestFenceNV),
5178 EXTENSION(glGetFenceivNV),
5179 EXTENSION(glFinishFenceNV),
5180 EXTENSION(glSetFenceNV),
5181 EXTENSION(glGetGraphicsResetStatusEXT),
5182 EXTENSION(glReadnPixelsEXT),
5183 EXTENSION(glGetnUniformfvEXT),
5184 EXTENSION(glGetnUniformivEXT),
5185 EXTENSION(glGenQueriesEXT),
5186 EXTENSION(glDeleteQueriesEXT),
5187 EXTENSION(glIsQueryEXT),
5188 EXTENSION(glBeginQueryEXT),
5189 EXTENSION(glEndQueryEXT),
5190 EXTENSION(glGetQueryivEXT),
5191 EXTENSION(glGetQueryObjectuivEXT),
5192 EXTENSION(glEGLImageTargetTexture2DOES),
5193 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
5194
5195 #undef EXTENSION
5196 };
5197
5198 for(int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
5199 {
5200 if(strcmp(procname, glExtensions[ext].name) == 0)
5201 {
5202 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
5203 }
5204 }
5205
5206 return NULL;
5207}
5208
5209void GL_APIENTRY Register(const char *licenseKey)
5210{
5211 RegisterLicenseKey(licenseKey);
5212}
5213
5214}