blob: cf263dc3eb74e63562413a89c54a4aba00374128 [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001// 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//
11// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
12
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"
John Baumand4ae8632014-05-06 16:18:33 -040027#include "Main/Register.hpp"
John Bauman66b8ab22014-05-06 15:57:45 -040028
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{
Nicolas Capens14ee7622014-10-28 23:48:41 -040038 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
John Bauman66b8ab22014-05-06 15:57:45 -040039 {
40 return false;
41 }
42
43 return true;
44}
45
Nicolas Capens14ee7622014-10-28 23:48:41 -040046static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)
John Bauman66b8ab22014-05-06 15:57:45 -040047{
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;
Nicolas Capens14ee7622014-10-28 23:48:41 -0400106 case es2::IMPLEMENTATION_COLOR_READ_FORMAT:
John Bauman66b8ab22014-05-06 15:57:45 -0400107 switch (type)
108 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400109 case es2::IMPLEMENTATION_COLOR_READ_TYPE:
John Bauman66b8ab22014-05-06 15:57:45 -0400110 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 try
130 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400131 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400132
133 if(context)
134 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400135 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
John Bauman66b8ab22014-05-06 15:57:45 -0400136 {
137 return error(GL_INVALID_ENUM);
138 }
139
140 context->setActiveSampler(texture - GL_TEXTURE0);
141 }
142 }
143 catch(std::bad_alloc&)
144 {
145 return error(GL_OUT_OF_MEMORY);
146 }
147}
148
149void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
150{
151 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
152
153 try
154 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400155 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400156
157 if(context)
158 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400159 es2::Program *programObject = context->getProgram(program);
160 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400161
162 if(!programObject)
163 {
164 if(context->getShader(program))
165 {
166 return error(GL_INVALID_OPERATION);
167 }
168 else
169 {
170 return error(GL_INVALID_VALUE);
171 }
172 }
173
174 if(!shaderObject)
175 {
176 if(context->getProgram(shader))
177 {
178 return error(GL_INVALID_OPERATION);
179 }
180 else
181 {
182 return error(GL_INVALID_VALUE);
183 }
184 }
185
186 if(!programObject->attachShader(shaderObject))
187 {
188 return error(GL_INVALID_OPERATION);
189 }
190 }
191 }
192 catch(std::bad_alloc&)
193 {
194 return error(GL_OUT_OF_MEMORY);
195 }
196}
197
198void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
199{
200 TRACE("(GLenum target = 0x%X, GLuint %d)", target, id);
201
202 try
203 {
204 switch(target)
205 {
206 case GL_ANY_SAMPLES_PASSED_EXT:
207 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
208 break;
209 default:
210 return error(GL_INVALID_ENUM);
211 }
212
213 if(id == 0)
214 {
215 return error(GL_INVALID_OPERATION);
216 }
217
Nicolas Capens14ee7622014-10-28 23:48:41 -0400218 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400219
220 if(context)
221 {
222 context->beginQuery(target, id);
223 }
224 }
225 catch(std::bad_alloc&)
226 {
227 return error(GL_OUT_OF_MEMORY);
228 }
229}
230
231void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
232{
Nicolas Capens7e12ac62014-11-05 17:07:53 -0500233 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
John Bauman66b8ab22014-05-06 15:57:45 -0400234
235 try
236 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400237 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -0400238 {
239 return error(GL_INVALID_VALUE);
240 }
241
Nicolas Capens14ee7622014-10-28 23:48:41 -0400242 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400243
244 if(context)
245 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400246 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -0400247
248 if(!programObject)
249 {
250 if(context->getShader(program))
251 {
252 return error(GL_INVALID_OPERATION);
253 }
254 else
255 {
256 return error(GL_INVALID_VALUE);
257 }
258 }
259
260 if(strncmp(name, "gl_", 3) == 0)
261 {
262 return error(GL_INVALID_OPERATION);
263 }
264
265 programObject->bindAttributeLocation(index, name);
266 }
267 }
268 catch(std::bad_alloc&)
269 {
270 return error(GL_OUT_OF_MEMORY);
271 }
272}
273
274void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
275{
276 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
277
278 try
279 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400280 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400281
282 if(context)
283 {
284 switch(target)
285 {
286 case GL_ARRAY_BUFFER:
287 context->bindArrayBuffer(buffer);
288 return;
289 case GL_ELEMENT_ARRAY_BUFFER:
290 context->bindElementArrayBuffer(buffer);
291 return;
292 default:
293 return error(GL_INVALID_ENUM);
294 }
295 }
296 }
297 catch(std::bad_alloc&)
298 {
299 return error(GL_OUT_OF_MEMORY);
300 }
301}
302
303void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
304{
305 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
306
307 try
308 {
309 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
310 {
311 return error(GL_INVALID_ENUM);
312 }
313
Nicolas Capens14ee7622014-10-28 23:48:41 -0400314 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400315
316 if(context)
317 {
318 if(target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
319 {
320 context->bindReadFramebuffer(framebuffer);
321 }
322
323 if(target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
324 {
325 context->bindDrawFramebuffer(framebuffer);
326 }
327 }
328 }
329 catch(std::bad_alloc&)
330 {
331 return error(GL_OUT_OF_MEMORY);
332 }
333}
334
335void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
336{
337 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
338
339 try
340 {
341 if(target != GL_RENDERBUFFER)
342 {
343 return error(GL_INVALID_ENUM);
344 }
345
Nicolas Capens14ee7622014-10-28 23:48:41 -0400346 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400347
348 if(context)
349 {
350 context->bindRenderbuffer(renderbuffer);
351 }
352 }
353 catch(std::bad_alloc&)
354 {
355 return error(GL_OUT_OF_MEMORY);
356 }
357}
358
359void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
360{
361 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
362
363 try
364 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400365 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400366
367 if(context)
368 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400369 es2::Texture *textureObject = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -0400370
371 if(textureObject && textureObject->getTarget() != target && texture != 0)
372 {
373 return error(GL_INVALID_OPERATION);
374 }
375
376 switch(target)
377 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -0400378 case GL_TEXTURE_2D:
John Bauman66b8ab22014-05-06 15:57:45 -0400379 context->bindTexture2D(texture);
380 return;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -0400381 case GL_TEXTURE_CUBE_MAP:
John Bauman66b8ab22014-05-06 15:57:45 -0400382 context->bindTextureCubeMap(texture);
383 return;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -0400384 case GL_TEXTURE_EXTERNAL_OES:
385 context->bindTextureExternal(texture);
386 return;
387 default:
John Bauman66b8ab22014-05-06 15:57:45 -0400388 return error(GL_INVALID_ENUM);
389 }
390 }
391 }
392 catch(std::bad_alloc&)
393 {
394 return error(GL_OUT_OF_MEMORY);
395 }
396}
397
398void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
399{
400 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
401 red, green, blue, alpha);
402
403 try
404 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400405 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400406
407 if(context)
408 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400409 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
John Bauman66b8ab22014-05-06 15:57:45 -0400410 }
411 }
412 catch(std::bad_alloc&)
413 {
414 return error(GL_OUT_OF_MEMORY);
415 }
416}
417
418void GL_APIENTRY glBlendEquation(GLenum mode)
419{
420 glBlendEquationSeparate(mode, mode);
421}
422
423void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
424{
425 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
426
427 try
428 {
429 switch(modeRGB)
430 {
Nicolas Capensae799b12014-05-13 10:34:00 -0400431 case GL_FUNC_ADD:
432 case GL_FUNC_SUBTRACT:
433 case GL_FUNC_REVERSE_SUBTRACT:
Nicolas Capense9c5e4f2014-05-28 22:46:43 -0400434 case GL_MIN_EXT:
Nicolas Capensae799b12014-05-13 10:34:00 -0400435 case GL_MAX_EXT:
John Bauman66b8ab22014-05-06 15:57:45 -0400436 break;
Nicolas Capensae799b12014-05-13 10:34:00 -0400437 default:
John Bauman66b8ab22014-05-06 15:57:45 -0400438 return error(GL_INVALID_ENUM);
439 }
440
441 switch(modeAlpha)
442 {
Nicolas Capensae799b12014-05-13 10:34:00 -0400443 case GL_FUNC_ADD:
444 case GL_FUNC_SUBTRACT:
445 case GL_FUNC_REVERSE_SUBTRACT:
Nicolas Capense9c5e4f2014-05-28 22:46:43 -0400446 case GL_MIN_EXT:
Nicolas Capensae799b12014-05-13 10:34:00 -0400447 case GL_MAX_EXT:
John Bauman66b8ab22014-05-06 15:57:45 -0400448 break;
Nicolas Capensae799b12014-05-13 10:34:00 -0400449 default:
John Bauman66b8ab22014-05-06 15:57:45 -0400450 return error(GL_INVALID_ENUM);
451 }
452
Nicolas Capens14ee7622014-10-28 23:48:41 -0400453 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400454
455 if(context)
456 {
457 context->setBlendEquation(modeRGB, modeAlpha);
458 }
459 }
460 catch(std::bad_alloc&)
461 {
462 return error(GL_OUT_OF_MEMORY);
463 }
464}
465
466void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
467{
468 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
469}
470
471void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
472{
473 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
474 srcRGB, dstRGB, srcAlpha, dstAlpha);
475
476 try
477 {
478 switch(srcRGB)
479 {
480 case GL_ZERO:
481 case GL_ONE:
482 case GL_SRC_COLOR:
483 case GL_ONE_MINUS_SRC_COLOR:
484 case GL_DST_COLOR:
485 case GL_ONE_MINUS_DST_COLOR:
486 case GL_SRC_ALPHA:
487 case GL_ONE_MINUS_SRC_ALPHA:
488 case GL_DST_ALPHA:
489 case GL_ONE_MINUS_DST_ALPHA:
490 case GL_CONSTANT_COLOR:
491 case GL_ONE_MINUS_CONSTANT_COLOR:
492 case GL_CONSTANT_ALPHA:
493 case GL_ONE_MINUS_CONSTANT_ALPHA:
494 case GL_SRC_ALPHA_SATURATE:
495 break;
496 default:
497 return error(GL_INVALID_ENUM);
498 }
499
500 switch(dstRGB)
501 {
502 case GL_ZERO:
503 case GL_ONE:
504 case GL_SRC_COLOR:
505 case GL_ONE_MINUS_SRC_COLOR:
506 case GL_DST_COLOR:
507 case GL_ONE_MINUS_DST_COLOR:
508 case GL_SRC_ALPHA:
509 case GL_ONE_MINUS_SRC_ALPHA:
510 case GL_DST_ALPHA:
511 case GL_ONE_MINUS_DST_ALPHA:
512 case GL_CONSTANT_COLOR:
513 case GL_ONE_MINUS_CONSTANT_COLOR:
514 case GL_CONSTANT_ALPHA:
515 case GL_ONE_MINUS_CONSTANT_ALPHA:
516 break;
517 default:
518 return error(GL_INVALID_ENUM);
519 }
520
521 switch(srcAlpha)
522 {
523 case GL_ZERO:
524 case GL_ONE:
525 case GL_SRC_COLOR:
526 case GL_ONE_MINUS_SRC_COLOR:
527 case GL_DST_COLOR:
528 case GL_ONE_MINUS_DST_COLOR:
529 case GL_SRC_ALPHA:
530 case GL_ONE_MINUS_SRC_ALPHA:
531 case GL_DST_ALPHA:
532 case GL_ONE_MINUS_DST_ALPHA:
533 case GL_CONSTANT_COLOR:
534 case GL_ONE_MINUS_CONSTANT_COLOR:
535 case GL_CONSTANT_ALPHA:
536 case GL_ONE_MINUS_CONSTANT_ALPHA:
537 case GL_SRC_ALPHA_SATURATE:
538 break;
539 default:
540 return error(GL_INVALID_ENUM);
541 }
542
543 switch(dstAlpha)
544 {
545 case GL_ZERO:
546 case GL_ONE:
547 case GL_SRC_COLOR:
548 case GL_ONE_MINUS_SRC_COLOR:
549 case GL_DST_COLOR:
550 case GL_ONE_MINUS_DST_COLOR:
551 case GL_SRC_ALPHA:
552 case GL_ONE_MINUS_SRC_ALPHA:
553 case GL_DST_ALPHA:
554 case GL_ONE_MINUS_DST_ALPHA:
555 case GL_CONSTANT_COLOR:
556 case GL_ONE_MINUS_CONSTANT_COLOR:
557 case GL_CONSTANT_ALPHA:
558 case GL_ONE_MINUS_CONSTANT_ALPHA:
559 break;
560 default:
561 return error(GL_INVALID_ENUM);
562 }
563
Nicolas Capens14ee7622014-10-28 23:48:41 -0400564 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400565
566 if(context)
567 {
568 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
569 }
570 }
571 catch(std::bad_alloc&)
572 {
573 return error(GL_OUT_OF_MEMORY);
574 }
575}
576
577void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
578{
579 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
580 target, size, data, usage);
581
582 try
583 {
584 if(size < 0)
585 {
586 return error(GL_INVALID_VALUE);
587 }
588
589 switch(usage)
590 {
591 case GL_STREAM_DRAW:
592 case GL_STATIC_DRAW:
593 case GL_DYNAMIC_DRAW:
594 break;
595 default:
596 return error(GL_INVALID_ENUM);
597 }
598
Nicolas Capens14ee7622014-10-28 23:48:41 -0400599 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400600
601 if(context)
602 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400603 es2::Buffer *buffer;
John Bauman66b8ab22014-05-06 15:57:45 -0400604
605 switch(target)
606 {
607 case GL_ARRAY_BUFFER:
608 buffer = context->getArrayBuffer();
609 break;
610 case GL_ELEMENT_ARRAY_BUFFER:
611 buffer = context->getElementArrayBuffer();
612 break;
613 default:
614 return error(GL_INVALID_ENUM);
615 }
616
617 if(!buffer)
618 {
619 return error(GL_INVALID_OPERATION);
620 }
621
622 buffer->bufferData(data, size, usage);
623 }
624 }
625 catch(std::bad_alloc&)
626 {
627 return error(GL_OUT_OF_MEMORY);
628 }
629}
630
631void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
632{
633 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
634 target, offset, size, data);
635
636 try
637 {
638 if(size < 0 || offset < 0)
639 {
640 return error(GL_INVALID_VALUE);
641 }
642
643 if(data == NULL)
644 {
645 return;
646 }
647
Nicolas Capens14ee7622014-10-28 23:48:41 -0400648 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400649
650 if(context)
651 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400652 es2::Buffer *buffer;
John Bauman66b8ab22014-05-06 15:57:45 -0400653
654 switch(target)
655 {
656 case GL_ARRAY_BUFFER:
657 buffer = context->getArrayBuffer();
658 break;
659 case GL_ELEMENT_ARRAY_BUFFER:
660 buffer = context->getElementArrayBuffer();
661 break;
662 default:
663 return error(GL_INVALID_ENUM);
664 }
665
666 if(!buffer)
667 {
668 return error(GL_INVALID_OPERATION);
669 }
670
671 if((size_t)size + offset > buffer->size())
672 {
673 return error(GL_INVALID_VALUE);
674 }
675
676 buffer->bufferSubData(data, size, offset);
677 }
678 }
679 catch(std::bad_alloc&)
680 {
681 return error(GL_OUT_OF_MEMORY);
682 }
683}
684
685GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
686{
687 TRACE("(GLenum target = 0x%X)", target);
688
689 try
690 {
691 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
692 {
693 return error(GL_INVALID_ENUM, 0);
694 }
695
Nicolas Capens14ee7622014-10-28 23:48:41 -0400696 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400697
698 if(context)
699 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400700 es2::Framebuffer *framebuffer = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -0400701 if(target == GL_READ_FRAMEBUFFER_ANGLE)
702 {
703 framebuffer = context->getReadFramebuffer();
704 }
705 else
706 {
707 framebuffer = context->getDrawFramebuffer();
708 }
709
710 return framebuffer->completeness();
711 }
712 }
713 catch(std::bad_alloc&)
714 {
715 return error(GL_OUT_OF_MEMORY, 0);
716 }
717
718 return 0;
719}
720
721void GL_APIENTRY glClear(GLbitfield mask)
722{
723 TRACE("(GLbitfield mask = %X)", mask);
724
725 try
726 {
727 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
728 {
729 return error(GL_INVALID_VALUE);
730 }
731
Nicolas Capens14ee7622014-10-28 23:48:41 -0400732 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400733
734 if(context)
735 {
736 context->clear(mask);
737 }
738 }
739 catch(std::bad_alloc&)
740 {
741 return error(GL_OUT_OF_MEMORY);
742 }
743}
744
745void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
746{
747 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
748 red, green, blue, alpha);
749
750 try
751 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400752 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400753
754 if(context)
755 {
756 context->setClearColor(red, green, blue, alpha);
757 }
758 }
759 catch(std::bad_alloc&)
760 {
761 return error(GL_OUT_OF_MEMORY);
762 }
763}
764
765void GL_APIENTRY glClearDepthf(GLclampf depth)
766{
767 TRACE("(GLclampf depth = %f)", depth);
768
769 try
770 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400771 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400772
773 if(context)
774 {
775 context->setClearDepth(depth);
776 }
777 }
778 catch(std::bad_alloc&)
779 {
780 return error(GL_OUT_OF_MEMORY);
781 }
782}
783
784void GL_APIENTRY glClearStencil(GLint s)
785{
786 TRACE("(GLint s = %d)", s);
787
788 try
789 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400790 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400791
792 if(context)
793 {
794 context->setClearStencil(s);
795 }
796 }
797 catch(std::bad_alloc&)
798 {
799 return error(GL_OUT_OF_MEMORY);
800 }
801}
802
803void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
804{
805 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
806 red, green, blue, alpha);
807
808 try
809 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400810 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400811
812 if(context)
813 {
814 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
815 }
816 }
817 catch(std::bad_alloc&)
818 {
819 return error(GL_OUT_OF_MEMORY);
820 }
821}
822
823void GL_APIENTRY glCompileShader(GLuint shader)
824{
825 TRACE("(GLuint shader = %d)", shader);
826
827 try
828 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400829 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400830
831 if(context)
832 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400833 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400834
835 if(!shaderObject)
836 {
837 if(context->getProgram(shader))
838 {
839 return error(GL_INVALID_OPERATION);
840 }
841 else
842 {
843 return error(GL_INVALID_VALUE);
844 }
845 }
846
847 shaderObject->compile();
848 }
849 }
850 catch(std::bad_alloc&)
851 {
852 return error(GL_OUT_OF_MEMORY);
853 }
854}
855
856void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
857 GLint border, GLsizei imageSize, const GLvoid* data)
858{
859 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
860 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
861 target, level, internalformat, width, height, border, imageSize, data);
862
863 try
864 {
865 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
866 {
867 return error(GL_INVALID_VALUE);
868 }
869
870 switch(internalformat)
871 {
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 case GL_DEPTH_COMPONENT:
882 case GL_DEPTH_COMPONENT16:
883 case GL_DEPTH_COMPONENT32_OES:
884 case GL_DEPTH_STENCIL_OES:
885 case GL_DEPTH24_STENCIL8_OES:
886 return error(GL_INVALID_OPERATION);
887 default:
888 return error(GL_INVALID_ENUM);
889 }
890
891 if(border != 0)
892 {
893 return error(GL_INVALID_VALUE);
894 }
895
Nicolas Capens14ee7622014-10-28 23:48:41 -0400896 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400897
898 if(context)
899 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400900 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
John Bauman66b8ab22014-05-06 15:57:45 -0400901 {
902 return error(GL_INVALID_VALUE);
903 }
904
905 switch(target)
906 {
907 case GL_TEXTURE_2D:
Nicolas Capens14ee7622014-10-28 23:48:41 -0400908 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
909 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -0400910 {
911 return error(GL_INVALID_VALUE);
912 }
913 break;
914 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
915 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
916 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
917 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
918 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
919 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
920 if(width != height)
921 {
922 return error(GL_INVALID_VALUE);
923 }
924
Nicolas Capens14ee7622014-10-28 23:48:41 -0400925 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
926 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -0400927 {
928 return error(GL_INVALID_VALUE);
929 }
930 break;
931 default:
932 return error(GL_INVALID_ENUM);
933 }
934
Nicolas Capens14ee7622014-10-28 23:48:41 -0400935 if(imageSize != es2::ComputeCompressedSize(width, height, internalformat))
John Bauman66b8ab22014-05-06 15:57:45 -0400936 {
937 return error(GL_INVALID_VALUE);
938 }
939
940 if(target == GL_TEXTURE_2D)
941 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400942 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -0400943
944 if(!texture)
945 {
946 return error(GL_INVALID_OPERATION);
947 }
948
949 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
950 }
951 else
952 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400953 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -0400954
955 if(!texture)
956 {
957 return error(GL_INVALID_OPERATION);
958 }
959
960 switch(target)
961 {
962 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
968 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
969 break;
970 default: UNREACHABLE();
971 }
972 }
973 }
974 }
975 catch(std::bad_alloc&)
976 {
977 return error(GL_OUT_OF_MEMORY);
978 }
979}
980
981void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
982 GLenum format, GLsizei imageSize, const GLvoid* data)
983{
984 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
985 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
986 "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
987 target, level, xoffset, yoffset, width, height, format, imageSize, data);
988
989 try
990 {
Nicolas Capens14ee7622014-10-28 23:48:41 -0400991 if(!es2::IsTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -0400992 {
993 return error(GL_INVALID_ENUM);
994 }
995
996 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
997 {
998 return error(GL_INVALID_VALUE);
999 }
1000
1001 switch(format)
1002 {
1003 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1004 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1005 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1006 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1007 if(!S3TC_SUPPORT)
1008 {
1009 return error(GL_INVALID_ENUM);
1010 }
1011 break;
1012 default:
1013 return error(GL_INVALID_ENUM);
1014 }
1015
1016 if(width == 0 || height == 0 || data == NULL)
1017 {
1018 return;
1019 }
1020
Nicolas Capens14ee7622014-10-28 23:48:41 -04001021 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001022
1023 if(context)
1024 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001025 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
John Bauman66b8ab22014-05-06 15:57:45 -04001026 {
1027 return error(GL_INVALID_VALUE);
1028 }
1029
Nicolas Capens14ee7622014-10-28 23:48:41 -04001030 if(imageSize != es2::ComputeCompressedSize(width, height, format))
John Bauman66b8ab22014-05-06 15:57:45 -04001031 {
1032 return error(GL_INVALID_VALUE);
1033 }
1034
1035 if(xoffset % 4 != 0 || yoffset % 4 != 0)
1036 {
1037 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
1038 return error(GL_INVALID_OPERATION);
1039 }
1040
1041 if(target == GL_TEXTURE_2D)
1042 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001043 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04001044
1045 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
1046 {
1047 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
1048 }
1049 }
Nicolas Capens14ee7622014-10-28 23:48:41 -04001050 else if(es2::IsCubemapTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04001051 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001052 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04001053
1054 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
1055 {
1056 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
1057 }
1058 }
1059 else
1060 {
1061 UNREACHABLE();
1062 }
1063 }
1064 }
1065 catch(std::bad_alloc&)
1066 {
1067 return error(GL_OUT_OF_MEMORY);
1068 }
1069}
1070
1071void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
1072{
1073 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
1074 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
1075 target, level, internalformat, x, y, width, height, border);
1076
1077 try
1078 {
1079 if(!validImageSize(level, width, height))
1080 {
1081 return error(GL_INVALID_VALUE);
1082 }
1083
1084 if(border != 0)
1085 {
1086 return error(GL_INVALID_VALUE);
1087 }
1088
Nicolas Capens14ee7622014-10-28 23:48:41 -04001089 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001090
1091 if(context)
1092 {
1093 switch(target)
1094 {
1095 case GL_TEXTURE_2D:
Nicolas Capens14ee7622014-10-28 23:48:41 -04001096 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
1097 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -04001098 {
1099 return error(GL_INVALID_VALUE);
1100 }
1101 break;
1102 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1104 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1105 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1106 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1108 if(width != height)
1109 {
1110 return error(GL_INVALID_VALUE);
1111 }
1112
Nicolas Capens14ee7622014-10-28 23:48:41 -04001113 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
1114 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -04001115 {
1116 return error(GL_INVALID_VALUE);
1117 }
1118 break;
1119 default:
1120 return error(GL_INVALID_ENUM);
1121 }
1122
Nicolas Capens14ee7622014-10-28 23:48:41 -04001123 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001124
1125 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1126 {
1127 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1128 }
1129
John Baumand4ae8632014-05-06 16:18:33 -04001130 if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
John Bauman66b8ab22014-05-06 15:57:45 -04001131 {
1132 return error(GL_INVALID_OPERATION);
1133 }
1134
Nicolas Capens14ee7622014-10-28 23:48:41 -04001135 es2::Renderbuffer *source = framebuffer->getColorbuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001136 GLenum colorbufferFormat = source->getFormat();
1137
1138 // [OpenGL ES 2.0.24] table 3.9
1139 switch(internalformat)
1140 {
1141 case GL_ALPHA:
1142 if(colorbufferFormat != GL_ALPHA &&
1143 colorbufferFormat != GL_RGBA &&
1144 colorbufferFormat != GL_RGBA4 &&
1145 colorbufferFormat != GL_RGB5_A1 &&
1146 colorbufferFormat != GL_RGBA8_OES)
1147 {
1148 return error(GL_INVALID_OPERATION);
1149 }
1150 break;
1151 case GL_LUMINANCE:
1152 case GL_RGB:
1153 if(colorbufferFormat != GL_RGB &&
1154 colorbufferFormat != GL_RGB565 &&
1155 colorbufferFormat != GL_RGB8_OES &&
1156 colorbufferFormat != GL_RGBA &&
1157 colorbufferFormat != GL_RGBA4 &&
1158 colorbufferFormat != GL_RGB5_A1 &&
1159 colorbufferFormat != GL_RGBA8_OES)
1160 {
1161 return error(GL_INVALID_OPERATION);
1162 }
1163 break;
1164 case GL_LUMINANCE_ALPHA:
1165 case GL_RGBA:
1166 if(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_COMPRESSED_RGB_S3TC_DXT1_EXT:
1175 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1176 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1177 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1178 if(S3TC_SUPPORT)
1179 {
1180 return error(GL_INVALID_OPERATION);
1181 }
1182 else
1183 {
1184 return error(GL_INVALID_ENUM);
1185 }
1186 break;
1187 default:
1188 return error(GL_INVALID_ENUM);
1189 }
1190
1191 if(target == GL_TEXTURE_2D)
1192 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001193 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04001194
1195 if(!texture)
1196 {
1197 return error(GL_INVALID_OPERATION);
1198 }
1199
1200 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
1201 }
Nicolas Capens14ee7622014-10-28 23:48:41 -04001202 else if(es2::IsCubemapTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04001203 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001204 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04001205
1206 if(!texture)
1207 {
1208 return error(GL_INVALID_OPERATION);
1209 }
1210
1211 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1212 }
1213 else UNREACHABLE();
1214 }
1215 }
1216 catch(std::bad_alloc&)
1217 {
1218 return error(GL_OUT_OF_MEMORY);
1219 }
1220}
1221
1222void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1223{
1224 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1225 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1226 target, level, xoffset, yoffset, x, y, width, height);
1227
1228 try
1229 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001230 if(!es2::IsTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04001231 {
1232 return error(GL_INVALID_ENUM);
1233 }
1234
1235 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1236 {
1237 return error(GL_INVALID_VALUE);
1238 }
1239
1240 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1241 {
1242 return error(GL_INVALID_VALUE);
1243 }
1244
1245 if(width == 0 || height == 0)
1246 {
1247 return;
1248 }
1249
Nicolas Capens14ee7622014-10-28 23:48:41 -04001250 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001251
1252 if(context)
1253 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001254 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
John Bauman66b8ab22014-05-06 15:57:45 -04001255 {
1256 return error(GL_INVALID_VALUE);
1257 }
1258
Nicolas Capens14ee7622014-10-28 23:48:41 -04001259 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001260
1261 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1262 {
1263 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1264 }
1265
John Baumand4ae8632014-05-06 16:18:33 -04001266 if(context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
John Bauman66b8ab22014-05-06 15:57:45 -04001267 {
1268 return error(GL_INVALID_OPERATION);
1269 }
1270
Nicolas Capens14ee7622014-10-28 23:48:41 -04001271 es2::Renderbuffer *source = framebuffer->getColorbuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001272 GLenum colorbufferFormat = source->getFormat();
Nicolas Capens14ee7622014-10-28 23:48:41 -04001273 es2::Texture *texture = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04001274
1275 if(target == GL_TEXTURE_2D)
1276 {
1277 texture = context->getTexture2D();
1278 }
Nicolas Capens14ee7622014-10-28 23:48:41 -04001279 else if(es2::IsCubemapTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04001280 {
1281 texture = context->getTextureCubeMap();
1282 }
1283 else UNREACHABLE();
1284
1285 if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture))
1286 {
1287 return;
1288 }
1289
1290 GLenum textureFormat = texture->getFormat(target, level);
1291
1292 // [OpenGL ES 2.0.24] table 3.9
1293 switch(textureFormat)
1294 {
1295 case GL_ALPHA:
1296 if(colorbufferFormat != GL_ALPHA &&
1297 colorbufferFormat != GL_RGBA &&
1298 colorbufferFormat != GL_RGBA4 &&
1299 colorbufferFormat != GL_RGB5_A1 &&
1300 colorbufferFormat != GL_RGBA8_OES)
1301 {
1302 return error(GL_INVALID_OPERATION);
1303 }
1304 break;
1305 case GL_LUMINANCE:
1306 case GL_RGB:
1307 if(colorbufferFormat != GL_RGB &&
1308 colorbufferFormat != GL_RGB565 &&
1309 colorbufferFormat != GL_RGB8_OES &&
1310 colorbufferFormat != GL_RGBA &&
1311 colorbufferFormat != GL_RGBA4 &&
1312 colorbufferFormat != GL_RGB5_A1 &&
1313 colorbufferFormat != GL_RGBA8_OES)
1314 {
1315 return error(GL_INVALID_OPERATION);
1316 }
1317 break;
1318 case GL_LUMINANCE_ALPHA:
1319 case GL_RGBA:
1320 if(colorbufferFormat != GL_RGBA &&
1321 colorbufferFormat != GL_RGBA4 &&
1322 colorbufferFormat != GL_RGB5_A1 &&
1323 colorbufferFormat != GL_RGBA8_OES)
1324 {
1325 return error(GL_INVALID_OPERATION);
1326 }
1327 break;
1328 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1329 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1330 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1331 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1332 return error(GL_INVALID_OPERATION);
1333 case GL_DEPTH_COMPONENT:
1334 case GL_DEPTH_STENCIL_OES:
1335 return error(GL_INVALID_OPERATION);
1336 default:
1337 return error(GL_INVALID_OPERATION);
1338 }
1339
1340 texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer);
1341 }
1342 }
1343
1344 catch(std::bad_alloc&)
1345 {
1346 return error(GL_OUT_OF_MEMORY);
1347 }
1348}
1349
1350GLuint GL_APIENTRY glCreateProgram(void)
1351{
1352 TRACE("()");
1353
1354 try
1355 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001356 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001357
1358 if(context)
1359 {
1360 return context->createProgram();
1361 }
1362 }
1363 catch(std::bad_alloc&)
1364 {
1365 return error(GL_OUT_OF_MEMORY, 0);
1366 }
1367
1368 return 0;
1369}
1370
1371GLuint GL_APIENTRY glCreateShader(GLenum type)
1372{
1373 TRACE("(GLenum type = 0x%X)", type);
1374
1375 try
1376 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001377 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001378
1379 if(context)
1380 {
1381 switch(type)
1382 {
1383 case GL_FRAGMENT_SHADER:
1384 case GL_VERTEX_SHADER:
1385 return context->createShader(type);
1386 default:
1387 return error(GL_INVALID_ENUM, 0);
1388 }
1389 }
1390 }
1391 catch(std::bad_alloc&)
1392 {
1393 return error(GL_OUT_OF_MEMORY, 0);
1394 }
1395
1396 return 0;
1397}
1398
1399void GL_APIENTRY glCullFace(GLenum mode)
1400{
1401 TRACE("(GLenum mode = 0x%X)", mode);
1402
1403 try
1404 {
1405 switch(mode)
1406 {
1407 case GL_FRONT:
1408 case GL_BACK:
1409 case GL_FRONT_AND_BACK:
1410 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001411 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001412
1413 if(context)
1414 {
1415 context->setCullMode(mode);
1416 }
1417 }
1418 break;
1419 default:
1420 return error(GL_INVALID_ENUM);
1421 }
1422 }
1423 catch(std::bad_alloc&)
1424 {
1425 return error(GL_OUT_OF_MEMORY);
1426 }
1427}
1428
1429void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
1430{
1431 TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
1432
1433 try
1434 {
1435 if(n < 0)
1436 {
1437 return error(GL_INVALID_VALUE);
1438 }
1439
Nicolas Capens14ee7622014-10-28 23:48:41 -04001440 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001441
1442 if(context)
1443 {
1444 for(int i = 0; i < n; i++)
1445 {
1446 context->deleteBuffer(buffers[i]);
1447 }
1448 }
1449 }
1450 catch(std::bad_alloc&)
1451 {
1452 return error(GL_OUT_OF_MEMORY);
1453 }
1454}
1455
1456void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
1457{
1458 TRACE("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
1459
1460 try
1461 {
1462 if(n < 0)
1463 {
1464 return error(GL_INVALID_VALUE);
1465 }
1466
Nicolas Capens14ee7622014-10-28 23:48:41 -04001467 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001468
1469 if(context)
1470 {
1471 for(int i = 0; i < n; i++)
1472 {
1473 context->deleteFence(fences[i]);
1474 }
1475 }
1476 }
1477 catch(std::bad_alloc&)
1478 {
1479 return error(GL_OUT_OF_MEMORY);
1480 }
1481}
1482
1483void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1484{
1485 TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
1486
1487 try
1488 {
1489 if(n < 0)
1490 {
1491 return error(GL_INVALID_VALUE);
1492 }
1493
Nicolas Capens14ee7622014-10-28 23:48:41 -04001494 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001495
1496 if(context)
1497 {
1498 for(int i = 0; i < n; i++)
1499 {
1500 if(framebuffers[i] != 0)
1501 {
1502 context->deleteFramebuffer(framebuffers[i]);
1503 }
1504 }
1505 }
1506 }
1507 catch(std::bad_alloc&)
1508 {
1509 return error(GL_OUT_OF_MEMORY);
1510 }
1511}
1512
1513void GL_APIENTRY glDeleteProgram(GLuint program)
1514{
1515 TRACE("(GLuint program = %d)", program);
1516
1517 try
1518 {
1519 if(program == 0)
1520 {
1521 return;
1522 }
1523
Nicolas Capens14ee7622014-10-28 23:48:41 -04001524 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001525
1526 if(context)
1527 {
1528 if(!context->getProgram(program))
1529 {
1530 if(context->getShader(program))
1531 {
1532 return error(GL_INVALID_OPERATION);
1533 }
1534 else
1535 {
1536 return error(GL_INVALID_VALUE);
1537 }
1538 }
1539
1540 context->deleteProgram(program);
1541 }
1542 }
1543 catch(std::bad_alloc&)
1544 {
1545 return error(GL_OUT_OF_MEMORY);
1546 }
1547}
1548
1549void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
1550{
1551 TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
1552
1553 try
1554 {
1555 if(n < 0)
1556 {
1557 return error(GL_INVALID_VALUE);
1558 }
1559
Nicolas Capens14ee7622014-10-28 23:48:41 -04001560 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001561
1562 if(context)
1563 {
1564 for(int i = 0; i < n; i++)
1565 {
1566 context->deleteQuery(ids[i]);
1567 }
1568 }
1569 }
1570 catch(std::bad_alloc&)
1571 {
1572 return error(GL_OUT_OF_MEMORY);
1573 }
1574}
1575
1576void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1577{
1578 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
1579
1580 try
1581 {
1582 if(n < 0)
1583 {
1584 return error(GL_INVALID_VALUE);
1585 }
1586
Nicolas Capens14ee7622014-10-28 23:48:41 -04001587 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001588
1589 if(context)
1590 {
1591 for(int i = 0; i < n; i++)
1592 {
1593 context->deleteRenderbuffer(renderbuffers[i]);
1594 }
1595 }
1596 }
1597 catch(std::bad_alloc&)
1598 {
1599 return error(GL_OUT_OF_MEMORY);
1600 }
1601}
1602
1603void GL_APIENTRY glDeleteShader(GLuint shader)
1604{
1605 TRACE("(GLuint shader = %d)", shader);
1606
1607 try
1608 {
1609 if(shader == 0)
1610 {
1611 return;
1612 }
1613
Nicolas Capens14ee7622014-10-28 23:48:41 -04001614 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001615
1616 if(context)
1617 {
1618 if(!context->getShader(shader))
1619 {
1620 if(context->getProgram(shader))
1621 {
1622 return error(GL_INVALID_OPERATION);
1623 }
1624 else
1625 {
1626 return error(GL_INVALID_VALUE);
1627 }
1628 }
1629
1630 context->deleteShader(shader);
1631 }
1632 }
1633 catch(std::bad_alloc&)
1634 {
1635 return error(GL_OUT_OF_MEMORY);
1636 }
1637}
1638
1639void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
1640{
1641 TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
1642
1643 try
1644 {
1645 if(n < 0)
1646 {
1647 return error(GL_INVALID_VALUE);
1648 }
1649
Nicolas Capens14ee7622014-10-28 23:48:41 -04001650 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001651
1652 if(context)
1653 {
1654 for(int i = 0; i < n; i++)
1655 {
1656 if(textures[i] != 0)
1657 {
1658 context->deleteTexture(textures[i]);
1659 }
1660 }
1661 }
1662 }
1663 catch(std::bad_alloc&)
1664 {
1665 return error(GL_OUT_OF_MEMORY);
1666 }
1667}
1668
1669void GL_APIENTRY glDepthFunc(GLenum func)
1670{
1671 TRACE("(GLenum func = 0x%X)", func);
1672
1673 try
1674 {
1675 switch(func)
1676 {
1677 case GL_NEVER:
1678 case GL_ALWAYS:
1679 case GL_LESS:
1680 case GL_LEQUAL:
1681 case GL_EQUAL:
1682 case GL_GREATER:
1683 case GL_GEQUAL:
1684 case GL_NOTEQUAL:
1685 break;
1686 default:
1687 return error(GL_INVALID_ENUM);
1688 }
1689
Nicolas Capens14ee7622014-10-28 23:48:41 -04001690 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001691
1692 if(context)
1693 {
1694 context->setDepthFunc(func);
1695 }
1696 }
1697 catch(std::bad_alloc&)
1698 {
1699 return error(GL_OUT_OF_MEMORY);
1700 }
1701}
1702
1703void GL_APIENTRY glDepthMask(GLboolean flag)
1704{
1705 TRACE("(GLboolean flag = %d)", flag);
1706
1707 try
1708 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001709 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001710
1711 if(context)
1712 {
1713 context->setDepthMask(flag != GL_FALSE);
1714 }
1715 }
1716 catch(std::bad_alloc&)
1717 {
1718 return error(GL_OUT_OF_MEMORY);
1719 }
1720}
1721
1722void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)
1723{
1724 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1725
1726 try
1727 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001728 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001729
1730 if(context)
1731 {
1732 context->setDepthRange(zNear, zFar);
1733 }
1734 }
1735 catch(std::bad_alloc&)
1736 {
1737 return error(GL_OUT_OF_MEMORY);
1738 }
1739}
1740
1741void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
1742{
1743 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1744
1745 try
1746 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001747 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001748
1749 if(context)
1750 {
1751
Nicolas Capens14ee7622014-10-28 23:48:41 -04001752 es2::Program *programObject = context->getProgram(program);
1753 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04001754
1755 if(!programObject)
1756 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001757 es2::Shader *shaderByProgramHandle;
John Bauman66b8ab22014-05-06 15:57:45 -04001758 shaderByProgramHandle = context->getShader(program);
1759 if(!shaderByProgramHandle)
1760 {
1761 return error(GL_INVALID_VALUE);
1762 }
1763 else
1764 {
1765 return error(GL_INVALID_OPERATION);
1766 }
1767 }
1768
1769 if(!shaderObject)
1770 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001771 es2::Program *programByShaderHandle = context->getProgram(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04001772 if(!programByShaderHandle)
1773 {
1774 return error(GL_INVALID_VALUE);
1775 }
1776 else
1777 {
1778 return error(GL_INVALID_OPERATION);
1779 }
1780 }
1781
1782 if(!programObject->detachShader(shaderObject))
1783 {
1784 return error(GL_INVALID_OPERATION);
1785 }
1786 }
1787 }
1788 catch(std::bad_alloc&)
1789 {
1790 return error(GL_OUT_OF_MEMORY);
1791 }
1792}
1793
1794void GL_APIENTRY glDisable(GLenum cap)
1795{
1796 TRACE("(GLenum cap = 0x%X)", cap);
1797
1798 try
1799 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001800 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001801
1802 if(context)
1803 {
1804 switch(cap)
1805 {
1806 case GL_CULL_FACE: context->setCullFace(false); break;
1807 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
1808 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
1809 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
1810 case GL_SCISSOR_TEST: context->setScissorTest(false); break;
1811 case GL_STENCIL_TEST: context->setStencilTest(false); break;
1812 case GL_DEPTH_TEST: context->setDepthTest(false); break;
1813 case GL_BLEND: context->setBlend(false); break;
1814 case GL_DITHER: context->setDither(false); break;
1815 default:
1816 return error(GL_INVALID_ENUM);
1817 }
1818 }
1819 }
1820 catch(std::bad_alloc&)
1821 {
1822 return error(GL_OUT_OF_MEMORY);
1823 }
1824}
1825
1826void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
1827{
1828 TRACE("(GLuint index = %d)", index);
1829
1830 try
1831 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001832 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04001833 {
1834 return error(GL_INVALID_VALUE);
1835 }
1836
Nicolas Capens14ee7622014-10-28 23:48:41 -04001837 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001838
1839 if(context)
1840 {
1841 context->setEnableVertexAttribArray(index, false);
1842 }
1843 }
1844 catch(std::bad_alloc&)
1845 {
1846 return error(GL_OUT_OF_MEMORY);
1847 }
1848}
1849
1850void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
1851{
1852 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1853
1854 try
1855 {
1856 if(count < 0 || first < 0)
1857 {
1858 return error(GL_INVALID_VALUE);
1859 }
1860
Nicolas Capens14ee7622014-10-28 23:48:41 -04001861 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001862
1863 if(context)
1864 {
1865 context->drawArrays(mode, first, count);
1866 }
1867 }
1868 catch(std::bad_alloc&)
1869 {
1870 return error(GL_OUT_OF_MEMORY);
1871 }
1872}
1873
1874void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1875{
1876 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
1877 mode, count, type, indices);
1878
1879 try
1880 {
1881 if(count < 0)
1882 {
1883 return error(GL_INVALID_VALUE);
1884 }
1885
Nicolas Capens14ee7622014-10-28 23:48:41 -04001886 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001887
1888 if(context)
1889 {
1890 switch(type)
1891 {
1892 case GL_UNSIGNED_BYTE:
1893 case GL_UNSIGNED_SHORT:
1894 case GL_UNSIGNED_INT:
1895 break;
1896 default:
1897 return error(GL_INVALID_ENUM);
1898 }
1899
1900 context->drawElements(mode, count, type, indices);
1901 }
1902 }
1903 catch(std::bad_alloc&)
1904 {
1905 return error(GL_OUT_OF_MEMORY);
1906 }
1907}
1908
1909void GL_APIENTRY glEnable(GLenum cap)
1910{
1911 TRACE("(GLenum cap = 0x%X)", cap);
1912
1913 try
1914 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001915 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001916
1917 if(context)
1918 {
1919 switch(cap)
1920 {
1921 case GL_CULL_FACE: context->setCullFace(true); break;
1922 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break;
1923 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
1924 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break;
1925 case GL_SCISSOR_TEST: context->setScissorTest(true); break;
1926 case GL_STENCIL_TEST: context->setStencilTest(true); break;
1927 case GL_DEPTH_TEST: context->setDepthTest(true); break;
1928 case GL_BLEND: context->setBlend(true); break;
1929 case GL_DITHER: context->setDither(true); break;
1930 default:
1931 return error(GL_INVALID_ENUM);
1932 }
1933 }
1934 }
1935 catch(std::bad_alloc&)
1936 {
1937 return error(GL_OUT_OF_MEMORY);
1938 }
1939}
1940
1941void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
1942{
1943 TRACE("(GLuint index = %d)", index);
1944
1945 try
1946 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001947 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04001948 {
1949 return error(GL_INVALID_VALUE);
1950 }
1951
Nicolas Capens14ee7622014-10-28 23:48:41 -04001952 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001953
1954 if(context)
1955 {
1956 context->setEnableVertexAttribArray(index, true);
1957 }
1958 }
1959 catch(std::bad_alloc&)
1960 {
1961 return error(GL_OUT_OF_MEMORY);
1962 }
1963}
1964
1965void GL_APIENTRY glEndQueryEXT(GLenum target)
1966{
1967 TRACE("GLenum target = 0x%X)", target);
1968
1969 try
1970 {
1971 switch(target)
1972 {
1973 case GL_ANY_SAMPLES_PASSED_EXT:
1974 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1975 break;
1976 default:
1977 return error(GL_INVALID_ENUM);
1978 }
1979
Nicolas Capens14ee7622014-10-28 23:48:41 -04001980 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001981
1982 if(context)
1983 {
1984 context->endQuery(target);
1985 }
1986 }
1987 catch(std::bad_alloc&)
1988 {
1989 return error(GL_OUT_OF_MEMORY);
1990 }
1991}
1992
1993void GL_APIENTRY glFinishFenceNV(GLuint fence)
1994{
1995 TRACE("(GLuint fence = %d)", fence);
1996
1997 try
1998 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04001999 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002000
2001 if(context)
2002 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002003 es2::Fence* fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04002004
2005 if(fenceObject == NULL)
2006 {
2007 return error(GL_INVALID_OPERATION);
2008 }
2009
2010 fenceObject->finishFence();
2011 }
2012 }
2013 catch(std::bad_alloc&)
2014 {
2015 return error(GL_OUT_OF_MEMORY);
2016 }
2017}
2018
2019void GL_APIENTRY glFinish(void)
2020{
2021 TRACE("()");
2022
2023 try
2024 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002025 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002026
2027 if(context)
2028 {
2029 context->finish();
2030 }
2031 }
2032 catch(std::bad_alloc&)
2033 {
2034 return error(GL_OUT_OF_MEMORY);
2035 }
2036}
2037
2038void GL_APIENTRY glFlush(void)
2039{
2040 TRACE("()");
2041
2042 try
2043 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002044 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002045
2046 if(context)
2047 {
2048 context->flush();
2049 }
2050 }
2051 catch(std::bad_alloc&)
2052 {
2053 return error(GL_OUT_OF_MEMORY);
2054 }
2055}
2056
2057void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
2058{
2059 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
2060 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
2061
2062 try
2063 {
2064 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2065 || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
2066 {
2067 return error(GL_INVALID_ENUM);
2068 }
2069
Nicolas Capens14ee7622014-10-28 23:48:41 -04002070 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002071
2072 if(context)
2073 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002074 es2::Framebuffer *framebuffer = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04002075 GLuint framebufferHandle = 0;
2076 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2077 {
2078 framebuffer = context->getReadFramebuffer();
2079 framebufferHandle = context->getReadFramebufferHandle();
2080 }
2081 else
2082 {
2083 framebuffer = context->getDrawFramebuffer();
2084 framebufferHandle = context->getDrawFramebufferHandle();
2085 }
2086
2087 if(!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
2088 {
2089 return error(GL_INVALID_OPERATION);
2090 }
2091
2092 switch(attachment)
2093 {
2094 case GL_COLOR_ATTACHMENT0:
2095 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
2096 break;
2097 case GL_DEPTH_ATTACHMENT:
2098 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
2099 break;
2100 case GL_STENCIL_ATTACHMENT:
2101 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
2102 break;
2103 default:
2104 return error(GL_INVALID_ENUM);
2105 }
2106 }
2107 }
2108 catch(std::bad_alloc&)
2109 {
2110 return error(GL_OUT_OF_MEMORY);
2111 }
2112}
2113
2114void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
2115{
2116 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
2117 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
2118
2119 try
2120 {
2121 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2122 {
2123 return error(GL_INVALID_ENUM);
2124 }
2125
2126 switch(attachment)
2127 {
2128 case GL_COLOR_ATTACHMENT0:
2129 case GL_DEPTH_ATTACHMENT:
2130 case GL_STENCIL_ATTACHMENT:
2131 break;
2132 default:
2133 return error(GL_INVALID_ENUM);
2134 }
2135
Nicolas Capens14ee7622014-10-28 23:48:41 -04002136 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002137
2138 if(context)
2139 {
2140 if(texture == 0)
2141 {
2142 textarget = GL_NONE;
2143 }
2144 else
2145 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002146 es2::Texture *tex = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -04002147
2148 if(tex == NULL)
2149 {
2150 return error(GL_INVALID_OPERATION);
2151 }
2152
2153 if(tex->isCompressed(textarget, level))
2154 {
2155 return error(GL_INVALID_OPERATION);
2156 }
2157
2158 switch(textarget)
2159 {
2160 case GL_TEXTURE_2D:
2161 if(tex->getTarget() != GL_TEXTURE_2D)
2162 {
2163 return error(GL_INVALID_OPERATION);
2164 }
2165 break;
2166
2167 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2168 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2169 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2170 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2171 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2172 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2173 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2174 {
2175 return error(GL_INVALID_OPERATION);
2176 }
2177 break;
2178
2179 default:
2180 return error(GL_INVALID_ENUM);
2181 }
2182
2183 if(level != 0)
2184 {
2185 return error(GL_INVALID_VALUE);
2186 }
2187 }
2188
Nicolas Capens14ee7622014-10-28 23:48:41 -04002189 es2::Framebuffer *framebuffer = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04002190 GLuint framebufferHandle = 0;
2191 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2192 {
2193 framebuffer = context->getReadFramebuffer();
2194 framebufferHandle = context->getReadFramebufferHandle();
2195 }
2196 else
2197 {
2198 framebuffer = context->getDrawFramebuffer();
2199 framebufferHandle = context->getDrawFramebufferHandle();
2200 }
2201
2202 if(framebufferHandle == 0 || !framebuffer)
2203 {
2204 return error(GL_INVALID_OPERATION);
2205 }
2206
2207 switch(attachment)
2208 {
2209 case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break;
2210 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
2211 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
2212 }
2213 }
2214 }
2215 catch(std::bad_alloc&)
2216 {
2217 return error(GL_OUT_OF_MEMORY);
2218 }
2219}
2220
2221void GL_APIENTRY glFrontFace(GLenum mode)
2222{
2223 TRACE("(GLenum mode = 0x%X)", mode);
2224
2225 try
2226 {
2227 switch(mode)
2228 {
2229 case GL_CW:
2230 case GL_CCW:
2231 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002232 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002233
2234 if(context)
2235 {
2236 context->setFrontFace(mode);
2237 }
2238 }
2239 break;
2240 default:
2241 return error(GL_INVALID_ENUM);
2242 }
2243 }
2244 catch(std::bad_alloc&)
2245 {
2246 return error(GL_OUT_OF_MEMORY);
2247 }
2248}
2249
2250void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
2251{
2252 TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
2253
2254 try
2255 {
2256 if(n < 0)
2257 {
2258 return error(GL_INVALID_VALUE);
2259 }
2260
Nicolas Capens14ee7622014-10-28 23:48:41 -04002261 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002262
2263 if(context)
2264 {
2265 for(int i = 0; i < n; i++)
2266 {
2267 buffers[i] = context->createBuffer();
2268 }
2269 }
2270 }
2271 catch(std::bad_alloc&)
2272 {
2273 return error(GL_OUT_OF_MEMORY);
2274 }
2275}
2276
2277void GL_APIENTRY glGenerateMipmap(GLenum target)
2278{
2279 TRACE("(GLenum target = 0x%X)", target);
2280
2281 try
2282 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002283 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002284
2285 if(context)
2286 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002287 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04002288
2289 switch(target)
2290 {
2291 case GL_TEXTURE_2D:
2292 texture = context->getTexture2D();
2293 break;
2294 case GL_TEXTURE_CUBE_MAP:
2295 texture = context->getTextureCubeMap();
2296 break;
2297 default:
2298 return error(GL_INVALID_ENUM);
2299 }
2300
2301 if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
2302 {
2303 return error(GL_INVALID_OPERATION);
2304 }
2305
2306 texture->generateMipmaps();
2307 }
2308 }
2309 catch(std::bad_alloc&)
2310 {
2311 return error(GL_OUT_OF_MEMORY);
2312 }
2313}
2314
2315void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
2316{
2317 TRACE("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
2318
2319 try
2320 {
2321 if(n < 0)
2322 {
2323 return error(GL_INVALID_VALUE);
2324 }
2325
Nicolas Capens14ee7622014-10-28 23:48:41 -04002326 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002327
2328 if(context)
2329 {
2330 for(int i = 0; i < n; i++)
2331 {
2332 fences[i] = context->createFence();
2333 }
2334 }
2335 }
2336 catch(std::bad_alloc&)
2337 {
2338 return error(GL_OUT_OF_MEMORY);
2339 }
2340}
2341
2342void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
2343{
2344 TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
2345
2346 try
2347 {
2348 if(n < 0)
2349 {
2350 return error(GL_INVALID_VALUE);
2351 }
2352
Nicolas Capens14ee7622014-10-28 23:48:41 -04002353 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002354
2355 if(context)
2356 {
2357 for(int i = 0; i < n; i++)
2358 {
2359 framebuffers[i] = context->createFramebuffer();
2360 }
2361 }
2362 }
2363 catch(std::bad_alloc&)
2364 {
2365 return error(GL_OUT_OF_MEMORY);
2366 }
2367}
2368
2369void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)
2370{
2371 TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
2372
2373 try
2374 {
2375 if(n < 0)
2376 {
2377 return error(GL_INVALID_VALUE);
2378 }
2379
Nicolas Capens14ee7622014-10-28 23:48:41 -04002380 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002381
2382 if(context)
2383 {
2384 for(int i = 0; i < n; i++)
2385 {
2386 ids[i] = context->createQuery();
2387 }
2388 }
2389 }
2390 catch(std::bad_alloc&)
2391 {
2392 return error(GL_OUT_OF_MEMORY);
2393 }
2394}
2395
2396void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2397{
2398 TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
2399
2400 try
2401 {
2402 if(n < 0)
2403 {
2404 return error(GL_INVALID_VALUE);
2405 }
2406
Nicolas Capens14ee7622014-10-28 23:48:41 -04002407 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002408
2409 if(context)
2410 {
2411 for(int i = 0; i < n; i++)
2412 {
2413 renderbuffers[i] = context->createRenderbuffer();
2414 }
2415 }
2416 }
2417 catch(std::bad_alloc&)
2418 {
2419 return error(GL_OUT_OF_MEMORY);
2420 }
2421}
2422
2423void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
2424{
Nicolas Capens7e12ac62014-11-05 17:07:53 -05002425 TRACE("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
John Bauman66b8ab22014-05-06 15:57:45 -04002426
2427 try
2428 {
2429 if(n < 0)
2430 {
2431 return error(GL_INVALID_VALUE);
2432 }
2433
Nicolas Capens14ee7622014-10-28 23:48:41 -04002434 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002435
2436 if(context)
2437 {
2438 for(int i = 0; i < n; i++)
2439 {
2440 textures[i] = context->createTexture();
2441 }
2442 }
2443 }
2444 catch(std::bad_alloc&)
2445 {
2446 return error(GL_OUT_OF_MEMORY);
2447 }
2448}
2449
2450void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2451{
2452 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
2453 "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
2454 program, index, bufsize, length, size, type, name);
2455
2456 try
2457 {
2458 if(bufsize < 0)
2459 {
2460 return error(GL_INVALID_VALUE);
2461 }
2462
Nicolas Capens14ee7622014-10-28 23:48:41 -04002463 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002464
2465 if(context)
2466 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002467 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002468
2469 if(!programObject)
2470 {
2471 if(context->getShader(program))
2472 {
2473 return error(GL_INVALID_OPERATION);
2474 }
2475 else
2476 {
2477 return error(GL_INVALID_VALUE);
2478 }
2479 }
2480
2481 if(index >= (GLuint)programObject->getActiveAttributeCount())
2482 {
2483 return error(GL_INVALID_VALUE);
2484 }
2485
2486 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2487 }
2488 }
2489 catch(std::bad_alloc&)
2490 {
2491 return error(GL_OUT_OF_MEMORY);
2492 }
2493}
2494
2495void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2496{
2497 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
Nicolas Capens7e12ac62014-11-05 17:07:53 -05002498 "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = %s)",
John Bauman66b8ab22014-05-06 15:57:45 -04002499 program, index, bufsize, length, size, type, name);
2500
2501 try
2502 {
2503 if(bufsize < 0)
2504 {
2505 return error(GL_INVALID_VALUE);
2506 }
2507
Nicolas Capens14ee7622014-10-28 23:48:41 -04002508 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002509
2510 if(context)
2511 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002512 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002513
2514 if(!programObject)
2515 {
2516 if(context->getShader(program))
2517 {
2518 return error(GL_INVALID_OPERATION);
2519 }
2520 else
2521 {
2522 return error(GL_INVALID_VALUE);
2523 }
2524 }
2525
2526 if(index >= (GLuint)programObject->getActiveUniformCount())
2527 {
2528 return error(GL_INVALID_VALUE);
2529 }
2530
2531 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2532 }
2533 }
2534 catch(std::bad_alloc&)
2535 {
2536 return error(GL_OUT_OF_MEMORY);
2537 }
2538}
2539
2540void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2541{
2542 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
2543 program, maxcount, count, shaders);
2544
2545 try
2546 {
2547 if(maxcount < 0)
2548 {
2549 return error(GL_INVALID_VALUE);
2550 }
2551
Nicolas Capens14ee7622014-10-28 23:48:41 -04002552 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002553
2554 if(context)
2555 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002556 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002557
2558 if(!programObject)
2559 {
2560 if(context->getShader(program))
2561 {
2562 return error(GL_INVALID_OPERATION);
2563 }
2564 else
2565 {
2566 return error(GL_INVALID_VALUE);
2567 }
2568 }
2569
2570 return programObject->getAttachedShaders(maxcount, count, shaders);
2571 }
2572 }
2573 catch(std::bad_alloc&)
2574 {
2575 return error(GL_OUT_OF_MEMORY);
2576 }
2577}
2578
2579int GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
2580{
2581 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2582
2583 try
2584 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002585 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002586
2587 if(context)
2588 {
2589
Nicolas Capens14ee7622014-10-28 23:48:41 -04002590 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002591
2592 if(!programObject)
2593 {
2594 if(context->getShader(program))
2595 {
2596 return error(GL_INVALID_OPERATION, -1);
2597 }
2598 else
2599 {
2600 return error(GL_INVALID_VALUE, -1);
2601 }
2602 }
2603
2604 if(!programObject->isLinked())
2605 {
2606 return error(GL_INVALID_OPERATION, -1);
2607 }
2608
2609 return programObject->getAttributeLocation(name);
2610 }
2611 }
2612 catch(std::bad_alloc&)
2613 {
2614 return error(GL_OUT_OF_MEMORY, -1);
2615 }
2616
2617 return -1;
2618}
2619
2620void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
2621{
2622 TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
2623
2624 try
2625 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002626 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002627
2628 if(context)
2629 {
2630 if(!(context->getBooleanv(pname, params)))
2631 {
2632 GLenum nativeType;
2633 unsigned int numParams = 0;
2634 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2635 return error(GL_INVALID_ENUM);
2636
2637 if(numParams == 0)
2638 return; // it is known that the pname is valid, but there are no parameters to return
2639
2640 if(nativeType == GL_FLOAT)
2641 {
2642 GLfloat *floatParams = NULL;
2643 floatParams = new GLfloat[numParams];
2644
2645 context->getFloatv(pname, floatParams);
2646
2647 for(unsigned int i = 0; i < numParams; ++i)
2648 {
2649 if(floatParams[i] == 0.0f)
2650 params[i] = GL_FALSE;
2651 else
2652 params[i] = GL_TRUE;
2653 }
2654
2655 delete [] floatParams;
2656 }
2657 else if(nativeType == GL_INT)
2658 {
2659 GLint *intParams = NULL;
2660 intParams = new GLint[numParams];
2661
2662 context->getIntegerv(pname, intParams);
2663
2664 for(unsigned int i = 0; i < numParams; ++i)
2665 {
2666 if(intParams[i] == 0)
2667 params[i] = GL_FALSE;
2668 else
2669 params[i] = GL_TRUE;
2670 }
2671
2672 delete [] intParams;
2673 }
2674 }
2675 }
2676 }
2677 catch(std::bad_alloc&)
2678 {
2679 return error(GL_OUT_OF_MEMORY);
2680 }
2681}
2682
2683void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2684{
2685 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
2686
2687 try
2688 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002689 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002690
2691 if(context)
2692 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002693 es2::Buffer *buffer;
John Bauman66b8ab22014-05-06 15:57:45 -04002694
2695 switch(target)
2696 {
2697 case GL_ARRAY_BUFFER:
2698 buffer = context->getArrayBuffer();
2699 break;
2700 case GL_ELEMENT_ARRAY_BUFFER:
2701 buffer = context->getElementArrayBuffer();
2702 break;
2703 default: return error(GL_INVALID_ENUM);
2704 }
2705
2706 if(!buffer)
2707 {
2708 // A null buffer means that "0" is bound to the requested buffer target
2709 return error(GL_INVALID_OPERATION);
2710 }
2711
2712 switch(pname)
2713 {
2714 case GL_BUFFER_USAGE:
2715 *params = buffer->usage();
2716 break;
2717 case GL_BUFFER_SIZE:
2718 *params = buffer->size();
2719 break;
2720 default: return error(GL_INVALID_ENUM);
2721 }
2722 }
2723 }
2724 catch(std::bad_alloc&)
2725 {
2726 return error(GL_OUT_OF_MEMORY);
2727 }
2728}
2729
2730GLenum GL_APIENTRY glGetError(void)
2731{
2732 TRACE("()");
2733
Nicolas Capens14ee7622014-10-28 23:48:41 -04002734 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002735
2736 if(context)
2737 {
2738 return context->getError();
2739 }
2740
2741 return GL_NO_ERROR;
2742}
2743
2744void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2745{
2746 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
2747
2748 try
2749 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002750 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002751
2752 if(context)
2753 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002754 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04002755
2756 if(fenceObject == NULL)
2757 {
2758 return error(GL_INVALID_OPERATION);
2759 }
2760
2761 fenceObject->getFenceiv(pname, params);
2762 }
2763 }
2764 catch(std::bad_alloc&)
2765 {
2766 return error(GL_OUT_OF_MEMORY);
2767 }
2768}
2769
2770void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
2771{
2772 TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
2773
2774 try
2775 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002776 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002777
2778 if(context)
2779 {
2780 if(!(context->getFloatv(pname, params)))
2781 {
2782 GLenum nativeType;
2783 unsigned int numParams = 0;
2784 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2785 return error(GL_INVALID_ENUM);
2786
2787 if(numParams == 0)
2788 return; // it is known that the pname is valid, but that there are no parameters to return.
2789
2790 if(nativeType == GL_BOOL)
2791 {
2792 GLboolean *boolParams = NULL;
2793 boolParams = new GLboolean[numParams];
2794
2795 context->getBooleanv(pname, boolParams);
2796
2797 for(unsigned int i = 0; i < numParams; ++i)
2798 {
2799 if(boolParams[i] == GL_FALSE)
2800 params[i] = 0.0f;
2801 else
2802 params[i] = 1.0f;
2803 }
2804
2805 delete [] boolParams;
2806 }
2807 else if(nativeType == GL_INT)
2808 {
2809 GLint *intParams = NULL;
2810 intParams = new GLint[numParams];
2811
2812 context->getIntegerv(pname, intParams);
2813
2814 for(unsigned int i = 0; i < numParams; ++i)
2815 {
2816 params[i] = (GLfloat)intParams[i];
2817 }
2818
2819 delete [] intParams;
2820 }
2821 }
2822 }
2823 }
2824 catch(std::bad_alloc&)
2825 {
2826 return error(GL_OUT_OF_MEMORY);
2827 }
2828}
2829
2830void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2831{
2832 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
2833 target, attachment, pname, params);
2834
2835 try
2836 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002837 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002838
2839 if(context)
2840 {
2841 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2842 {
2843 return error(GL_INVALID_ENUM);
2844 }
2845
Nicolas Capens14ee7622014-10-28 23:48:41 -04002846 es2::Framebuffer *framebuffer = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04002847 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2848 {
2849 if(context->getReadFramebufferHandle() == 0)
2850 {
2851 return error(GL_INVALID_OPERATION);
2852 }
2853
2854 framebuffer = context->getReadFramebuffer();
2855 }
2856 else
2857 {
2858 if(context->getDrawFramebufferHandle() == 0)
2859 {
2860 return error(GL_INVALID_OPERATION);
2861 }
2862
2863 framebuffer = context->getDrawFramebuffer();
2864 }
2865
2866 GLenum attachmentType;
2867 GLuint attachmentHandle;
2868 switch(attachment)
2869 {
2870 case GL_COLOR_ATTACHMENT0:
2871 attachmentType = framebuffer->getColorbufferType();
2872 attachmentHandle = framebuffer->getColorbufferHandle();
2873 break;
2874 case GL_DEPTH_ATTACHMENT:
2875 attachmentType = framebuffer->getDepthbufferType();
2876 attachmentHandle = framebuffer->getDepthbufferHandle();
2877 break;
2878 case GL_STENCIL_ATTACHMENT:
2879 attachmentType = framebuffer->getStencilbufferType();
2880 attachmentHandle = framebuffer->getStencilbufferHandle();
2881 break;
2882 default: return error(GL_INVALID_ENUM);
2883 }
2884
2885 GLenum attachmentObjectType; // Type category
2886 if(attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
2887 {
2888 attachmentObjectType = attachmentType;
2889 }
Nicolas Capens14ee7622014-10-28 23:48:41 -04002890 else if(es2::IsTextureTarget(attachmentType))
John Bauman66b8ab22014-05-06 15:57:45 -04002891 {
2892 attachmentObjectType = GL_TEXTURE;
2893 }
2894 else UNREACHABLE();
2895
2896 switch(pname)
2897 {
2898 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2899 *params = attachmentObjectType;
2900 break;
2901 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2902 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
2903 {
2904 *params = attachmentHandle;
2905 }
2906 else
2907 {
2908 return error(GL_INVALID_ENUM);
2909 }
2910 break;
2911 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2912 if(attachmentObjectType == GL_TEXTURE)
2913 {
2914 *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
2915 }
2916 else
2917 {
2918 return error(GL_INVALID_ENUM);
2919 }
2920 break;
2921 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2922 if(attachmentObjectType == GL_TEXTURE)
2923 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002924 if(es2::IsCubemapTextureTarget(attachmentType))
John Bauman66b8ab22014-05-06 15:57:45 -04002925 {
2926 *params = attachmentType;
2927 }
2928 else
2929 {
2930 *params = 0;
2931 }
2932 }
2933 else
2934 {
2935 return error(GL_INVALID_ENUM);
2936 }
2937 break;
2938 default:
2939 return error(GL_INVALID_ENUM);
2940 }
2941 }
2942 }
2943 catch(std::bad_alloc&)
2944 {
2945 return error(GL_OUT_OF_MEMORY);
2946 }
2947}
2948
2949GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
2950{
2951 TRACE("()");
2952
2953 return GL_NO_ERROR;
2954}
2955
2956void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
2957{
2958 TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
2959
2960 try
2961 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04002962 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002963
2964 if(context)
2965 {
2966 if(!(context->getIntegerv(pname, params)))
2967 {
2968 GLenum nativeType;
2969 unsigned int numParams = 0;
2970 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2971 return error(GL_INVALID_ENUM);
2972
2973 if(numParams == 0)
2974 return; // it is known that pname is valid, but there are no parameters to return
2975
2976 if(nativeType == GL_BOOL)
2977 {
2978 GLboolean *boolParams = NULL;
2979 boolParams = new GLboolean[numParams];
2980
2981 context->getBooleanv(pname, boolParams);
2982
2983 for(unsigned int i = 0; i < numParams; ++i)
2984 {
2985 if(boolParams[i] == GL_FALSE)
2986 params[i] = 0;
2987 else
2988 params[i] = 1;
2989 }
2990
2991 delete [] boolParams;
2992 }
2993 else if(nativeType == GL_FLOAT)
2994 {
2995 GLfloat *floatParams = NULL;
2996 floatParams = new GLfloat[numParams];
2997
2998 context->getFloatv(pname, floatParams);
2999
3000 for(unsigned int i = 0; i < numParams; ++i)
3001 {
3002 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3003 {
3004 params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f);
3005 }
3006 else
3007 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3008 }
3009
3010 delete [] floatParams;
3011 }
3012 }
3013 }
3014 }
3015 catch(std::bad_alloc&)
3016 {
3017 return error(GL_OUT_OF_MEMORY);
3018 }
3019}
3020
3021void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
3022{
Nicolas Capens7e12ac62014-11-05 17:07:53 -05003023 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003024
3025 try
3026 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003027 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003028
3029 if(context)
3030 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003031 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003032
3033 if(!programObject)
3034 {
3035 return error(GL_INVALID_VALUE);
3036 }
3037
3038 switch(pname)
3039 {
3040 case GL_DELETE_STATUS:
3041 *params = programObject->isFlaggedForDeletion();
3042 return;
3043 case GL_LINK_STATUS:
3044 *params = programObject->isLinked();
3045 return;
3046 case GL_VALIDATE_STATUS:
3047 *params = programObject->isValidated();
3048 return;
3049 case GL_INFO_LOG_LENGTH:
3050 *params = programObject->getInfoLogLength();
3051 return;
3052 case GL_ATTACHED_SHADERS:
3053 *params = programObject->getAttachedShadersCount();
3054 return;
3055 case GL_ACTIVE_ATTRIBUTES:
3056 *params = programObject->getActiveAttributeCount();
3057 return;
3058 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3059 *params = programObject->getActiveAttributeMaxLength();
3060 return;
3061 case GL_ACTIVE_UNIFORMS:
3062 *params = programObject->getActiveUniformCount();
3063 return;
3064 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3065 *params = programObject->getActiveUniformMaxLength();
3066 return;
3067 default:
3068 return error(GL_INVALID_ENUM);
3069 }
3070 }
3071 }
3072 catch(std::bad_alloc&)
3073 {
3074 return error(GL_OUT_OF_MEMORY);
3075 }
3076}
3077
3078void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3079{
3080 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
3081 program, bufsize, length, infolog);
3082
3083 try
3084 {
3085 if(bufsize < 0)
3086 {
3087 return error(GL_INVALID_VALUE);
3088 }
3089
Nicolas Capens14ee7622014-10-28 23:48:41 -04003090 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003091
3092 if(context)
3093 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003094 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003095
3096 if(!programObject)
3097 {
3098 return error(GL_INVALID_VALUE);
3099 }
3100
3101 programObject->getInfoLog(bufsize, length, infolog);
3102 }
3103 }
3104 catch(std::bad_alloc&)
3105 {
3106 return error(GL_OUT_OF_MEMORY);
3107 }
3108}
3109
3110void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3111{
3112 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
3113
3114 try
3115 {
3116 switch(pname)
3117 {
3118 case GL_CURRENT_QUERY_EXT:
3119 break;
3120 default:
3121 return error(GL_INVALID_ENUM);
3122 }
3123
Nicolas Capens14ee7622014-10-28 23:48:41 -04003124 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003125
3126 if(context)
3127 {
3128 params[0] = context->getActiveQuery(target);
3129 }
3130 }
3131 catch(std::bad_alloc&)
3132 {
3133 return error(GL_OUT_OF_MEMORY);
3134 }
3135}
3136
3137void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
3138{
3139 TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
3140
3141 try
3142 {
3143 switch(pname)
3144 {
3145 case GL_QUERY_RESULT_EXT:
3146 case GL_QUERY_RESULT_AVAILABLE_EXT:
3147 break;
3148 default:
3149 return error(GL_INVALID_ENUM);
3150 }
3151
Nicolas Capens14ee7622014-10-28 23:48:41 -04003152 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003153
3154 if(context)
3155 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003156 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);
John Bauman66b8ab22014-05-06 15:57:45 -04003157
3158 if(!queryObject)
3159 {
3160 return error(GL_INVALID_OPERATION);
3161 }
3162
3163 if(context->getActiveQuery(queryObject->getType()) == id)
3164 {
3165 return error(GL_INVALID_OPERATION);
3166 }
3167
3168 switch(pname)
3169 {
3170 case GL_QUERY_RESULT_EXT:
3171 params[0] = queryObject->getResult();
3172 break;
3173 case GL_QUERY_RESULT_AVAILABLE_EXT:
3174 params[0] = queryObject->isResultAvailable();
3175 break;
3176 default:
3177 ASSERT(false);
3178 }
3179 }
3180 }
3181 catch(std::bad_alloc&)
3182 {
3183 return error(GL_OUT_OF_MEMORY);
3184 }
3185}
3186
3187void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3188{
3189 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
3190
3191 try
3192 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003193 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003194
3195 if(context)
3196 {
3197 if(target != GL_RENDERBUFFER)
3198 {
3199 return error(GL_INVALID_ENUM);
3200 }
3201
3202 if(context->getRenderbufferHandle() == 0)
3203 {
3204 return error(GL_INVALID_OPERATION);
3205 }
3206
Nicolas Capens14ee7622014-10-28 23:48:41 -04003207 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle());
John Bauman66b8ab22014-05-06 15:57:45 -04003208
3209 switch(pname)
3210 {
John Baumand4ae8632014-05-06 16:18:33 -04003211 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3212 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
3213 case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat(); break;
3214 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3215 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3216 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3217 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3218 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3219 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
3220 case GL_RENDERBUFFER_SAMPLES_ANGLE: *params = renderbuffer->getSamples(); break;
3221 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003222 return error(GL_INVALID_ENUM);
3223 }
3224 }
3225 }
3226 catch(std::bad_alloc&)
3227 {
3228 return error(GL_OUT_OF_MEMORY);
3229 }
3230}
3231
3232void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
3233{
3234 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
3235
3236 try
3237 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003238 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003239
3240 if(context)
3241 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003242 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003243
3244 if(!shaderObject)
3245 {
3246 return error(GL_INVALID_VALUE);
3247 }
3248
3249 switch(pname)
3250 {
3251 case GL_SHADER_TYPE:
3252 *params = shaderObject->getType();
3253 return;
3254 case GL_DELETE_STATUS:
3255 *params = shaderObject->isFlaggedForDeletion();
3256 return;
3257 case GL_COMPILE_STATUS:
3258 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3259 return;
3260 case GL_INFO_LOG_LENGTH:
3261 *params = shaderObject->getInfoLogLength();
3262 return;
3263 case GL_SHADER_SOURCE_LENGTH:
3264 *params = shaderObject->getSourceLength();
3265 return;
3266 default:
3267 return error(GL_INVALID_ENUM);
3268 }
3269 }
3270 }
3271 catch(std::bad_alloc&)
3272 {
3273 return error(GL_OUT_OF_MEMORY);
3274 }
3275}
3276
3277void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3278{
3279 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
3280 shader, bufsize, length, infolog);
3281
3282 try
3283 {
3284 if(bufsize < 0)
3285 {
3286 return error(GL_INVALID_VALUE);
3287 }
3288
Nicolas Capens14ee7622014-10-28 23:48:41 -04003289 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003290
3291 if(context)
3292 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003293 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003294
3295 if(!shaderObject)
3296 {
3297 return error(GL_INVALID_VALUE);
3298 }
3299
3300 shaderObject->getInfoLog(bufsize, length, infolog);
3301 }
3302 }
3303 catch(std::bad_alloc&)
3304 {
3305 return error(GL_OUT_OF_MEMORY);
3306 }
3307}
3308
3309void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3310{
3311 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
3312 shadertype, precisiontype, range, precision);
3313
3314 try
3315 {
3316 switch(shadertype)
3317 {
3318 case GL_VERTEX_SHADER:
3319 case GL_FRAGMENT_SHADER:
3320 break;
3321 default:
3322 return error(GL_INVALID_ENUM);
3323 }
3324
3325 switch(precisiontype)
3326 {
3327 case GL_LOW_FLOAT:
3328 case GL_MEDIUM_FLOAT:
3329 case GL_HIGH_FLOAT:
3330 // IEEE 754 single-precision
3331 range[0] = 127;
3332 range[1] = 127;
3333 *precision = 23;
3334 break;
3335 case GL_LOW_INT:
3336 case GL_MEDIUM_INT:
3337 case GL_HIGH_INT:
3338 // Single-precision floating-point numbers can accurately represent integers up to +/-16777216
3339 range[0] = 24;
3340 range[1] = 24;
3341 *precision = 0;
3342 break;
3343 default:
3344 return error(GL_INVALID_ENUM);
3345 }
3346 }
3347 catch(std::bad_alloc&)
3348 {
3349 return error(GL_OUT_OF_MEMORY);
3350 }
3351}
3352
3353void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3354{
3355 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
3356 shader, bufsize, length, source);
3357
3358 try
3359 {
3360 if(bufsize < 0)
3361 {
3362 return error(GL_INVALID_VALUE);
3363 }
3364
Nicolas Capens14ee7622014-10-28 23:48:41 -04003365 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003366
3367 if(context)
3368 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003369 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003370
3371 if(!shaderObject)
3372 {
3373 return error(GL_INVALID_OPERATION);
3374 }
3375
3376 shaderObject->getSource(bufsize, length, source);
3377 }
3378 }
3379 catch(std::bad_alloc&)
3380 {
3381 return error(GL_OUT_OF_MEMORY);
3382 }
3383}
3384
3385const GLubyte* GL_APIENTRY glGetString(GLenum name)
3386{
3387 TRACE("(GLenum name = 0x%X)", name);
3388
3389 try
3390 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003391 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003392
3393 switch(name)
3394 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003395 case GL_VENDOR:
John Bauman66b8ab22014-05-06 15:57:45 -04003396 return (GLubyte*)"TransGaming Inc.";
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003397 case GL_RENDERER:
John Bauman66b8ab22014-05-06 15:57:45 -04003398 return (GLubyte*)"SwiftShader";
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003399 case GL_VERSION:
John Bauman66b8ab22014-05-06 15:57:45 -04003400 return (GLubyte*)"OpenGL ES 2.0 SwiftShader "VERSION_STRING;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003401 case GL_SHADING_LANGUAGE_VERSION:
John Bauman66b8ab22014-05-06 15:57:45 -04003402 return (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader "VERSION_STRING;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003403 case GL_EXTENSIONS:
3404 // Keep list sorted in following order:
3405 // OES extensions
3406 // EXT extensions
3407 // Vendor extensions
3408 return (GLubyte*)
3409 "GL_OES_depth_texture "
3410 "GL_OES_depth_texture_cube_map "
Nicolas Capensb4db6292014-10-23 23:37:17 -04003411 "GL_OES_EGL_image "
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003412 "GL_OES_EGL_image_external "
3413 "GL_OES_element_index_uint "
3414 "GL_OES_packed_depth_stencil "
3415 "GL_OES_rgb8_rgba8 "
3416 "GL_OES_standard_derivatives "
3417 "GL_OES_texture_float "
3418 "GL_OES_texture_float_linear "
3419 "GL_OES_texture_half_float "
3420 "GL_OES_texture_half_float_linear "
3421 "GL_OES_texture_npot "
3422 "GL_EXT_blend_minmax "
3423 "GL_EXT_occlusion_query_boolean "
3424 "GL_EXT_read_format_bgra "
3425 #if (S3TC_SUPPORT)
3426 "GL_EXT_texture_compression_dxt1 "
3427 "GL_ANGLE_texture_compression_dxt3 "
3428 "GL_ANGLE_texture_compression_dxt5 "
3429 #endif
3430 "GL_EXT_texture_filter_anisotropic "
3431 "GL_EXT_texture_format_BGRA8888 "
3432 "GL_ANGLE_framebuffer_blit "
3433 "GL_ANGLE_framebuffer_multisample "
3434 "GL_NV_fence";
3435 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003436 return error(GL_INVALID_ENUM, (GLubyte*)NULL);
3437 }
3438 }
3439 catch(std::bad_alloc&)
3440 {
3441 return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL);
3442 }
3443
3444 return NULL;
3445}
3446
3447void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3448{
3449 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
3450
3451 try
3452 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003453 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003454
3455 if(context)
3456 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003457 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04003458
3459 switch(target)
3460 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003461 case GL_TEXTURE_2D:
John Bauman66b8ab22014-05-06 15:57:45 -04003462 texture = context->getTexture2D();
3463 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003464 case GL_TEXTURE_CUBE_MAP:
John Bauman66b8ab22014-05-06 15:57:45 -04003465 texture = context->getTextureCubeMap();
3466 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003467 case GL_TEXTURE_EXTERNAL_OES:
3468 texture = context->getTextureExternal();
3469 break;
3470 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003471 return error(GL_INVALID_ENUM);
3472 }
3473
3474 switch(pname)
3475 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003476 case GL_TEXTURE_MAG_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04003477 *params = (GLfloat)texture->getMagFilter();
3478 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003479 case GL_TEXTURE_MIN_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04003480 *params = (GLfloat)texture->getMinFilter();
3481 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003482 case GL_TEXTURE_WRAP_S:
John Bauman66b8ab22014-05-06 15:57:45 -04003483 *params = (GLfloat)texture->getWrapS();
3484 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003485 case GL_TEXTURE_WRAP_T:
John Bauman66b8ab22014-05-06 15:57:45 -04003486 *params = (GLfloat)texture->getWrapT();
3487 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003488 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
John Bauman66b8ab22014-05-06 15:57:45 -04003489 *params = texture->getMaxAnisotropy();
3490 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003491 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3492 *params = (GLfloat)1;
3493 break;
3494 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003495 return error(GL_INVALID_ENUM);
3496 }
3497 }
3498 }
3499 catch(std::bad_alloc&)
3500 {
3501 return error(GL_OUT_OF_MEMORY);
3502 }
3503}
3504
3505void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3506{
3507 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
3508
3509 try
3510 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003511 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003512
3513 if(context)
3514 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003515 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04003516
3517 switch(target)
3518 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003519 case GL_TEXTURE_2D:
John Bauman66b8ab22014-05-06 15:57:45 -04003520 texture = context->getTexture2D();
3521 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003522 case GL_TEXTURE_CUBE_MAP:
John Bauman66b8ab22014-05-06 15:57:45 -04003523 texture = context->getTextureCubeMap();
3524 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003525 case GL_TEXTURE_EXTERNAL_OES:
3526 texture = context->getTextureExternal();
3527 break;
3528 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003529 return error(GL_INVALID_ENUM);
3530 }
3531
3532 switch(pname)
3533 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003534 case GL_TEXTURE_MAG_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04003535 *params = texture->getMagFilter();
3536 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003537 case GL_TEXTURE_MIN_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04003538 *params = texture->getMinFilter();
3539 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003540 case GL_TEXTURE_WRAP_S:
John Bauman66b8ab22014-05-06 15:57:45 -04003541 *params = texture->getWrapS();
3542 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003543 case GL_TEXTURE_WRAP_T:
John Bauman66b8ab22014-05-06 15:57:45 -04003544 *params = texture->getWrapT();
3545 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003546 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
John Bauman66b8ab22014-05-06 15:57:45 -04003547 *params = (GLint)texture->getMaxAnisotropy();
3548 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04003549 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3550 *params = 1;
3551 break;
3552 default:
John Bauman66b8ab22014-05-06 15:57:45 -04003553 return error(GL_INVALID_ENUM);
3554 }
3555 }
3556 }
3557 catch(std::bad_alloc&)
3558 {
3559 return error(GL_OUT_OF_MEMORY);
3560 }
3561}
3562
3563void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3564{
3565 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
3566 program, location, bufSize, params);
3567
3568 try
3569 {
3570 if(bufSize < 0)
3571 {
3572 return error(GL_INVALID_VALUE);
3573 }
3574
Nicolas Capens14ee7622014-10-28 23:48:41 -04003575 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003576
3577 if(context)
3578 {
3579 if(program == 0)
3580 {
3581 return error(GL_INVALID_VALUE);
3582 }
3583
Nicolas Capens14ee7622014-10-28 23:48:41 -04003584 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003585
3586 if(!programObject || !programObject->isLinked())
3587 {
3588 return error(GL_INVALID_OPERATION);
3589 }
3590
3591 if(!programObject->getUniformfv(location, &bufSize, params))
3592 {
3593 return error(GL_INVALID_OPERATION);
3594 }
3595 }
3596 }
3597 catch(std::bad_alloc&)
3598 {
3599 return error(GL_OUT_OF_MEMORY);
3600 }
3601}
3602
3603void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
3604{
3605 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
3606
3607 try
3608 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003609 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003610
3611 if(context)
3612 {
3613 if(program == 0)
3614 {
3615 return error(GL_INVALID_VALUE);
3616 }
3617
Nicolas Capens14ee7622014-10-28 23:48:41 -04003618 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003619
3620 if(!programObject || !programObject->isLinked())
3621 {
3622 return error(GL_INVALID_OPERATION);
3623 }
3624
3625 if(!programObject->getUniformfv(location, NULL, params))
3626 {
3627 return error(GL_INVALID_OPERATION);
3628 }
3629 }
3630 }
3631 catch(std::bad_alloc&)
3632 {
3633 return error(GL_OUT_OF_MEMORY);
3634 }
3635}
3636
3637void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3638{
3639 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
3640 program, location, bufSize, params);
3641
3642 try
3643 {
3644 if(bufSize < 0)
3645 {
3646 return error(GL_INVALID_VALUE);
3647 }
3648
Nicolas Capens14ee7622014-10-28 23:48:41 -04003649 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003650
3651 if(context)
3652 {
3653 if(program == 0)
3654 {
3655 return error(GL_INVALID_VALUE);
3656 }
3657
Nicolas Capens14ee7622014-10-28 23:48:41 -04003658 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003659
3660 if(!programObject || !programObject->isLinked())
3661 {
3662 return error(GL_INVALID_OPERATION);
3663 }
3664
3665 if(!programObject)
3666 {
3667 return error(GL_INVALID_OPERATION);
3668 }
3669
3670 if(!programObject->getUniformiv(location, &bufSize, params))
3671 {
3672 return error(GL_INVALID_OPERATION);
3673 }
3674 }
3675 }
3676 catch(std::bad_alloc&)
3677 {
3678 return error(GL_OUT_OF_MEMORY);
3679 }
3680}
3681
3682void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
3683{
3684 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
3685
3686 try
3687 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003688 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003689
3690 if(context)
3691 {
3692 if(program == 0)
3693 {
3694 return error(GL_INVALID_VALUE);
3695 }
3696
Nicolas Capens14ee7622014-10-28 23:48:41 -04003697 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003698
3699 if(!programObject || !programObject->isLinked())
3700 {
3701 return error(GL_INVALID_OPERATION);
3702 }
3703
3704 if(!programObject)
3705 {
3706 return error(GL_INVALID_OPERATION);
3707 }
3708
3709 if(!programObject->getUniformiv(location, NULL, params))
3710 {
3711 return error(GL_INVALID_OPERATION);
3712 }
3713 }
3714 }
3715 catch(std::bad_alloc&)
3716 {
3717 return error(GL_OUT_OF_MEMORY);
3718 }
3719}
3720
3721int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
3722{
Nicolas Capens7e12ac62014-11-05 17:07:53 -05003723 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
John Bauman66b8ab22014-05-06 15:57:45 -04003724
3725 try
3726 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003727 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003728
3729 if(strstr(name, "gl_") == name)
3730 {
3731 return -1;
3732 }
3733
3734 if(context)
3735 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003736 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003737
3738 if(!programObject)
3739 {
3740 if(context->getShader(program))
3741 {
3742 return error(GL_INVALID_OPERATION, -1);
3743 }
3744 else
3745 {
3746 return error(GL_INVALID_VALUE, -1);
3747 }
3748 }
3749
3750 if(!programObject->isLinked())
3751 {
3752 return error(GL_INVALID_OPERATION, -1);
3753 }
3754
3755 return programObject->getUniformLocation(name);
3756 }
3757 }
3758 catch(std::bad_alloc&)
3759 {
3760 return error(GL_OUT_OF_MEMORY, -1);
3761 }
3762
3763 return -1;
3764}
3765
3766void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3767{
3768 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
3769
3770 try
3771 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003772 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003773
3774 if(context)
3775 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003776 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04003777 {
3778 return error(GL_INVALID_VALUE);
3779 }
3780
Nicolas Capens14ee7622014-10-28 23:48:41 -04003781 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
John Bauman66b8ab22014-05-06 15:57:45 -04003782
3783 switch(pname)
3784 {
3785 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3786 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3787 break;
3788 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3789 *params = (GLfloat)attribState.mSize;
3790 break;
3791 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3792 *params = (GLfloat)attribState.mStride;
3793 break;
3794 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3795 *params = (GLfloat)attribState.mType;
3796 break;
3797 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3798 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3799 break;
3800 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3801 *params = (GLfloat)attribState.mBoundBuffer.id();
3802 break;
3803 case GL_CURRENT_VERTEX_ATTRIB:
3804 for(int i = 0; i < 4; ++i)
3805 {
3806 params[i] = attribState.mCurrentValue[i];
3807 }
3808 break;
3809 default: return error(GL_INVALID_ENUM);
3810 }
3811 }
3812 }
3813 catch(std::bad_alloc&)
3814 {
3815 return error(GL_OUT_OF_MEMORY);
3816 }
3817}
3818
3819void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3820{
3821 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
3822
3823 try
3824 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003825 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003826
3827 if(context)
3828 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003829 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04003830 {
3831 return error(GL_INVALID_VALUE);
3832 }
3833
Nicolas Capens14ee7622014-10-28 23:48:41 -04003834 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
John Bauman66b8ab22014-05-06 15:57:45 -04003835
3836 switch(pname)
3837 {
3838 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3839 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3840 break;
3841 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3842 *params = attribState.mSize;
3843 break;
3844 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3845 *params = attribState.mStride;
3846 break;
3847 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3848 *params = attribState.mType;
3849 break;
3850 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3851 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3852 break;
3853 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3854 *params = attribState.mBoundBuffer.id();
3855 break;
3856 case GL_CURRENT_VERTEX_ATTRIB:
3857 for(int i = 0; i < 4; ++i)
3858 {
3859 float currentValue = attribState.mCurrentValue[i];
3860 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3861 }
3862 break;
3863 default: return error(GL_INVALID_ENUM);
3864 }
3865 }
3866 }
3867 catch(std::bad_alloc&)
3868 {
3869 return error(GL_OUT_OF_MEMORY);
3870 }
3871}
3872
3873void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3874{
3875 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
3876
3877 try
3878 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003879 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003880
3881 if(context)
3882 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003883 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04003884 {
3885 return error(GL_INVALID_VALUE);
3886 }
3887
3888 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3889 {
3890 return error(GL_INVALID_ENUM);
3891 }
3892
3893 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3894 }
3895 }
3896 catch(std::bad_alloc&)
3897 {
3898 return error(GL_OUT_OF_MEMORY);
3899 }
3900}
3901
3902void GL_APIENTRY glHint(GLenum target, GLenum mode)
3903{
3904 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3905
3906 try
3907 {
3908 switch(mode)
3909 {
3910 case GL_FASTEST:
3911 case GL_NICEST:
3912 case GL_DONT_CARE:
3913 break;
3914 default:
3915 return error(GL_INVALID_ENUM);
3916 }
3917
Nicolas Capens14ee7622014-10-28 23:48:41 -04003918 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003919 switch(target)
3920 {
3921 case GL_GENERATE_MIPMAP_HINT:
3922 if(context) context->setGenerateMipmapHint(mode);
3923 break;
3924 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3925 if(context) context->setFragmentShaderDerivativeHint(mode);
3926 break;
3927 default:
3928 return error(GL_INVALID_ENUM);
3929 }
3930 }
3931 catch(std::bad_alloc&)
3932 {
3933 return error(GL_OUT_OF_MEMORY);
3934 }
3935}
3936
3937GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
3938{
3939 TRACE("(GLuint buffer = %d)", buffer);
3940
3941 try
3942 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003943 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003944
3945 if(context && buffer)
3946 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003947 es2::Buffer *bufferObject = context->getBuffer(buffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003948
3949 if(bufferObject)
3950 {
3951 return GL_TRUE;
3952 }
3953 }
3954 }
3955 catch(std::bad_alloc&)
3956 {
3957 return error(GL_OUT_OF_MEMORY, GL_FALSE);
3958 }
3959
3960 return GL_FALSE;
3961}
3962
3963GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
3964{
3965 TRACE("(GLenum cap = 0x%X)", cap);
3966
3967 try
3968 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04003969 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003970
3971 if(context)
3972 {
3973 switch(cap)
3974 {
3975 case GL_CULL_FACE: return context->isCullFaceEnabled();
3976 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3977 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3978 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3979 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3980 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3981 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3982 case GL_BLEND: return context->isBlendEnabled();
3983 case GL_DITHER: return context->isDitherEnabled();
3984 default:
3985 return error(GL_INVALID_ENUM, false);
3986 }
3987 }
3988 }
3989 catch(std::bad_alloc&)
3990 {
3991 return error(GL_OUT_OF_MEMORY, false);
3992 }
3993
3994 return false;
3995}
3996
3997GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
3998{
3999 TRACE("(GLuint fence = %d)", fence);
4000
4001 try
4002 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004003 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004004
4005 if(context)
4006 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004007 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004008
4009 if(fenceObject == NULL)
4010 {
4011 return GL_FALSE;
4012 }
4013
4014 return fenceObject->isFence();
4015 }
4016 }
4017 catch(std::bad_alloc&)
4018 {
4019 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4020 }
4021
4022 return GL_FALSE;
4023}
4024
4025GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
4026{
4027 TRACE("(GLuint framebuffer = %d)", framebuffer);
4028
4029 try
4030 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004031 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004032
4033 if(context && framebuffer)
4034 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004035 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04004036
4037 if(framebufferObject)
4038 {
4039 return GL_TRUE;
4040 }
4041 }
4042 }
4043 catch(std::bad_alloc&)
4044 {
4045 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4046 }
4047
4048 return GL_FALSE;
4049}
4050
4051GLboolean GL_APIENTRY glIsProgram(GLuint program)
4052{
4053 TRACE("(GLuint program = %d)", program);
4054
4055 try
4056 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004057 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004058
4059 if(context && program)
4060 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004061 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04004062
4063 if(programObject)
4064 {
4065 return GL_TRUE;
4066 }
4067 }
4068 }
4069 catch(std::bad_alloc&)
4070 {
4071 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4072 }
4073
4074 return GL_FALSE;
4075}
4076
4077GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
4078{
4079 TRACE("(GLuint id = %d)", id);
4080
4081 try
4082 {
4083 if(id == 0)
4084 {
4085 return GL_FALSE;
4086 }
4087
Nicolas Capens14ee7622014-10-28 23:48:41 -04004088 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004089
4090 if(context)
4091 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004092 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);
John Bauman66b8ab22014-05-06 15:57:45 -04004093
4094 if(queryObject)
4095 {
4096 return GL_TRUE;
4097 }
4098 }
4099 }
4100 catch(std::bad_alloc&)
4101 {
4102 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4103 }
4104
4105 return GL_FALSE;
4106}
4107
4108GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
4109{
4110 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
4111
4112 try
4113 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004114 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004115
4116 if(context && renderbuffer)
4117 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004118 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04004119
4120 if(renderbufferObject)
4121 {
4122 return GL_TRUE;
4123 }
4124 }
4125 }
4126 catch(std::bad_alloc&)
4127 {
4128 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4129 }
4130
4131 return GL_FALSE;
4132}
4133
4134GLboolean GL_APIENTRY glIsShader(GLuint shader)
4135{
4136 TRACE("(GLuint shader = %d)", shader);
4137
4138 try
4139 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004140 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004141
4142 if(context && shader)
4143 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004144 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04004145
4146 if(shaderObject)
4147 {
4148 return GL_TRUE;
4149 }
4150 }
4151 }
4152 catch(std::bad_alloc&)
4153 {
4154 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4155 }
4156
4157 return GL_FALSE;
4158}
4159
4160GLboolean GL_APIENTRY glIsTexture(GLuint texture)
4161{
4162 TRACE("(GLuint texture = %d)", texture);
4163
4164 try
4165 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004166 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004167
4168 if(context && texture)
4169 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004170 es2::Texture *textureObject = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -04004171
4172 if(textureObject)
4173 {
4174 return GL_TRUE;
4175 }
4176 }
4177 }
4178 catch(std::bad_alloc&)
4179 {
4180 return error(GL_OUT_OF_MEMORY, GL_FALSE);
4181 }
4182
4183 return GL_FALSE;
4184}
4185
4186void GL_APIENTRY glLineWidth(GLfloat width)
4187{
4188 TRACE("(GLfloat width = %f)", width);
4189
4190 try
4191 {
4192 if(width <= 0.0f)
4193 {
4194 return error(GL_INVALID_VALUE);
4195 }
4196
Nicolas Capens14ee7622014-10-28 23:48:41 -04004197 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004198
4199 if(context)
4200 {
4201 context->setLineWidth(width);
4202 }
4203 }
4204 catch(std::bad_alloc&)
4205 {
4206 return error(GL_OUT_OF_MEMORY);
4207 }
4208}
4209
4210void GL_APIENTRY glLinkProgram(GLuint program)
4211{
4212 TRACE("(GLuint program = %d)", program);
4213
4214 try
4215 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004216 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004217
4218 if(context)
4219 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004220 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04004221
4222 if(!programObject)
4223 {
4224 if(context->getShader(program))
4225 {
4226 return error(GL_INVALID_OPERATION);
4227 }
4228 else
4229 {
4230 return error(GL_INVALID_VALUE);
4231 }
4232 }
4233
4234 programObject->link();
4235 }
4236 }
4237 catch(std::bad_alloc&)
4238 {
4239 return error(GL_OUT_OF_MEMORY);
4240 }
4241}
4242
4243void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
4244{
4245 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4246
4247 try
4248 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004249 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004250
4251 if(context)
4252 {
4253 switch(pname)
4254 {
4255 case GL_UNPACK_ALIGNMENT:
4256 if(param != 1 && param != 2 && param != 4 && param != 8)
4257 {
4258 return error(GL_INVALID_VALUE);
4259 }
4260
4261 context->setUnpackAlignment(param);
4262 break;
4263
4264 case GL_PACK_ALIGNMENT:
4265 if(param != 1 && param != 2 && param != 4 && param != 8)
4266 {
4267 return error(GL_INVALID_VALUE);
4268 }
4269
4270 context->setPackAlignment(param);
4271 break;
4272
4273 default:
4274 return error(GL_INVALID_ENUM);
4275 }
4276 }
4277 }
4278 catch(std::bad_alloc&)
4279 {
4280 return error(GL_OUT_OF_MEMORY);
4281 }
4282}
4283
4284void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
4285{
4286 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4287
4288 try
4289 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004290 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004291
4292 if(context)
4293 {
4294 context->setPolygonOffsetParams(factor, units);
4295 }
4296 }
4297 catch(std::bad_alloc&)
4298 {
4299 return error(GL_OUT_OF_MEMORY);
4300 }
4301}
4302
4303void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4304 GLenum format, GLenum type, GLsizei bufSize,
4305 GLvoid *data)
4306{
4307 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4308 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
4309 x, y, width, height, format, type, bufSize, data);
4310
4311 try
4312 {
4313 if(width < 0 || height < 0 || bufSize < 0)
4314 {
4315 return error(GL_INVALID_VALUE);
4316 }
4317
4318 if(!validReadFormatType(format, type))
4319 {
4320 return error(GL_INVALID_OPERATION);
4321 }
4322
Nicolas Capens14ee7622014-10-28 23:48:41 -04004323 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004324
4325 if(context)
4326 {
4327 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4328 }
4329 }
4330 catch(std::bad_alloc&)
4331 {
4332 return error(GL_OUT_OF_MEMORY);
4333 }
4334}
4335
4336void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4337{
4338 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4339 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
4340 x, y, width, height, format, type, pixels);
4341
4342 try
4343 {
4344 if(width < 0 || height < 0)
4345 {
4346 return error(GL_INVALID_VALUE);
4347 }
4348
4349 if(!validReadFormatType(format, type))
4350 {
4351 return error(GL_INVALID_OPERATION);
4352 }
4353
Nicolas Capens14ee7622014-10-28 23:48:41 -04004354 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004355
4356 if(context)
4357 {
4358 context->readPixels(x, y, width, height, format, type, NULL, pixels);
4359 }
4360 }
4361 catch(std::bad_alloc&)
4362 {
4363 return error(GL_OUT_OF_MEMORY);
4364 }
4365}
4366
4367void GL_APIENTRY glReleaseShaderCompiler(void)
4368{
4369 TRACE("()");
4370
4371 try
4372 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004373 es2::Shader::releaseCompiler();
John Bauman66b8ab22014-05-06 15:57:45 -04004374 }
4375 catch(std::bad_alloc&)
4376 {
4377 return error(GL_OUT_OF_MEMORY);
4378 }
4379}
4380
4381void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4382{
4383 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4384 target, samples, internalformat, width, height);
4385
4386 try
4387 {
4388 switch(target)
4389 {
4390 case GL_RENDERBUFFER:
4391 break;
4392 default:
4393 return error(GL_INVALID_ENUM);
4394 }
4395
Nicolas Capens14ee7622014-10-28 23:48:41 -04004396 if(!es2::IsColorRenderable(internalformat) && !es2::IsDepthRenderable(internalformat) && !es2::IsStencilRenderable(internalformat))
John Bauman66b8ab22014-05-06 15:57:45 -04004397 {
4398 return error(GL_INVALID_ENUM);
4399 }
4400
4401 if(width < 0 || height < 0 || samples < 0)
4402 {
4403 return error(GL_INVALID_VALUE);
4404 }
4405
Nicolas Capens14ee7622014-10-28 23:48:41 -04004406 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004407
4408 if(context)
4409 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004410 if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4411 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4412 samples > es2::IMPLEMENTATION_MAX_SAMPLES)
John Bauman66b8ab22014-05-06 15:57:45 -04004413 {
4414 return error(GL_INVALID_VALUE);
4415 }
4416
4417 GLuint handle = context->getRenderbufferHandle();
4418 if(handle == 0)
4419 {
4420 return error(GL_INVALID_OPERATION);
4421 }
4422
4423 switch(internalformat)
4424 {
4425 case GL_DEPTH_COMPONENT16:
Nicolas Capens14ee7622014-10-28 23:48:41 -04004426 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, samples));
John Bauman66b8ab22014-05-06 15:57:45 -04004427 break;
4428 case GL_RGBA4:
4429 case GL_RGB5_A1:
4430 case GL_RGB565:
4431 case GL_RGB8_OES:
4432 case GL_RGBA8_OES:
Nicolas Capens14ee7622014-10-28 23:48:41 -04004433 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
John Bauman66b8ab22014-05-06 15:57:45 -04004434 break;
4435 case GL_STENCIL_INDEX8:
Nicolas Capens14ee7622014-10-28 23:48:41 -04004436 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
John Bauman66b8ab22014-05-06 15:57:45 -04004437 break;
4438 case GL_DEPTH24_STENCIL8_OES:
Nicolas Capens14ee7622014-10-28 23:48:41 -04004439 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, samples));
John Bauman66b8ab22014-05-06 15:57:45 -04004440 break;
4441 default:
4442 return error(GL_INVALID_ENUM);
4443 }
4444 }
4445 }
4446 catch(std::bad_alloc&)
4447 {
4448 return error(GL_OUT_OF_MEMORY);
4449 }
4450}
4451
4452void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4453{
4454 glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
4455}
4456
4457void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)
4458{
4459 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4460
4461 try
4462 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004463 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004464
4465 if(context)
4466 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004467 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
John Bauman66b8ab22014-05-06 15:57:45 -04004468 }
4469 }
4470 catch(std::bad_alloc&)
4471 {
4472 return error(GL_OUT_OF_MEMORY);
4473 }
4474}
4475
4476void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
4477{
4478 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4479
4480 try
4481 {
4482 if(condition != GL_ALL_COMPLETED_NV)
4483 {
4484 return error(GL_INVALID_ENUM);
4485 }
4486
Nicolas Capens14ee7622014-10-28 23:48:41 -04004487 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004488
4489 if(context)
4490 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004491 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004492
4493 if(fenceObject == NULL)
4494 {
4495 return error(GL_INVALID_OPERATION);
4496 }
4497
4498 fenceObject->setFence(condition);
4499 }
4500 }
4501 catch(std::bad_alloc&)
4502 {
4503 return error(GL_OUT_OF_MEMORY);
4504 }
4505}
4506
4507void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
4508{
4509 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4510
4511 try
4512 {
4513 if(width < 0 || height < 0)
4514 {
4515 return error(GL_INVALID_VALUE);
4516 }
4517
Nicolas Capens14ee7622014-10-28 23:48:41 -04004518 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004519
4520 if(context)
4521 {
4522 context->setScissorParams(x, y, width, height);
4523 }
4524 }
4525 catch(std::bad_alloc&)
4526 {
4527 return error(GL_OUT_OF_MEMORY);
4528 }
4529}
4530
4531void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4532{
4533 TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
4534 "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
4535 n, shaders, binaryformat, binary, length);
4536
4537 try
4538 {
4539 // No binary shader formats are supported.
4540 return error(GL_INVALID_ENUM);
4541 }
4542 catch(std::bad_alloc&)
4543 {
4544 return error(GL_OUT_OF_MEMORY);
4545 }
4546}
4547
Nicolas Capensb0e93552014-10-28 11:54:43 -04004548void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
John Bauman66b8ab22014-05-06 15:57:45 -04004549{
4550 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
4551 shader, count, string, length);
4552
4553 try
4554 {
4555 if(count < 0)
4556 {
4557 return error(GL_INVALID_VALUE);
4558 }
4559
Nicolas Capens14ee7622014-10-28 23:48:41 -04004560 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004561
4562 if(context)
4563 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004564 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04004565
4566 if(!shaderObject)
4567 {
4568 if(context->getProgram(shader))
4569 {
4570 return error(GL_INVALID_OPERATION);
4571 }
4572 else
4573 {
4574 return error(GL_INVALID_VALUE);
4575 }
4576 }
4577
4578 shaderObject->setSource(count, string, length);
4579 }
4580 }
4581 catch(std::bad_alloc&)
4582 {
4583 return error(GL_OUT_OF_MEMORY);
4584 }
4585}
4586
4587void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
4588{
4589 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4590}
4591
4592void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4593{
4594 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4595
4596 try
4597 {
4598 switch(face)
4599 {
4600 case GL_FRONT:
4601 case GL_BACK:
4602 case GL_FRONT_AND_BACK:
4603 break;
4604 default:
4605 return error(GL_INVALID_ENUM);
4606 }
4607
4608 switch(func)
4609 {
4610 case GL_NEVER:
4611 case GL_ALWAYS:
4612 case GL_LESS:
4613 case GL_LEQUAL:
4614 case GL_EQUAL:
4615 case GL_GEQUAL:
4616 case GL_GREATER:
4617 case GL_NOTEQUAL:
4618 break;
4619 default:
4620 return error(GL_INVALID_ENUM);
4621 }
4622
Nicolas Capens14ee7622014-10-28 23:48:41 -04004623 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004624
4625 if(context)
4626 {
4627 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4628 {
4629 context->setStencilParams(func, ref, mask);
4630 }
4631
4632 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4633 {
4634 context->setStencilBackParams(func, ref, mask);
4635 }
4636 }
4637 }
4638 catch(std::bad_alloc&)
4639 {
4640 return error(GL_OUT_OF_MEMORY);
4641 }
4642}
4643
4644void GL_APIENTRY glStencilMask(GLuint mask)
4645{
4646 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4647}
4648
4649void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
4650{
4651 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4652
4653 try
4654 {
4655 switch(face)
4656 {
4657 case GL_FRONT:
4658 case GL_BACK:
4659 case GL_FRONT_AND_BACK:
4660 break;
4661 default:
4662 return error(GL_INVALID_ENUM);
4663 }
4664
Nicolas Capens14ee7622014-10-28 23:48:41 -04004665 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004666
4667 if(context)
4668 {
4669 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4670 {
4671 context->setStencilWritemask(mask);
4672 }
4673
4674 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4675 {
4676 context->setStencilBackWritemask(mask);
4677 }
4678 }
4679 }
4680 catch(std::bad_alloc&)
4681 {
4682 return error(GL_OUT_OF_MEMORY);
4683 }
4684}
4685
4686void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4687{
4688 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4689}
4690
4691void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4692{
4693 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4694 face, fail, zfail, zpass);
4695
4696 try
4697 {
4698 switch(face)
4699 {
4700 case GL_FRONT:
4701 case GL_BACK:
4702 case GL_FRONT_AND_BACK:
4703 break;
4704 default:
4705 return error(GL_INVALID_ENUM);
4706 }
4707
4708 switch(fail)
4709 {
4710 case GL_ZERO:
4711 case GL_KEEP:
4712 case GL_REPLACE:
4713 case GL_INCR:
4714 case GL_DECR:
4715 case GL_INVERT:
4716 case GL_INCR_WRAP:
4717 case GL_DECR_WRAP:
4718 break;
4719 default:
4720 return error(GL_INVALID_ENUM);
4721 }
4722
4723 switch(zfail)
4724 {
4725 case GL_ZERO:
4726 case GL_KEEP:
4727 case GL_REPLACE:
4728 case GL_INCR:
4729 case GL_DECR:
4730 case GL_INVERT:
4731 case GL_INCR_WRAP:
4732 case GL_DECR_WRAP:
4733 break;
4734 default:
4735 return error(GL_INVALID_ENUM);
4736 }
4737
4738 switch(zpass)
4739 {
4740 case GL_ZERO:
4741 case GL_KEEP:
4742 case GL_REPLACE:
4743 case GL_INCR:
4744 case GL_DECR:
4745 case GL_INVERT:
4746 case GL_INCR_WRAP:
4747 case GL_DECR_WRAP:
4748 break;
4749 default:
4750 return error(GL_INVALID_ENUM);
4751 }
4752
Nicolas Capens14ee7622014-10-28 23:48:41 -04004753 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004754
4755 if(context)
4756 {
4757 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4758 {
4759 context->setStencilOperations(fail, zfail, zpass);
4760 }
4761
4762 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4763 {
4764 context->setStencilBackOperations(fail, zfail, zpass);
4765 }
4766 }
4767 }
4768 catch(std::bad_alloc&)
4769 {
4770 return error(GL_OUT_OF_MEMORY);
4771 }
4772}
4773
4774GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
4775{
4776 TRACE("(GLuint fence = %d)", fence);
4777
4778 try
4779 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004780 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004781
4782 if(context)
4783 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004784 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004785
4786 if(fenceObject == NULL)
4787 {
4788 return error(GL_INVALID_OPERATION, GL_TRUE);
4789 }
4790
4791 return fenceObject->testFence();
4792 }
4793 }
4794 catch(std::bad_alloc&)
4795 {
4796 error(GL_OUT_OF_MEMORY);
4797 }
4798
4799 return GL_TRUE;
4800}
4801
4802void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4803 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
4804{
4805 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
4806 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
4807 target, level, internalformat, width, height, border, format, type, pixels);
4808
4809 try
4810 {
4811 if(!validImageSize(level, width, height))
4812 {
4813 return error(GL_INVALID_VALUE);
4814 }
4815
4816 if(internalformat != format)
4817 {
4818 return error(GL_INVALID_OPERATION);
4819 }
4820
4821 switch(format)
4822 {
4823 case GL_ALPHA:
4824 case GL_LUMINANCE:
4825 case GL_LUMINANCE_ALPHA:
4826 switch(type)
4827 {
4828 case GL_UNSIGNED_BYTE:
4829 case GL_FLOAT:
4830 case GL_HALF_FLOAT_OES:
4831 break;
4832 default:
4833 return error(GL_INVALID_ENUM);
4834 }
4835 break;
4836 case GL_RGB:
4837 switch(type)
4838 {
4839 case GL_UNSIGNED_BYTE:
4840 case GL_UNSIGNED_SHORT_5_6_5:
4841 case GL_FLOAT:
4842 case GL_HALF_FLOAT_OES:
4843 break;
4844 default:
4845 return error(GL_INVALID_ENUM);
4846 }
4847 break;
4848 case GL_RGBA:
4849 switch(type)
4850 {
4851 case GL_UNSIGNED_BYTE:
4852 case GL_UNSIGNED_SHORT_4_4_4_4:
4853 case GL_UNSIGNED_SHORT_5_5_5_1:
4854 case GL_FLOAT:
4855 case GL_HALF_FLOAT_OES:
4856 break;
4857 default:
4858 return error(GL_INVALID_ENUM);
4859 }
4860 break;
4861 case GL_BGRA_EXT:
4862 switch(type)
4863 {
4864 case GL_UNSIGNED_BYTE:
4865 break;
4866 default:
4867 return error(GL_INVALID_ENUM);
4868 }
4869 break;
4870 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
4871 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
4872 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
4873 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
4874 break;
4875 case GL_DEPTH_COMPONENT:
4876 switch(type)
4877 {
4878 case GL_UNSIGNED_SHORT:
4879 case GL_UNSIGNED_INT:
4880 break;
4881 default:
4882 return error(GL_INVALID_ENUM);
4883 }
4884 break;
4885 case GL_DEPTH_STENCIL_OES:
4886 switch(type)
4887 {
4888 case GL_UNSIGNED_INT_24_8_OES:
4889 break;
4890 default:
4891 return error(GL_INVALID_ENUM);
4892 }
4893 break;
4894 default:
4895 return error(GL_INVALID_VALUE);
4896 }
4897
4898 if(border != 0)
4899 {
4900 return error(GL_INVALID_VALUE);
4901 }
4902
Nicolas Capens14ee7622014-10-28 23:48:41 -04004903 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004904
4905 if(context)
4906 {
4907 switch(target)
4908 {
4909 case GL_TEXTURE_2D:
Nicolas Capens14ee7622014-10-28 23:48:41 -04004910 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4911 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -04004912 {
4913 return error(GL_INVALID_VALUE);
4914 }
4915 break;
4916 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4917 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4918 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4919 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4920 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4921 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4922 if(width != height)
4923 {
4924 return error(GL_INVALID_VALUE);
4925 }
4926
Nicolas Capens14ee7622014-10-28 23:48:41 -04004927 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4928 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -04004929 {
4930 return error(GL_INVALID_VALUE);
4931 }
4932 break;
4933 default:
4934 return error(GL_INVALID_ENUM);
4935 }
4936
4937 if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
4938 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
4939 format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
4940 format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
4941 {
4942 if(S3TC_SUPPORT)
4943 {
4944 return error(GL_INVALID_OPERATION);
4945 }
4946 else
4947 {
4948 return error(GL_INVALID_ENUM);
4949 }
4950 }
4951
4952 if(target == GL_TEXTURE_2D)
4953 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004954 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04004955
4956 if(!texture)
4957 {
4958 return error(GL_INVALID_OPERATION);
4959 }
4960
4961 texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
4962 }
4963 else
4964 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004965 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04004966
4967 if(!texture)
4968 {
4969 return error(GL_INVALID_OPERATION);
4970 }
4971
4972 texture->setImage(target, level, width, height, format, type, context->getUnpackAlignment(), pixels);
4973 }
4974 }
4975 }
4976 catch(std::bad_alloc&)
4977 {
4978 return error(GL_OUT_OF_MEMORY);
4979 }
4980}
4981
4982void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
4983{
4984 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4985
4986 try
4987 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004988 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004989
4990 if(context)
4991 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04004992 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04004993
4994 switch(target)
4995 {
4996 case GL_TEXTURE_2D:
4997 texture = context->getTexture2D();
4998 break;
4999 case GL_TEXTURE_CUBE_MAP:
5000 texture = context->getTextureCubeMap();
5001 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005002 case GL_TEXTURE_EXTERNAL_OES:
5003 texture = context->getTextureExternal();
5004 break;
John Bauman66b8ab22014-05-06 15:57:45 -04005005 default:
5006 return error(GL_INVALID_ENUM);
5007 }
5008
5009 switch(pname)
5010 {
5011 case GL_TEXTURE_WRAP_S:
5012 if(!texture->setWrapS((GLenum)param))
5013 {
5014 return error(GL_INVALID_ENUM);
5015 }
5016 break;
5017 case GL_TEXTURE_WRAP_T:
5018 if(!texture->setWrapT((GLenum)param))
5019 {
5020 return error(GL_INVALID_ENUM);
5021 }
5022 break;
5023 case GL_TEXTURE_MIN_FILTER:
5024 if(!texture->setMinFilter((GLenum)param))
5025 {
5026 return error(GL_INVALID_ENUM);
5027 }
5028 break;
5029 case GL_TEXTURE_MAG_FILTER:
5030 if(!texture->setMagFilter((GLenum)param))
5031 {
5032 return error(GL_INVALID_ENUM);
5033 }
5034 break;
5035 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5036 if(!texture->setMaxAnisotropy(param))
5037 {
5038 return error(GL_INVALID_VALUE);
5039 }
5040 break;
5041 default:
5042 return error(GL_INVALID_ENUM);
5043 }
5044 }
5045 }
5046 catch(std::bad_alloc&)
5047 {
5048 return error(GL_OUT_OF_MEMORY);
5049 }
5050}
5051
5052void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5053{
5054 glTexParameterf(target, pname, *params);
5055}
5056
5057void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
5058{
5059 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
5060
5061 try
5062 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005063 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005064
5065 if(context)
5066 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005067 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04005068
5069 switch(target)
5070 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005071 case GL_TEXTURE_2D:
John Bauman66b8ab22014-05-06 15:57:45 -04005072 texture = context->getTexture2D();
5073 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005074 case GL_TEXTURE_CUBE_MAP:
John Bauman66b8ab22014-05-06 15:57:45 -04005075 texture = context->getTextureCubeMap();
5076 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005077 case GL_TEXTURE_EXTERNAL_OES:
5078 texture = context->getTextureExternal();
5079 break;
5080 default:
John Bauman66b8ab22014-05-06 15:57:45 -04005081 return error(GL_INVALID_ENUM);
5082 }
5083
5084 switch(pname)
5085 {
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005086 case GL_TEXTURE_WRAP_S:
John Bauman66b8ab22014-05-06 15:57:45 -04005087 if(!texture->setWrapS((GLenum)param))
5088 {
5089 return error(GL_INVALID_ENUM);
5090 }
5091 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005092 case GL_TEXTURE_WRAP_T:
John Bauman66b8ab22014-05-06 15:57:45 -04005093 if(!texture->setWrapT((GLenum)param))
5094 {
5095 return error(GL_INVALID_ENUM);
5096 }
5097 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005098 case GL_TEXTURE_MIN_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04005099 if(!texture->setMinFilter((GLenum)param))
5100 {
5101 return error(GL_INVALID_ENUM);
5102 }
5103 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005104 case GL_TEXTURE_MAG_FILTER:
John Bauman66b8ab22014-05-06 15:57:45 -04005105 if(!texture->setMagFilter((GLenum)param))
5106 {
5107 return error(GL_INVALID_ENUM);
5108 }
5109 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005110 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
John Bauman66b8ab22014-05-06 15:57:45 -04005111 if(!texture->setMaxAnisotropy((GLfloat)param))
5112 {
5113 return error(GL_INVALID_VALUE);
5114 }
5115 break;
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04005116 default:
John Bauman66b8ab22014-05-06 15:57:45 -04005117 return error(GL_INVALID_ENUM);
5118 }
5119 }
5120 }
5121 catch(std::bad_alloc&)
5122 {
5123 return error(GL_OUT_OF_MEMORY);
5124 }
5125}
5126
5127void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
5128{
5129 glTexParameteri(target, pname, *params);
5130}
5131
5132void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
5133 GLenum format, GLenum type, const GLvoid* pixels)
5134{
5135 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5136 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
5137 "const GLvoid* pixels = 0x%0.8p)",
5138 target, level, xoffset, yoffset, width, height, format, type, pixels);
5139
5140 try
5141 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005142 if(!es2::IsTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04005143 {
5144 return error(GL_INVALID_ENUM);
5145 }
5146
5147 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5148 {
5149 return error(GL_INVALID_VALUE);
5150 }
5151
5152 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5153 {
5154 return error(GL_INVALID_VALUE);
5155 }
5156
Nicolas Capens14ee7622014-10-28 23:48:41 -04005157 if(!es2::CheckTextureFormatType(format, type))
John Bauman66b8ab22014-05-06 15:57:45 -04005158 {
5159 return error(GL_INVALID_ENUM);
5160 }
5161
5162 if(width == 0 || height == 0 || pixels == NULL)
5163 {
5164 return;
5165 }
5166
Nicolas Capens14ee7622014-10-28 23:48:41 -04005167 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005168
5169 if(context)
5170 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005171 if(level > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
John Bauman66b8ab22014-05-06 15:57:45 -04005172 {
5173 return error(GL_INVALID_VALUE);
5174 }
5175
5176 if(target == GL_TEXTURE_2D)
5177 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005178 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04005179
5180 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
5181 {
5182 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
5183 }
5184 }
Nicolas Capens14ee7622014-10-28 23:48:41 -04005185 else if(es2::IsCubemapTextureTarget(target))
John Bauman66b8ab22014-05-06 15:57:45 -04005186 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005187 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04005188
5189 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
5190 {
5191 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
5192 }
5193 }
5194 else
5195 {
5196 UNREACHABLE();
5197 }
5198 }
5199 }
5200 catch(std::bad_alloc&)
5201 {
5202 return error(GL_OUT_OF_MEMORY);
5203 }
5204}
5205
5206void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
5207{
5208 glUniform1fv(location, 1, &x);
5209}
5210
5211void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
5212{
5213 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5214
5215 try
5216 {
5217 if(count < 0)
5218 {
5219 return error(GL_INVALID_VALUE);
5220 }
5221
5222 if(location == -1)
5223 {
5224 return;
5225 }
5226
Nicolas Capens14ee7622014-10-28 23:48:41 -04005227 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005228
5229 if(context)
5230 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005231 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005232
5233 if(!program)
5234 {
5235 return error(GL_INVALID_OPERATION);
5236 }
5237
5238 if(!program->setUniform1fv(location, count, v))
5239 {
5240 return error(GL_INVALID_OPERATION);
5241 }
5242 }
5243 }
5244 catch(std::bad_alloc&)
5245 {
5246 return error(GL_OUT_OF_MEMORY);
5247 }
5248}
5249
5250void GL_APIENTRY glUniform1i(GLint location, GLint x)
5251{
5252 glUniform1iv(location, 1, &x);
5253}
5254
5255void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
5256{
5257 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5258
5259 try
5260 {
5261 if(count < 0)
5262 {
5263 return error(GL_INVALID_VALUE);
5264 }
5265
5266 if(location == -1)
5267 {
5268 return;
5269 }
5270
Nicolas Capens14ee7622014-10-28 23:48:41 -04005271 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005272
5273 if(context)
5274 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005275 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005276
5277 if(!program)
5278 {
5279 return error(GL_INVALID_OPERATION);
5280 }
5281
5282 if(!program->setUniform1iv(location, count, v))
5283 {
5284 return error(GL_INVALID_OPERATION);
5285 }
5286 }
5287 }
5288 catch(std::bad_alloc&)
5289 {
5290 return error(GL_OUT_OF_MEMORY);
5291 }
5292}
5293
5294void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
5295{
5296 GLfloat xy[2] = {x, y};
5297
5298 glUniform2fv(location, 1, (GLfloat*)&xy);
5299}
5300
5301void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
5302{
5303 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5304
5305 try
5306 {
5307 if(count < 0)
5308 {
5309 return error(GL_INVALID_VALUE);
5310 }
5311
5312 if(location == -1)
5313 {
5314 return;
5315 }
5316
Nicolas Capens14ee7622014-10-28 23:48:41 -04005317 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005318
5319 if(context)
5320 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005321 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005322
5323 if(!program)
5324 {
5325 return error(GL_INVALID_OPERATION);
5326 }
5327
5328 if(!program->setUniform2fv(location, count, v))
5329 {
5330 return error(GL_INVALID_OPERATION);
5331 }
5332 }
5333 }
5334 catch(std::bad_alloc&)
5335 {
5336 return error(GL_OUT_OF_MEMORY);
5337 }
5338}
5339
5340void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
5341{
5342 GLint xy[4] = {x, y};
5343
5344 glUniform2iv(location, 1, (GLint*)&xy);
5345}
5346
5347void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
5348{
5349 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5350
5351 try
5352 {
5353 if(count < 0)
5354 {
5355 return error(GL_INVALID_VALUE);
5356 }
5357
5358 if(location == -1)
5359 {
5360 return;
5361 }
5362
Nicolas Capens14ee7622014-10-28 23:48:41 -04005363 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005364
5365 if(context)
5366 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005367 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005368
5369 if(!program)
5370 {
5371 return error(GL_INVALID_OPERATION);
5372 }
5373
5374 if(!program->setUniform2iv(location, count, v))
5375 {
5376 return error(GL_INVALID_OPERATION);
5377 }
5378 }
5379 }
5380 catch(std::bad_alloc&)
5381 {
5382 return error(GL_OUT_OF_MEMORY);
5383 }
5384}
5385
5386void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5387{
5388 GLfloat xyz[3] = {x, y, z};
5389
5390 glUniform3fv(location, 1, (GLfloat*)&xyz);
5391}
5392
5393void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
5394{
5395 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5396
5397 try
5398 {
5399 if(count < 0)
5400 {
5401 return error(GL_INVALID_VALUE);
5402 }
5403
5404 if(location == -1)
5405 {
5406 return;
5407 }
5408
Nicolas Capens14ee7622014-10-28 23:48:41 -04005409 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005410
5411 if(context)
5412 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005413 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005414
5415 if(!program)
5416 {
5417 return error(GL_INVALID_OPERATION);
5418 }
5419
5420 if(!program->setUniform3fv(location, count, v))
5421 {
5422 return error(GL_INVALID_OPERATION);
5423 }
5424 }
5425 }
5426 catch(std::bad_alloc&)
5427 {
5428 return error(GL_OUT_OF_MEMORY);
5429 }
5430}
5431
5432void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
5433{
5434 GLint xyz[3] = {x, y, z};
5435
5436 glUniform3iv(location, 1, (GLint*)&xyz);
5437}
5438
5439void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
5440{
5441 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5442
5443 try
5444 {
5445 if(count < 0)
5446 {
5447 return error(GL_INVALID_VALUE);
5448 }
5449
5450 if(location == -1)
5451 {
5452 return;
5453 }
5454
Nicolas Capens14ee7622014-10-28 23:48:41 -04005455 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005456
5457 if(context)
5458 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005459 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005460
5461 if(!program)
5462 {
5463 return error(GL_INVALID_OPERATION);
5464 }
5465
5466 if(!program->setUniform3iv(location, count, v))
5467 {
5468 return error(GL_INVALID_OPERATION);
5469 }
5470 }
5471 }
5472 catch(std::bad_alloc&)
5473 {
5474 return error(GL_OUT_OF_MEMORY);
5475 }
5476}
5477
5478void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5479{
5480 GLfloat xyzw[4] = {x, y, z, w};
5481
5482 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5483}
5484
5485void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
5486{
5487 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
5488
5489 try
5490 {
5491 if(count < 0)
5492 {
5493 return error(GL_INVALID_VALUE);
5494 }
5495
5496 if(location == -1)
5497 {
5498 return;
5499 }
5500
Nicolas Capens14ee7622014-10-28 23:48:41 -04005501 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005502
5503 if(context)
5504 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005505 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005506
5507 if(!program)
5508 {
5509 return error(GL_INVALID_OPERATION);
5510 }
5511
5512 if(!program->setUniform4fv(location, count, v))
5513 {
5514 return error(GL_INVALID_OPERATION);
5515 }
5516 }
5517 }
5518 catch(std::bad_alloc&)
5519 {
5520 return error(GL_OUT_OF_MEMORY);
5521 }
5522}
5523
5524void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5525{
5526 GLint xyzw[4] = {x, y, z, w};
5527
5528 glUniform4iv(location, 1, (GLint*)&xyzw);
5529}
5530
5531void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
5532{
5533 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
5534
5535 try
5536 {
5537 if(count < 0)
5538 {
5539 return error(GL_INVALID_VALUE);
5540 }
5541
5542 if(location == -1)
5543 {
5544 return;
5545 }
5546
Nicolas Capens14ee7622014-10-28 23:48:41 -04005547 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005548
5549 if(context)
5550 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005551 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005552
5553 if(!program)
5554 {
5555 return error(GL_INVALID_OPERATION);
5556 }
5557
5558 if(!program->setUniform4iv(location, count, v))
5559 {
5560 return error(GL_INVALID_OPERATION);
5561 }
5562 }
5563 }
5564 catch(std::bad_alloc&)
5565 {
5566 return error(GL_OUT_OF_MEMORY);
5567 }
5568}
5569
5570void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5571{
5572 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5573 location, count, transpose, value);
5574
5575 try
5576 {
5577 if(count < 0 || transpose != GL_FALSE)
5578 {
5579 return error(GL_INVALID_VALUE);
5580 }
5581
5582 if(location == -1)
5583 {
5584 return;
5585 }
5586
Nicolas Capens14ee7622014-10-28 23:48:41 -04005587 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005588
5589 if(context)
5590 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005591 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005592
5593 if(!program)
5594 {
5595 return error(GL_INVALID_OPERATION);
5596 }
5597
5598 if(!program->setUniformMatrix2fv(location, count, value))
5599 {
5600 return error(GL_INVALID_OPERATION);
5601 }
5602 }
5603 }
5604 catch(std::bad_alloc&)
5605 {
5606 return error(GL_OUT_OF_MEMORY);
5607 }
5608}
5609
5610void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5611{
5612 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5613 location, count, transpose, value);
5614
5615 try
5616 {
5617 if(count < 0 || transpose != GL_FALSE)
5618 {
5619 return error(GL_INVALID_VALUE);
5620 }
5621
5622 if(location == -1)
5623 {
5624 return;
5625 }
5626
Nicolas Capens14ee7622014-10-28 23:48:41 -04005627 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005628
5629 if(context)
5630 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005631 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005632
5633 if(!program)
5634 {
5635 return error(GL_INVALID_OPERATION);
5636 }
5637
5638 if(!program->setUniformMatrix3fv(location, count, value))
5639 {
5640 return error(GL_INVALID_OPERATION);
5641 }
5642 }
5643 }
5644 catch(std::bad_alloc&)
5645 {
5646 return error(GL_OUT_OF_MEMORY);
5647 }
5648}
5649
5650void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5651{
5652 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5653 location, count, transpose, value);
5654
5655 try
5656 {
5657 if(count < 0 || transpose != GL_FALSE)
5658 {
5659 return error(GL_INVALID_VALUE);
5660 }
5661
5662 if(location == -1)
5663 {
5664 return;
5665 }
5666
Nicolas Capens14ee7622014-10-28 23:48:41 -04005667 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005668
5669 if(context)
5670 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005671 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005672
5673 if(!program)
5674 {
5675 return error(GL_INVALID_OPERATION);
5676 }
5677
5678 if(!program->setUniformMatrix4fv(location, count, value))
5679 {
5680 return error(GL_INVALID_OPERATION);
5681 }
5682 }
5683 }
5684 catch(std::bad_alloc&)
5685 {
5686 return error(GL_OUT_OF_MEMORY);
5687 }
5688}
5689
5690void GL_APIENTRY glUseProgram(GLuint program)
5691{
5692 TRACE("(GLuint program = %d)", program);
5693
5694 try
5695 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005696 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005697
5698 if(context)
5699 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005700 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04005701
5702 if(!programObject && program != 0)
5703 {
5704 if(context->getShader(program))
5705 {
5706 return error(GL_INVALID_OPERATION);
5707 }
5708 else
5709 {
5710 return error(GL_INVALID_VALUE);
5711 }
5712 }
5713
5714 if(program != 0 && !programObject->isLinked())
5715 {
5716 return error(GL_INVALID_OPERATION);
5717 }
5718
5719 context->useProgram(program);
5720 }
5721 }
5722 catch(std::bad_alloc&)
5723 {
5724 return error(GL_OUT_OF_MEMORY);
5725 }
5726}
5727
5728void GL_APIENTRY glValidateProgram(GLuint program)
5729{
5730 TRACE("(GLuint program = %d)", program);
5731
5732 try
5733 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005734 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005735
5736 if(context)
5737 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005738 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04005739
5740 if(!programObject)
5741 {
5742 if(context->getShader(program))
5743 {
5744 return error(GL_INVALID_OPERATION);
5745 }
5746 else
5747 {
5748 return error(GL_INVALID_VALUE);
5749 }
5750 }
5751
5752 programObject->validate();
5753 }
5754 }
5755 catch(std::bad_alloc&)
5756 {
5757 return error(GL_OUT_OF_MEMORY);
5758 }
5759}
5760
5761void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)
5762{
5763 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5764
5765 try
5766 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005767 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005768 {
5769 return error(GL_INVALID_VALUE);
5770 }
5771
Nicolas Capens14ee7622014-10-28 23:48:41 -04005772 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005773
5774 if(context)
5775 {
5776 GLfloat vals[4] = { x, 0, 0, 1 };
5777 context->setVertexAttrib(index, vals);
5778 }
5779 }
5780 catch(std::bad_alloc&)
5781 {
5782 return error(GL_OUT_OF_MEMORY);
5783 }
5784}
5785
5786void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)
5787{
5788 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5789
5790 try
5791 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005792 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005793 {
5794 return error(GL_INVALID_VALUE);
5795 }
5796
Nicolas Capens14ee7622014-10-28 23:48:41 -04005797 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005798
5799 if(context)
5800 {
5801 GLfloat vals[4] = { values[0], 0, 0, 1 };
5802 context->setVertexAttrib(index, vals);
5803 }
5804 }
5805 catch(std::bad_alloc&)
5806 {
5807 return error(GL_OUT_OF_MEMORY);
5808 }
5809}
5810
5811void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5812{
5813 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5814
5815 try
5816 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005817 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005818 {
5819 return error(GL_INVALID_VALUE);
5820 }
5821
Nicolas Capens14ee7622014-10-28 23:48:41 -04005822 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005823
5824 if(context)
5825 {
5826 GLfloat vals[4] = { x, y, 0, 1 };
5827 context->setVertexAttrib(index, vals);
5828 }
5829 }
5830 catch(std::bad_alloc&)
5831 {
5832 return error(GL_OUT_OF_MEMORY);
5833 }
5834}
5835
5836void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)
5837{
5838 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5839
5840 try
5841 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005842 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005843 {
5844 return error(GL_INVALID_VALUE);
5845 }
5846
Nicolas Capens14ee7622014-10-28 23:48:41 -04005847 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005848
5849 if(context)
5850 {
5851 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5852 context->setVertexAttrib(index, vals);
5853 }
5854 }
5855 catch(std::bad_alloc&)
5856 {
5857 return error(GL_OUT_OF_MEMORY);
5858 }
5859}
5860
5861void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5862{
5863 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5864
5865 try
5866 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005867 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005868 {
5869 return error(GL_INVALID_VALUE);
5870 }
5871
Nicolas Capens14ee7622014-10-28 23:48:41 -04005872 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005873
5874 if(context)
5875 {
5876 GLfloat vals[4] = { x, y, z, 1 };
5877 context->setVertexAttrib(index, vals);
5878 }
5879 }
5880 catch(std::bad_alloc&)
5881 {
5882 return error(GL_OUT_OF_MEMORY);
5883 }
5884}
5885
5886void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)
5887{
5888 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5889
5890 try
5891 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005892 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005893 {
5894 return error(GL_INVALID_VALUE);
5895 }
5896
Nicolas Capens14ee7622014-10-28 23:48:41 -04005897 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005898
5899 if(context)
5900 {
5901 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5902 context->setVertexAttrib(index, vals);
5903 }
5904 }
5905 catch(std::bad_alloc&)
5906 {
5907 return error(GL_OUT_OF_MEMORY);
5908 }
5909}
5910
5911void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5912{
5913 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5914
5915 try
5916 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005917 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005918 {
5919 return error(GL_INVALID_VALUE);
5920 }
5921
Nicolas Capens14ee7622014-10-28 23:48:41 -04005922 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005923
5924 if(context)
5925 {
5926 GLfloat vals[4] = { x, y, z, w };
5927 context->setVertexAttrib(index, vals);
5928 }
5929 }
5930 catch(std::bad_alloc&)
5931 {
5932 return error(GL_OUT_OF_MEMORY);
5933 }
5934}
5935
5936void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)
5937{
5938 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
5939
5940 try
5941 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005942 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005943 {
5944 return error(GL_INVALID_VALUE);
5945 }
5946
Nicolas Capens14ee7622014-10-28 23:48:41 -04005947 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005948
5949 if(context)
5950 {
5951 context->setVertexAttrib(index, values);
5952 }
5953 }
5954 catch(std::bad_alloc&)
5955 {
5956 return error(GL_OUT_OF_MEMORY);
5957 }
5958}
5959
5960void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5961{
5962 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5963 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
5964 index, size, type, normalized, stride, ptr);
5965
5966 try
5967 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04005968 if(index >= es2::MAX_VERTEX_ATTRIBS)
John Bauman66b8ab22014-05-06 15:57:45 -04005969 {
5970 return error(GL_INVALID_VALUE);
5971 }
5972
5973 if(size < 1 || size > 4)
5974 {
5975 return error(GL_INVALID_VALUE);
5976 }
5977
5978 switch(type)
5979 {
5980 case GL_BYTE:
5981 case GL_UNSIGNED_BYTE:
5982 case GL_SHORT:
5983 case GL_UNSIGNED_SHORT:
5984 case GL_FIXED:
5985 case GL_FLOAT:
5986 break;
5987 default:
5988 return error(GL_INVALID_ENUM);
5989 }
5990
5991 if(stride < 0)
5992 {
5993 return error(GL_INVALID_VALUE);
5994 }
5995
Nicolas Capens14ee7622014-10-28 23:48:41 -04005996 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005997
5998 if(context)
5999 {
6000 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
6001 }
6002 }
6003 catch(std::bad_alloc&)
6004 {
6005 return error(GL_OUT_OF_MEMORY);
6006 }
6007}
6008
6009void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
6010{
6011 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
6012
6013 try
6014 {
6015 if(width < 0 || height < 0)
6016 {
6017 return error(GL_INVALID_VALUE);
6018 }
6019
Nicolas Capens14ee7622014-10-28 23:48:41 -04006020 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006021
6022 if(context)
6023 {
6024 context->setViewportParams(x, y, width, height);
6025 }
6026 }
6027 catch(std::bad_alloc&)
6028 {
6029 return error(GL_OUT_OF_MEMORY);
6030 }
6031}
6032
6033void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6034 GLbitfield mask, GLenum filter)
6035{
6036 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6037 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6038 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6039 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6040
6041 try
6042 {
6043 switch(filter)
6044 {
6045 case GL_NEAREST:
6046 break;
6047 default:
6048 return error(GL_INVALID_ENUM);
6049 }
6050
6051 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6052 {
6053 return error(GL_INVALID_VALUE);
6054 }
6055
6056 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6057 {
6058 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6059 return error(GL_INVALID_OPERATION);
6060 }
6061
Nicolas Capens14ee7622014-10-28 23:48:41 -04006062 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006063
6064 if(context)
6065 {
6066 if(context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
6067 {
6068 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6069 return error(GL_INVALID_OPERATION);
6070 }
6071
6072 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
6073 }
6074 }
6075 catch(std::bad_alloc&)
6076 {
6077 return error(GL_OUT_OF_MEMORY);
6078 }
6079}
6080
6081void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
6082 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
6083{
6084 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6085 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
6086 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
6087 target, level, internalformat, width, height, depth, border, format, type, pixels);
6088
6089 try
6090 {
Nicolas Capensd76b5df2014-10-28 15:54:46 -04006091 UNIMPLEMENTED(); // FIXME
John Bauman66b8ab22014-05-06 15:57:45 -04006092 }
6093 catch(std::bad_alloc&)
6094 {
6095 return error(GL_OUT_OF_MEMORY);
6096 }
6097}
6098
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006099void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6100{
Nicolas Capensd76b5df2014-10-28 15:54:46 -04006101 if(egl::getClientVersion() == 1)
6102 {
Nicolas Capensf3d2efd2014-10-29 11:27:55 -04006103 static auto glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)es1::getProcAddress("glEGLImageTargetTexture2DOES");
Nicolas Capensd76b5df2014-10-28 15:54:46 -04006104 return glEGLImageTargetTexture2DOES(target, image);
6105 }
6106
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006107 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
6108
6109 try
6110 {
6111 switch(target)
6112 {
6113 case GL_TEXTURE_EXTERNAL_OES:
6114 break;
6115 default:
6116 return error(GL_INVALID_ENUM);
6117 }
6118
6119 if(!image)
6120 {
6121 return error(GL_INVALID_OPERATION);
6122 }
6123
Nicolas Capens14ee7622014-10-28 23:48:41 -04006124 es2::Context *context = es2::getContext();
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006125
6126 if(context)
6127 {
Nicolas Capens14ee7622014-10-28 23:48:41 -04006128 es2::TextureExternal *texture = context->getTextureExternal();
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006129
6130 if(!texture)
6131 {
6132 return error(GL_INVALID_OPERATION);
6133 }
6134
Nicolas Capens14ee7622014-10-28 23:48:41 -04006135 es2::Image *glImage = static_cast<es2::Image*>(image);
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006136
6137 texture->setImage(glImage);
6138 }
6139 }
6140 catch(std::bad_alloc&)
6141 {
6142 return error(GL_OUT_OF_MEMORY);
6143 }
6144}
6145
Nicolas Capens7e12ac62014-11-05 17:07:53 -05006146void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6147{
6148 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
6149
6150 UNIMPLEMENTED();
6151}
6152
John Bauman66b8ab22014-05-06 15:57:45 -04006153__eglMustCastToProperFunctionPointerType glGetProcAddress(const char *procname)
6154{
6155 struct Extension
6156 {
6157 const char *name;
6158 __eglMustCastToProperFunctionPointerType address;
6159 };
6160
6161 static const Extension glExtensions[] =
6162 {
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006163 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6164
6165 EXTENSION(glTexImage3DOES),
6166 EXTENSION(glBlitFramebufferANGLE),
6167 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6168 EXTENSION(glDeleteFencesNV),
6169 EXTENSION(glGenFencesNV),
6170 EXTENSION(glIsFenceNV),
6171 EXTENSION(glTestFenceNV),
6172 EXTENSION(glGetFenceivNV),
6173 EXTENSION(glFinishFenceNV),
6174 EXTENSION(glSetFenceNV),
6175 EXTENSION(glGetGraphicsResetStatusEXT),
6176 EXTENSION(glReadnPixelsEXT),
6177 EXTENSION(glGetnUniformfvEXT),
6178 EXTENSION(glGetnUniformivEXT),
6179 EXTENSION(glGenQueriesEXT),
6180 EXTENSION(glDeleteQueriesEXT),
6181 EXTENSION(glIsQueryEXT),
6182 EXTENSION(glBeginQueryEXT),
6183 EXTENSION(glEndQueryEXT),
6184 EXTENSION(glGetQueryivEXT),
6185 EXTENSION(glGetQueryObjectuivEXT),
6186 EXTENSION(glEGLImageTargetTexture2DOES),
Nicolas Capens7e12ac62014-11-05 17:07:53 -05006187 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006188
6189 #undef EXTENSION
John Bauman66b8ab22014-05-06 15:57:45 -04006190 };
6191
6192 for(int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
6193 {
6194 if(strcmp(procname, glExtensions[ext].name) == 0)
6195 {
6196 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
6197 }
6198 }
6199
6200 return NULL;
6201}
6202
John Baumand4ae8632014-05-06 16:18:33 -04006203void GL_APIENTRY Register(const char *licenseKey)
6204{
6205 RegisterLicenseKey(licenseKey);
6206}
6207
John Bauman66b8ab22014-05-06 15:57:45 -04006208}