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