blob: e528154c966ce553dcade06fa21639feb1eb28ba [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001// SwiftShader Software Renderer
2//
3// Copyright(c) 2005-2013 TransGaming Inc.
4//
5// All rights reserved. No part of this software may be copied, distributed, transmitted,
6// transcribed, stored in a retrieval system, translated into any human or computer
7// language by any means, or disclosed to third parties without the explicit written
8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9// or implied, including but not limited to any patent rights, are granted to you.
10//
11// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
12
13#include "main.h"
14#include "mathutil.h"
15#include "utilities.h"
16#include "Buffer.h"
17#include "Context.h"
18#include "Fence.h"
19#include "Framebuffer.h"
20#include "Program.h"
21#include "Renderbuffer.h"
22#include "Shader.h"
23#include "Texture.h"
24#include "Query.h"
25#include "common/debug.h"
26#include "Common/Version.h"
John Baumand4ae8632014-05-06 16:18:33 -040027#include "Main/Register.hpp"
John Bauman66b8ab22014-05-06 15:57:45 -040028
29#define GL_APICALL
30#include <GLES2/gl2.h>
31#include <GLES2/gl2ext.h>
Alexis Hetufceb1832015-03-10 16:42:04 -040032#include <GLES3/gl3.h>
John Bauman66b8ab22014-05-06 15:57:45 -040033
John Bauman66b8ab22014-05-06 15:57:45 -040034#include <limits>
35
Greg Hartman6074f122015-04-08 09:57:16 -070036#ifdef ANDROID
37#include <cutils/log.h>
38#endif
39
Nicolas Capensa2308052015-04-15 16:50:21 -040040using namespace es2;
41
Alexis Hetub027aa92015-01-19 15:56:12 -050042typedef std::pair<GLenum, GLenum> InternalFormatTypePair;
43typedef std::map<InternalFormatTypePair, GLenum> FormatMap;
44
45// A helper function to insert data into the format map with fewer characters.
46static void InsertFormatMapping(FormatMap& map, GLenum internalformat, GLenum format, GLenum type)
47{
48 map[InternalFormatTypePair(internalformat, type)] = format;
49}
50
John Bauman66b8ab22014-05-06 15:57:45 -040051static bool validImageSize(GLint level, GLsizei width, GLsizei height)
52{
Nicolas Capensf160b172014-11-26 11:58:23 -050053 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
54 {
55 return false;
56 }
John Bauman66b8ab22014-05-06 15:57:45 -040057
Nicolas Capensf160b172014-11-26 11:58:23 -050058 return true;
John Bauman66b8ab22014-05-06 15:57:45 -040059}
60
Nicolas Capens14ee7622014-10-28 23:48:41 -040061static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)
John Bauman66b8ab22014-05-06 15:57:45 -040062{
Nicolas Capensf160b172014-11-26 11:58:23 -050063 if(!texture)
64 {
65 return error(GL_INVALID_OPERATION, false);
66 }
John Bauman66b8ab22014-05-06 15:57:45 -040067
Nicolas Capensf160b172014-11-26 11:58:23 -050068 if(compressed != texture->isCompressed(target, level))
69 {
70 return error(GL_INVALID_OPERATION, false);
71 }
John Bauman66b8ab22014-05-06 15:57:45 -040072
Nicolas Capensf160b172014-11-26 11:58:23 -050073 if(format != GL_NONE && format != texture->getFormat(target, level))
74 {
75 return error(GL_INVALID_OPERATION, false);
76 }
John Bauman66b8ab22014-05-06 15:57:45 -040077
Nicolas Capensf160b172014-11-26 11:58:23 -050078 if(compressed)
79 {
80 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
Alexis Hetub027aa92015-01-19 15:56:12 -050081 (height % 4 != 0 && height != texture->getHeight(target, 0)))
Nicolas Capensf160b172014-11-26 11:58:23 -050082 {
83 return error(GL_INVALID_OPERATION, false);
84 }
85 }
John Bauman66b8ab22014-05-06 15:57:45 -040086
Nicolas Capensf160b172014-11-26 11:58:23 -050087 if(xoffset + width > texture->getWidth(target, level) ||
Alexis Hetub027aa92015-01-19 15:56:12 -050088 yoffset + height > texture->getHeight(target, level))
Nicolas Capensf160b172014-11-26 11:58:23 -050089 {
90 return error(GL_INVALID_VALUE, false);
91 }
John Bauman66b8ab22014-05-06 15:57:45 -040092
Nicolas Capensf160b172014-11-26 11:58:23 -050093 return true;
John Bauman66b8ab22014-05-06 15:57:45 -040094}
95
Alexis Hetub027aa92015-01-19 15:56:12 -050096static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)
97{
98 if(!texture)
99 {
100 return error(GL_INVALID_OPERATION, false);
101 }
102
103 if(compressed != texture->isCompressed(target, level))
104 {
105 return error(GL_INVALID_OPERATION, false);
106 }
107
108 if(format != GL_NONE && format != texture->getFormat(target, level))
109 {
110 return error(GL_INVALID_OPERATION, false);
111 }
112
113 if(compressed)
114 {
115 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
116 (height % 4 != 0 && height != texture->getHeight(target, 0)) ||
117 (depth % 4 != 0 && depth != texture->getDepth(target, 0)))
118 {
119 return error(GL_INVALID_OPERATION, false);
120 }
121 }
122
123 if(xoffset + width > texture->getWidth(target, level) ||
124 yoffset + height > texture->getHeight(target, level) ||
125 zoffset + depth > texture->getDepth(target, level))
126 {
127 return error(GL_INVALID_VALUE, false);
128 }
129
130 return true;
131}
132
133static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
134{
135 // [OpenGL ES 2.0.24] table 3.9
136 switch(textureFormat)
137 {
138 case GL_ALPHA:
139 if(colorbufferFormat != GL_ALPHA &&
140 colorbufferFormat != GL_RGBA &&
141 colorbufferFormat != GL_RGBA4 &&
142 colorbufferFormat != GL_RGB5_A1 &&
143 colorbufferFormat != GL_RGBA8_OES)
144 {
145 return error(GL_INVALID_OPERATION, false);
146 }
147 break;
148 case GL_LUMINANCE:
149 case GL_RGB:
150 if(colorbufferFormat != GL_RGB &&
151 colorbufferFormat != GL_RGB565 &&
152 colorbufferFormat != GL_RGB8_OES &&
153 colorbufferFormat != GL_RGBA &&
154 colorbufferFormat != GL_RGBA4 &&
155 colorbufferFormat != GL_RGB5_A1 &&
156 colorbufferFormat != GL_RGBA8_OES)
157 {
158 return error(GL_INVALID_OPERATION, false);
159 }
160 break;
161 case GL_LUMINANCE_ALPHA:
162 case GL_RGBA:
163 if(colorbufferFormat != GL_RGBA &&
164 colorbufferFormat != GL_RGBA4 &&
165 colorbufferFormat != GL_RGB5_A1 &&
166 colorbufferFormat != GL_RGBA8_OES)
167 {
168 return error(GL_INVALID_OPERATION, false);
169 }
170 break;
171 case GL_ETC1_RGB8_OES:
172 return error(GL_INVALID_OPERATION, false);
173 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
174 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
175 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
176 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
177 if(S3TC_SUPPORT)
178 {
179 return error(GL_INVALID_OPERATION, false);
180 }
181 else
182 {
183 return error(GL_INVALID_ENUM, false);
184 }
185 case GL_DEPTH_COMPONENT:
186 case GL_DEPTH_STENCIL_OES:
187 return error(GL_INVALID_OPERATION, false);
188 default:
189 return error(GL_INVALID_ENUM, false);
190 }
191 return true;
192}
193
194static FormatMap BuildFormatMap3D()
195{
196 FormatMap map;
197
198 // Internal format | Format | Type
199 InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
200 InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
201 InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
202 InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
203 InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
204 InsertFormatMapping(map, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
205 InsertFormatMapping(map, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
206 InsertFormatMapping(map, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
207 InsertFormatMapping(map, GL_R8_EXT, GL_RED_EXT, GL_UNSIGNED_BYTE);
208 InsertFormatMapping(map, GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
209 InsertFormatMapping(map, GL_R16F_EXT, GL_RED_EXT, GL_FLOAT);
210 InsertFormatMapping(map, GL_R32F_EXT, GL_RED_EXT, GL_FLOAT);
211 InsertFormatMapping(map, GL_RG8_EXT, GL_RG_EXT, GL_UNSIGNED_BYTE);
212 InsertFormatMapping(map, GL_R16F_EXT, GL_RED_EXT, GL_HALF_FLOAT_OES);
213 InsertFormatMapping(map, GL_R16F_EXT, GL_RED_EXT, GL_FLOAT);
214 InsertFormatMapping(map, GL_RG32F_EXT, GL_RG_EXT, GL_FLOAT);
215 InsertFormatMapping(map, GL_RGB8_OES, GL_RGB, GL_UNSIGNED_BYTE);
216 InsertFormatMapping(map, GL_SRGB8_NV, GL_RGB, GL_UNSIGNED_BYTE);
217 InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE);
218 InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
Alexis Hetu0300e3c2015-03-12 17:33:07 -0400219 InsertFormatMapping(map, GL_RGB16F_EXT, GL_RGB, GL_HALF_FLOAT_OES);
220 InsertFormatMapping(map, GL_RGB16F_EXT, GL_RGB, GL_FLOAT);
Alexis Hetub027aa92015-01-19 15:56:12 -0500221 InsertFormatMapping(map, GL_RGB32F_EXT, GL_RGB, GL_FLOAT);
222 InsertFormatMapping(map, GL_RGBA8_OES, GL_RGBA, GL_UNSIGNED_BYTE);
223 InsertFormatMapping(map, GL_SRGB8_ALPHA8_EXT, GL_RGBA, GL_UNSIGNED_BYTE);
224 InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE);
225 InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
226 InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV_EXT);
227 InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE);
228 InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
229 InsertFormatMapping(map, GL_RGB10_A2_EXT, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV_EXT);
230 InsertFormatMapping(map, GL_RGBA16F_EXT, GL_RGBA, GL_HALF_FLOAT_OES);
231 InsertFormatMapping(map, GL_RGBA16F_EXT, GL_RGBA, GL_FLOAT);
232 InsertFormatMapping(map, GL_RGBA32F_EXT, GL_RGBA, GL_FLOAT);
233
234 return map;
235}
236
237static bool ValidateType3D(GLenum type)
238{
239 switch(type)
240 {
241 case GL_UNSIGNED_BYTE:
242 case GL_BYTE:
243 case GL_UNSIGNED_SHORT:
244 case GL_SHORT:
245 case GL_UNSIGNED_INT:
246 case GL_INT:
247 case GL_HALF_FLOAT_OES:
248 case GL_FLOAT:
249 case GL_UNSIGNED_SHORT_5_6_5:
250 case GL_UNSIGNED_SHORT_4_4_4_4:
251 case GL_UNSIGNED_SHORT_5_5_5_1:
252 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
253 return true;
254 default:
255 break;
256 }
257 return false;
258}
259
260static bool ValidateFormat3D(GLenum format)
261{
262 switch(format)
263 {
264 case GL_RED_EXT:
265 case GL_RG_EXT:
266 case GL_RGB:
267 case GL_RGBA:
268 case GL_DEPTH_COMPONENT:
269 case GL_DEPTH_STENCIL_OES:
270 case GL_LUMINANCE_ALPHA:
271 case GL_LUMINANCE:
272 case GL_ALPHA:
273 return true;
274 default:
275 break;
276 }
277 return false;
278}
279
280static bool ValidateInternalFormat3D(GLenum internalformat, GLenum format, GLenum type)
281{
282 static const FormatMap formatMap = BuildFormatMap3D();
283 FormatMap::const_iterator iter = formatMap.find(InternalFormatTypePair(internalformat, type));
284 if(iter != formatMap.end())
285 {
286 return iter->second == format;
287 }
288 return false;
289}
290
John Bauman66b8ab22014-05-06 15:57:45 -0400291extern "C"
292{
293
294void GL_APIENTRY glActiveTexture(GLenum texture)
295{
Nicolas Capensf160b172014-11-26 11:58:23 -0500296 TRACE("(GLenum texture = 0x%X)", texture);
John Bauman66b8ab22014-05-06 15:57:45 -0400297
Nicolas Capensf160b172014-11-26 11:58:23 -0500298 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400299
Nicolas Capensf160b172014-11-26 11:58:23 -0500300 if(context)
301 {
302 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
303 {
304 return error(GL_INVALID_ENUM);
305 }
John Bauman66b8ab22014-05-06 15:57:45 -0400306
Nicolas Capensf160b172014-11-26 11:58:23 -0500307 context->setActiveSampler(texture - GL_TEXTURE0);
308 }
John Bauman66b8ab22014-05-06 15:57:45 -0400309}
310
311void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
312{
Nicolas Capensf160b172014-11-26 11:58:23 -0500313 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400314
Nicolas Capensf160b172014-11-26 11:58:23 -0500315 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400316
Nicolas Capensf160b172014-11-26 11:58:23 -0500317 if(context)
318 {
319 es2::Program *programObject = context->getProgram(program);
320 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400321
Nicolas Capensf160b172014-11-26 11:58:23 -0500322 if(!programObject)
323 {
324 if(context->getShader(program))
325 {
326 return error(GL_INVALID_OPERATION);
327 }
328 else
329 {
330 return error(GL_INVALID_VALUE);
331 }
332 }
John Bauman66b8ab22014-05-06 15:57:45 -0400333
Nicolas Capensf160b172014-11-26 11:58:23 -0500334 if(!shaderObject)
335 {
336 if(context->getProgram(shader))
337 {
338 return error(GL_INVALID_OPERATION);
339 }
340 else
341 {
342 return error(GL_INVALID_VALUE);
343 }
344 }
John Bauman66b8ab22014-05-06 15:57:45 -0400345
Nicolas Capensf160b172014-11-26 11:58:23 -0500346 if(!programObject->attachShader(shaderObject))
347 {
348 return error(GL_INVALID_OPERATION);
349 }
350 }
John Bauman66b8ab22014-05-06 15:57:45 -0400351}
352
Nicolas Capens7cc75e12015-01-29 14:44:24 -0500353void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint name)
John Bauman66b8ab22014-05-06 15:57:45 -0400354{
Nicolas Capens7cc75e12015-01-29 14:44:24 -0500355 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
John Bauman66b8ab22014-05-06 15:57:45 -0400356
Nicolas Capensf160b172014-11-26 11:58:23 -0500357 switch(target)
358 {
359 case GL_ANY_SAMPLES_PASSED_EXT:
360 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
361 break;
362 default:
363 return error(GL_INVALID_ENUM);
364 }
John Bauman66b8ab22014-05-06 15:57:45 -0400365
Nicolas Capens7cc75e12015-01-29 14:44:24 -0500366 if(name == 0)
Nicolas Capensf160b172014-11-26 11:58:23 -0500367 {
368 return error(GL_INVALID_OPERATION);
369 }
John Bauman66b8ab22014-05-06 15:57:45 -0400370
Nicolas Capensf160b172014-11-26 11:58:23 -0500371 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400372
Nicolas Capensf160b172014-11-26 11:58:23 -0500373 if(context)
374 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -0500375 context->beginQuery(target, name);
Nicolas Capensf160b172014-11-26 11:58:23 -0500376 }
John Bauman66b8ab22014-05-06 15:57:45 -0400377}
378
379void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
380{
Nicolas Capensf160b172014-11-26 11:58:23 -0500381 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
John Bauman66b8ab22014-05-06 15:57:45 -0400382
Nicolas Capensf160b172014-11-26 11:58:23 -0500383 if(index >= es2::MAX_VERTEX_ATTRIBS)
384 {
385 return error(GL_INVALID_VALUE);
386 }
John Bauman66b8ab22014-05-06 15:57:45 -0400387
Nicolas Capensf160b172014-11-26 11:58:23 -0500388 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400389
Nicolas Capensf160b172014-11-26 11:58:23 -0500390 if(context)
391 {
392 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -0400393
Nicolas Capensf160b172014-11-26 11:58:23 -0500394 if(!programObject)
395 {
396 if(context->getShader(program))
397 {
398 return error(GL_INVALID_OPERATION);
399 }
400 else
401 {
402 return error(GL_INVALID_VALUE);
403 }
404 }
John Bauman66b8ab22014-05-06 15:57:45 -0400405
Nicolas Capensf160b172014-11-26 11:58:23 -0500406 if(strncmp(name, "gl_", 3) == 0)
407 {
408 return error(GL_INVALID_OPERATION);
409 }
John Bauman66b8ab22014-05-06 15:57:45 -0400410
Nicolas Capensf160b172014-11-26 11:58:23 -0500411 programObject->bindAttributeLocation(index, name);
412 }
John Bauman66b8ab22014-05-06 15:57:45 -0400413}
414
415void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
416{
Nicolas Capensf160b172014-11-26 11:58:23 -0500417 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
John Bauman66b8ab22014-05-06 15:57:45 -0400418
Nicolas Capensf160b172014-11-26 11:58:23 -0500419 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400420
Nicolas Capensf160b172014-11-26 11:58:23 -0500421 if(context)
422 {
Alexis Hetuf9b7cb12015-04-10 13:44:36 -0400423 egl::GLint clientVersion = egl::getClientVersion();
424
Nicolas Capensf160b172014-11-26 11:58:23 -0500425 switch(target)
426 {
427 case GL_ARRAY_BUFFER:
428 context->bindArrayBuffer(buffer);
429 return;
430 case GL_ELEMENT_ARRAY_BUFFER:
431 context->bindElementArrayBuffer(buffer);
432 return;
Alexis Hetuf9b7cb12015-04-10 13:44:36 -0400433 case GL_COPY_READ_BUFFER:
434 if(clientVersion >= 3)
435 {
436 context->bindCopyReadBuffer(buffer);
437 return;
438 }
439 else return error(GL_INVALID_ENUM);
440 case GL_COPY_WRITE_BUFFER:
441 if(clientVersion >= 3)
442 {
443 context->bindCopyWriteBuffer(buffer);
444 return;
445 }
446 else return error(GL_INVALID_ENUM);
447 case GL_PIXEL_PACK_BUFFER:
448 if(clientVersion >= 3)
449 {
450 context->bindPixelPackBuffer(buffer);
451 return;
452 }
453 else return error(GL_INVALID_ENUM);
454 case GL_PIXEL_UNPACK_BUFFER:
455 if(clientVersion >= 3)
456 {
457 context->bindPixelUnpackBuffer(buffer);
458 return;
459 }
460 else return error(GL_INVALID_ENUM);
461 case GL_TRANSFORM_FEEDBACK_BUFFER:
462 if(clientVersion >= 3)
463 {
464 UNIMPLEMENTED();
465 return;
466 }
467 else return error(GL_INVALID_ENUM);
468 case GL_UNIFORM_BUFFER:
469 if(clientVersion >= 3)
470 {
471 context->bindUniformBuffer(buffer);
472 return;
473 }
474 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -0500475 default:
476 return error(GL_INVALID_ENUM);
477 }
478 }
John Bauman66b8ab22014-05-06 15:57:45 -0400479}
480
481void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
482{
Nicolas Capensf160b172014-11-26 11:58:23 -0500483 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
John Bauman66b8ab22014-05-06 15:57:45 -0400484
Nicolas Capensf160b172014-11-26 11:58:23 -0500485 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
486 {
487 return error(GL_INVALID_ENUM);
488 }
John Bauman66b8ab22014-05-06 15:57:45 -0400489
Nicolas Capensf160b172014-11-26 11:58:23 -0500490 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400491
Nicolas Capensf160b172014-11-26 11:58:23 -0500492 if(context)
493 {
494 if(target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
495 {
496 context->bindReadFramebuffer(framebuffer);
497 }
Nicolas Capens08e90f02014-11-21 12:49:12 -0500498
Nicolas Capensf160b172014-11-26 11:58:23 -0500499 if(target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
500 {
501 context->bindDrawFramebuffer(framebuffer);
502 }
503 }
John Bauman66b8ab22014-05-06 15:57:45 -0400504}
505
506void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
507{
Nicolas Capensf160b172014-11-26 11:58:23 -0500508 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
John Bauman66b8ab22014-05-06 15:57:45 -0400509
Nicolas Capensf160b172014-11-26 11:58:23 -0500510 if(target != GL_RENDERBUFFER)
511 {
512 return error(GL_INVALID_ENUM);
513 }
John Bauman66b8ab22014-05-06 15:57:45 -0400514
Nicolas Capensf160b172014-11-26 11:58:23 -0500515 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400516
Nicolas Capensf160b172014-11-26 11:58:23 -0500517 if(context)
518 {
519 if(renderbuffer != 0 && !context->getRenderbuffer(renderbuffer))
520 {
521 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
522 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
523 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
524 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
525 return error(GL_INVALID_OPERATION);
526 }
Alexis Hetu42a584d2014-11-07 14:23:33 -0500527
Nicolas Capensf160b172014-11-26 11:58:23 -0500528 context->bindRenderbuffer(renderbuffer);
529 }
John Bauman66b8ab22014-05-06 15:57:45 -0400530}
531
532void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
533{
Nicolas Capensf160b172014-11-26 11:58:23 -0500534 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
John Bauman66b8ab22014-05-06 15:57:45 -0400535
Nicolas Capensf160b172014-11-26 11:58:23 -0500536 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400537
Nicolas Capensf160b172014-11-26 11:58:23 -0500538 if(context)
539 {
540 es2::Texture *textureObject = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -0400541
Nicolas Capensf160b172014-11-26 11:58:23 -0500542 if(textureObject && textureObject->getTarget() != target && texture != 0)
543 {
544 return error(GL_INVALID_OPERATION);
545 }
John Bauman66b8ab22014-05-06 15:57:45 -0400546
Alexis Hetued306182015-04-02 12:02:28 -0400547 egl::GLint clientVersion = context->getClientVersion();
548
Nicolas Capensf160b172014-11-26 11:58:23 -0500549 switch(target)
550 {
551 case GL_TEXTURE_2D:
552 context->bindTexture2D(texture);
553 return;
554 case GL_TEXTURE_CUBE_MAP:
555 context->bindTextureCubeMap(texture);
556 return;
557 case GL_TEXTURE_EXTERNAL_OES:
558 context->bindTextureExternal(texture);
559 return;
Alexis Hetued306182015-04-02 12:02:28 -0400560 case GL_TEXTURE_2D_ARRAY:
561 if(clientVersion < 3)
562 {
563 return error(GL_INVALID_ENUM);
564 }
565 else
566 {
567 UNIMPLEMENTED();
568 context->bindTexture3D(texture);
569 break;
570 }
Alexis Hetub027aa92015-01-19 15:56:12 -0500571 case GL_TEXTURE_3D_OES:
572 context->bindTexture3D(texture);
573 return;
Nicolas Capensf160b172014-11-26 11:58:23 -0500574 default:
575 return error(GL_INVALID_ENUM);
576 }
577 }
John Bauman66b8ab22014-05-06 15:57:45 -0400578}
579
580void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
581{
Nicolas Capensf160b172014-11-26 11:58:23 -0500582 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
583 red, green, blue, alpha);
John Bauman66b8ab22014-05-06 15:57:45 -0400584
Nicolas Capensf160b172014-11-26 11:58:23 -0500585 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400586
Nicolas Capensf160b172014-11-26 11:58:23 -0500587 if(context)
588 {
589 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
590 }
John Bauman66b8ab22014-05-06 15:57:45 -0400591}
592
593void GL_APIENTRY glBlendEquation(GLenum mode)
594{
Nicolas Capensf160b172014-11-26 11:58:23 -0500595 glBlendEquationSeparate(mode, mode);
John Bauman66b8ab22014-05-06 15:57:45 -0400596}
597
598void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
599{
Nicolas Capensf160b172014-11-26 11:58:23 -0500600 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
John Bauman66b8ab22014-05-06 15:57:45 -0400601
Nicolas Capensf160b172014-11-26 11:58:23 -0500602 switch(modeRGB)
603 {
604 case GL_FUNC_ADD:
605 case GL_FUNC_SUBTRACT:
606 case GL_FUNC_REVERSE_SUBTRACT:
607 case GL_MIN_EXT:
608 case GL_MAX_EXT:
609 break;
610 default:
611 return error(GL_INVALID_ENUM);
612 }
John Bauman66b8ab22014-05-06 15:57:45 -0400613
Nicolas Capensf160b172014-11-26 11:58:23 -0500614 switch(modeAlpha)
615 {
616 case GL_FUNC_ADD:
617 case GL_FUNC_SUBTRACT:
618 case GL_FUNC_REVERSE_SUBTRACT:
619 case GL_MIN_EXT:
620 case GL_MAX_EXT:
621 break;
622 default:
623 return error(GL_INVALID_ENUM);
624 }
John Bauman66b8ab22014-05-06 15:57:45 -0400625
Nicolas Capensf160b172014-11-26 11:58:23 -0500626 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400627
Nicolas Capensf160b172014-11-26 11:58:23 -0500628 if(context)
629 {
630 context->setBlendEquation(modeRGB, modeAlpha);
631 }
John Bauman66b8ab22014-05-06 15:57:45 -0400632}
633
634void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
635{
Nicolas Capensf160b172014-11-26 11:58:23 -0500636 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
John Bauman66b8ab22014-05-06 15:57:45 -0400637}
638
639void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
640{
Nicolas Capensf160b172014-11-26 11:58:23 -0500641 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
642 srcRGB, dstRGB, srcAlpha, dstAlpha);
John Bauman66b8ab22014-05-06 15:57:45 -0400643
Nicolas Capensf160b172014-11-26 11:58:23 -0500644 switch(srcRGB)
645 {
646 case GL_ZERO:
647 case GL_ONE:
648 case GL_SRC_COLOR:
649 case GL_ONE_MINUS_SRC_COLOR:
650 case GL_DST_COLOR:
651 case GL_ONE_MINUS_DST_COLOR:
652 case GL_SRC_ALPHA:
653 case GL_ONE_MINUS_SRC_ALPHA:
654 case GL_DST_ALPHA:
655 case GL_ONE_MINUS_DST_ALPHA:
656 case GL_CONSTANT_COLOR:
657 case GL_ONE_MINUS_CONSTANT_COLOR:
658 case GL_CONSTANT_ALPHA:
659 case GL_ONE_MINUS_CONSTANT_ALPHA:
660 case GL_SRC_ALPHA_SATURATE:
661 break;
662 default:
663 return error(GL_INVALID_ENUM);
664 }
John Bauman66b8ab22014-05-06 15:57:45 -0400665
Nicolas Capensf160b172014-11-26 11:58:23 -0500666 switch(dstRGB)
667 {
668 case GL_ZERO:
669 case GL_ONE:
670 case GL_SRC_COLOR:
671 case GL_ONE_MINUS_SRC_COLOR:
672 case GL_DST_COLOR:
673 case GL_ONE_MINUS_DST_COLOR:
674 case GL_SRC_ALPHA:
675 case GL_ONE_MINUS_SRC_ALPHA:
676 case GL_DST_ALPHA:
677 case GL_ONE_MINUS_DST_ALPHA:
678 case GL_CONSTANT_COLOR:
679 case GL_ONE_MINUS_CONSTANT_COLOR:
680 case GL_CONSTANT_ALPHA:
681 case GL_ONE_MINUS_CONSTANT_ALPHA:
682 break;
683 default:
684 return error(GL_INVALID_ENUM);
685 }
John Bauman66b8ab22014-05-06 15:57:45 -0400686
Nicolas Capensf160b172014-11-26 11:58:23 -0500687 switch(srcAlpha)
688 {
689 case GL_ZERO:
690 case GL_ONE:
691 case GL_SRC_COLOR:
692 case GL_ONE_MINUS_SRC_COLOR:
693 case GL_DST_COLOR:
694 case GL_ONE_MINUS_DST_COLOR:
695 case GL_SRC_ALPHA:
696 case GL_ONE_MINUS_SRC_ALPHA:
697 case GL_DST_ALPHA:
698 case GL_ONE_MINUS_DST_ALPHA:
699 case GL_CONSTANT_COLOR:
700 case GL_ONE_MINUS_CONSTANT_COLOR:
701 case GL_CONSTANT_ALPHA:
702 case GL_ONE_MINUS_CONSTANT_ALPHA:
703 case GL_SRC_ALPHA_SATURATE:
704 break;
705 default:
706 return error(GL_INVALID_ENUM);
707 }
John Bauman66b8ab22014-05-06 15:57:45 -0400708
Nicolas Capensf160b172014-11-26 11:58:23 -0500709 switch(dstAlpha)
710 {
711 case GL_ZERO:
712 case GL_ONE:
713 case GL_SRC_COLOR:
714 case GL_ONE_MINUS_SRC_COLOR:
715 case GL_DST_COLOR:
716 case GL_ONE_MINUS_DST_COLOR:
717 case GL_SRC_ALPHA:
718 case GL_ONE_MINUS_SRC_ALPHA:
719 case GL_DST_ALPHA:
720 case GL_ONE_MINUS_DST_ALPHA:
721 case GL_CONSTANT_COLOR:
722 case GL_ONE_MINUS_CONSTANT_COLOR:
723 case GL_CONSTANT_ALPHA:
724 case GL_ONE_MINUS_CONSTANT_ALPHA:
725 break;
726 default:
727 return error(GL_INVALID_ENUM);
728 }
John Bauman66b8ab22014-05-06 15:57:45 -0400729
Nicolas Capensf160b172014-11-26 11:58:23 -0500730 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400731
Nicolas Capensf160b172014-11-26 11:58:23 -0500732 if(context)
733 {
734 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
735 }
John Bauman66b8ab22014-05-06 15:57:45 -0400736}
737
738void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
Nicolas Capens54b721d2014-12-12 12:50:04 -0500739{
740 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
Nicolas Capens4cadfe32014-12-10 22:26:26 -0500741
Nicolas Capensf160b172014-11-26 11:58:23 -0500742 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
743 target, size, data, usage);
John Bauman66b8ab22014-05-06 15:57:45 -0400744
Nicolas Capensf160b172014-11-26 11:58:23 -0500745 if(size < 0)
746 {
747 return error(GL_INVALID_VALUE);
748 }
John Bauman66b8ab22014-05-06 15:57:45 -0400749
Alexis Hetued306182015-04-02 12:02:28 -0400750 egl::GLint clientVersion = egl::getClientVersion();
751
Nicolas Capensf160b172014-11-26 11:58:23 -0500752 switch(usage)
753 {
754 case GL_STREAM_DRAW:
755 case GL_STATIC_DRAW:
756 case GL_DYNAMIC_DRAW:
757 break;
Alexis Hetued306182015-04-02 12:02:28 -0400758 case GL_STREAM_READ:
759 case GL_STREAM_COPY:
760 case GL_STATIC_READ:
761 case GL_STATIC_COPY:
762 case GL_DYNAMIC_READ:
763 case GL_DYNAMIC_COPY:
764 if(clientVersion < 3)
765 {
766 return error(GL_INVALID_ENUM);
767 }
768 break;
Nicolas Capensf160b172014-11-26 11:58:23 -0500769 default:
770 return error(GL_INVALID_ENUM);
771 }
John Bauman66b8ab22014-05-06 15:57:45 -0400772
Nicolas Capensf160b172014-11-26 11:58:23 -0500773 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400774
Nicolas Capensf160b172014-11-26 11:58:23 -0500775 if(context)
776 {
777 es2::Buffer *buffer;
Alexis Hetuf9b7cb12015-04-10 13:44:36 -0400778 if(!context->getBuffer(target, &buffer))
Nicolas Capensf160b172014-11-26 11:58:23 -0500779 {
Nicolas Capensf160b172014-11-26 11:58:23 -0500780 return error(GL_INVALID_ENUM);
781 }
John Bauman66b8ab22014-05-06 15:57:45 -0400782
Nicolas Capensf160b172014-11-26 11:58:23 -0500783 if(!buffer)
784 {
Alexis Hetued306182015-04-02 12:02:28 -0400785 // A null buffer means that "0" is bound to the requested buffer target
Nicolas Capensf160b172014-11-26 11:58:23 -0500786 return error(GL_INVALID_OPERATION);
787 }
John Bauman66b8ab22014-05-06 15:57:45 -0400788
Nicolas Capensf160b172014-11-26 11:58:23 -0500789 buffer->bufferData(data, size, usage);
790 }
John Bauman66b8ab22014-05-06 15:57:45 -0400791}
792
793void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
Nicolas Capens54b721d2014-12-12 12:50:04 -0500794{
795 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
796 offset = static_cast<GLint>(offset);
Nicolas Capens4cadfe32014-12-10 22:26:26 -0500797
Nicolas Capensf160b172014-11-26 11:58:23 -0500798 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
799 target, offset, size, data);
John Bauman66b8ab22014-05-06 15:57:45 -0400800
Nicolas Capensf160b172014-11-26 11:58:23 -0500801 if(size < 0 || offset < 0)
802 {
803 return error(GL_INVALID_VALUE);
804 }
John Bauman66b8ab22014-05-06 15:57:45 -0400805
Nicolas Capensf160b172014-11-26 11:58:23 -0500806 if(data == NULL)
807 {
808 return;
809 }
John Bauman66b8ab22014-05-06 15:57:45 -0400810
Nicolas Capensf160b172014-11-26 11:58:23 -0500811 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400812
Nicolas Capensf160b172014-11-26 11:58:23 -0500813 if(context)
814 {
815 es2::Buffer *buffer;
Alexis Hetuf9b7cb12015-04-10 13:44:36 -0400816 if(!context->getBuffer(target, &buffer))
Nicolas Capensf160b172014-11-26 11:58:23 -0500817 {
Nicolas Capensf160b172014-11-26 11:58:23 -0500818 return error(GL_INVALID_ENUM);
819 }
John Bauman66b8ab22014-05-06 15:57:45 -0400820
Nicolas Capensf160b172014-11-26 11:58:23 -0500821 if(!buffer)
822 {
Alexis Hetued306182015-04-02 12:02:28 -0400823 // A null buffer means that "0" is bound to the requested buffer target
Nicolas Capensf160b172014-11-26 11:58:23 -0500824 return error(GL_INVALID_OPERATION);
825 }
John Bauman66b8ab22014-05-06 15:57:45 -0400826
Nicolas Capensf160b172014-11-26 11:58:23 -0500827 if((size_t)size + offset > buffer->size())
John Bauman66b8ab22014-05-06 15:57:45 -0400828 {
829 return error(GL_INVALID_VALUE);
830 }
831
Nicolas Capensf160b172014-11-26 11:58:23 -0500832 buffer->bufferSubData(data, size, offset);
833 }
834}
John Bauman66b8ab22014-05-06 15:57:45 -0400835
Nicolas Capensf160b172014-11-26 11:58:23 -0500836GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
837{
838 TRACE("(GLenum target = 0x%X)", target);
839
840 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
841 {
842 return error(GL_INVALID_ENUM, 0);
843 }
844
845 es2::Context *context = es2::getContext();
846
847 if(context)
848 {
849 es2::Framebuffer *framebuffer = NULL;
850 if(target == GL_READ_FRAMEBUFFER_ANGLE)
851 {
852 framebuffer = context->getReadFramebuffer();
853 }
854 else
855 {
856 framebuffer = context->getDrawFramebuffer();
857 }
858
859 return framebuffer->completeness();
860 }
861
862 return 0;
863}
864
865void GL_APIENTRY glClear(GLbitfield mask)
866{
867 TRACE("(GLbitfield mask = %X)", mask);
868
869 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
870 {
871 return error(GL_INVALID_VALUE);
872 }
873
874 es2::Context *context = es2::getContext();
875
876 if(context)
877 {
878 context->clear(mask);
879 }
John Bauman66b8ab22014-05-06 15:57:45 -0400880}
881
882void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
883{
Nicolas Capensf160b172014-11-26 11:58:23 -0500884 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
885 red, green, blue, alpha);
John Bauman66b8ab22014-05-06 15:57:45 -0400886
Nicolas Capensf160b172014-11-26 11:58:23 -0500887 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400888
Nicolas Capensf160b172014-11-26 11:58:23 -0500889 if(context)
890 {
891 context->setClearColor(red, green, blue, alpha);
892 }
John Bauman66b8ab22014-05-06 15:57:45 -0400893}
894
895void GL_APIENTRY glClearDepthf(GLclampf depth)
896{
Nicolas Capensf160b172014-11-26 11:58:23 -0500897 TRACE("(GLclampf depth = %f)", depth);
John Bauman66b8ab22014-05-06 15:57:45 -0400898
Nicolas Capensf160b172014-11-26 11:58:23 -0500899 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400900
Nicolas Capensf160b172014-11-26 11:58:23 -0500901 if(context)
902 {
903 context->setClearDepth(depth);
904 }
John Bauman66b8ab22014-05-06 15:57:45 -0400905}
906
907void GL_APIENTRY glClearStencil(GLint s)
908{
Nicolas Capensf160b172014-11-26 11:58:23 -0500909 TRACE("(GLint s = %d)", s);
John Bauman66b8ab22014-05-06 15:57:45 -0400910
Nicolas Capensf160b172014-11-26 11:58:23 -0500911 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400912
Nicolas Capensf160b172014-11-26 11:58:23 -0500913 if(context)
914 {
915 context->setClearStencil(s);
916 }
John Bauman66b8ab22014-05-06 15:57:45 -0400917}
918
919void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
920{
Nicolas Capensf160b172014-11-26 11:58:23 -0500921 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
922 red, green, blue, alpha);
John Bauman66b8ab22014-05-06 15:57:45 -0400923
Nicolas Capensf160b172014-11-26 11:58:23 -0500924 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400925
Nicolas Capensf160b172014-11-26 11:58:23 -0500926 if(context)
927 {
928 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
929 }
John Bauman66b8ab22014-05-06 15:57:45 -0400930}
931
932void GL_APIENTRY glCompileShader(GLuint shader)
933{
Nicolas Capensf160b172014-11-26 11:58:23 -0500934 TRACE("(GLuint shader = %d)", shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400935
Nicolas Capensf160b172014-11-26 11:58:23 -0500936 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -0400937
Nicolas Capensf160b172014-11-26 11:58:23 -0500938 if(context)
939 {
940 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -0400941
Nicolas Capensf160b172014-11-26 11:58:23 -0500942 if(!shaderObject)
943 {
944 if(context->getProgram(shader))
945 {
946 return error(GL_INVALID_OPERATION);
947 }
948 else
949 {
950 return error(GL_INVALID_VALUE);
951 }
952 }
John Bauman66b8ab22014-05-06 15:57:45 -0400953
Nicolas Capensf160b172014-11-26 11:58:23 -0500954 shaderObject->compile();
955 }
John Bauman66b8ab22014-05-06 15:57:45 -0400956}
957
Nicolas Capens08e90f02014-11-21 12:49:12 -0500958void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
John Bauman66b8ab22014-05-06 15:57:45 -0400959 GLint border, GLsizei imageSize, const GLvoid* data)
960{
Nicolas Capensf160b172014-11-26 11:58:23 -0500961 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
962 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
963 target, level, internalformat, width, height, border, imageSize, data);
John Bauman66b8ab22014-05-06 15:57:45 -0400964
Nicolas Capensf160b172014-11-26 11:58:23 -0500965 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
966 {
967 return error(GL_INVALID_VALUE);
968 }
John Bauman66b8ab22014-05-06 15:57:45 -0400969
Alexis Hetued306182015-04-02 12:02:28 -0400970 egl::GLint clientVersion = egl::getClientVersion();
971
Nicolas Capensf160b172014-11-26 11:58:23 -0500972 switch(internalformat)
973 {
Nicolas Capens22658242014-11-29 00:31:41 -0500974 case GL_ETC1_RGB8_OES:
975 break;
Alexis Hetued306182015-04-02 12:02:28 -0400976 case GL_COMPRESSED_R11_EAC:
977 case GL_COMPRESSED_SIGNED_R11_EAC:
978 case GL_COMPRESSED_RG11_EAC:
979 case GL_COMPRESSED_SIGNED_RG11_EAC:
980 case GL_COMPRESSED_RGB8_ETC2:
981 case GL_COMPRESSED_SRGB8_ETC2:
982 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
983 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
984 case GL_COMPRESSED_RGBA8_ETC2_EAC:
985 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
986 if(clientVersion >= 3)
987 {
988 break;
989 }
990 return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -0500991 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
992 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
993 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
994 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
995 if(!S3TC_SUPPORT)
996 {
997 return error(GL_INVALID_ENUM);
998 }
999 break;
1000 case GL_DEPTH_COMPONENT:
1001 case GL_DEPTH_COMPONENT16:
1002 case GL_DEPTH_COMPONENT32_OES:
1003 case GL_DEPTH_STENCIL_OES:
1004 case GL_DEPTH24_STENCIL8_OES:
1005 return error(GL_INVALID_OPERATION);
1006 default:
1007 return error(GL_INVALID_ENUM);
1008 }
John Bauman66b8ab22014-05-06 15:57:45 -04001009
Nicolas Capensf160b172014-11-26 11:58:23 -05001010 if(border != 0)
1011 {
1012 return error(GL_INVALID_VALUE);
1013 }
John Bauman66b8ab22014-05-06 15:57:45 -04001014
Nicolas Capensf160b172014-11-26 11:58:23 -05001015 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001016
Nicolas Capensf160b172014-11-26 11:58:23 -05001017 if(context)
1018 {
Alexis Hetub027aa92015-01-19 15:56:12 -05001019 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Nicolas Capensf160b172014-11-26 11:58:23 -05001020 {
1021 return error(GL_INVALID_VALUE);
1022 }
John Bauman66b8ab22014-05-06 15:57:45 -04001023
Nicolas Capensf160b172014-11-26 11:58:23 -05001024 switch(target)
1025 {
1026 case GL_TEXTURE_2D:
1027 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
1028 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
1029 {
1030 return error(GL_INVALID_VALUE);
1031 }
1032 break;
1033 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1034 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1035 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1036 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1037 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1038 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1039 if(width != height)
1040 {
1041 return error(GL_INVALID_VALUE);
1042 }
John Bauman66b8ab22014-05-06 15:57:45 -04001043
Nicolas Capensf160b172014-11-26 11:58:23 -05001044 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
1045 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
1046 {
1047 return error(GL_INVALID_VALUE);
1048 }
1049 break;
1050 default:
1051 return error(GL_INVALID_ENUM);
1052 }
John Bauman66b8ab22014-05-06 15:57:45 -04001053
Nicolas Capensf160b172014-11-26 11:58:23 -05001054 if(imageSize != es2::ComputeCompressedSize(width, height, internalformat))
1055 {
1056 return error(GL_INVALID_VALUE);
1057 }
John Bauman66b8ab22014-05-06 15:57:45 -04001058
Nicolas Capensf160b172014-11-26 11:58:23 -05001059 if(target == GL_TEXTURE_2D)
1060 {
1061 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04001062
Nicolas Capensf160b172014-11-26 11:58:23 -05001063 if(!texture)
1064 {
1065 return error(GL_INVALID_OPERATION);
1066 }
John Bauman66b8ab22014-05-06 15:57:45 -04001067
Nicolas Capensf160b172014-11-26 11:58:23 -05001068 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
1069 }
1070 else
1071 {
1072 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04001073
Nicolas Capensf160b172014-11-26 11:58:23 -05001074 if(!texture)
1075 {
1076 return error(GL_INVALID_OPERATION);
1077 }
John Bauman66b8ab22014-05-06 15:57:45 -04001078
Nicolas Capensf160b172014-11-26 11:58:23 -05001079 switch(target)
1080 {
1081 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1082 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1083 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1084 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1085 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1086 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1087 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
1088 break;
1089 default: UNREACHABLE();
1090 }
1091 }
1092 }
John Bauman66b8ab22014-05-06 15:57:45 -04001093}
1094
1095void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Nicolas Capensf160b172014-11-26 11:58:23 -05001096 GLenum format, GLsizei imageSize, const GLvoid* data)
John Bauman66b8ab22014-05-06 15:57:45 -04001097{
Nicolas Capensf160b172014-11-26 11:58:23 -05001098 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1099 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
1100 "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
1101 target, level, xoffset, yoffset, width, height, format, imageSize, data);
John Bauman66b8ab22014-05-06 15:57:45 -04001102
Nicolas Capensf160b172014-11-26 11:58:23 -05001103 if(!es2::IsTextureTarget(target))
1104 {
1105 return error(GL_INVALID_ENUM);
1106 }
John Bauman66b8ab22014-05-06 15:57:45 -04001107
Nicolas Capensf160b172014-11-26 11:58:23 -05001108 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
1109 {
1110 return error(GL_INVALID_VALUE);
1111 }
John Bauman66b8ab22014-05-06 15:57:45 -04001112
Alexis Hetued306182015-04-02 12:02:28 -04001113 egl::GLint clientVersion = egl::getClientVersion();
1114
Nicolas Capensf160b172014-11-26 11:58:23 -05001115 switch(format)
1116 {
Nicolas Capens22658242014-11-29 00:31:41 -05001117 case GL_ETC1_RGB8_OES:
1118 break;
Alexis Hetued306182015-04-02 12:02:28 -04001119 case GL_COMPRESSED_R11_EAC:
1120 case GL_COMPRESSED_SIGNED_R11_EAC:
1121 case GL_COMPRESSED_RG11_EAC:
1122 case GL_COMPRESSED_SIGNED_RG11_EAC:
1123 case GL_COMPRESSED_RGB8_ETC2:
1124 case GL_COMPRESSED_SRGB8_ETC2:
1125 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1126 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
1127 case GL_COMPRESSED_RGBA8_ETC2_EAC:
1128 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
1129 if(clientVersion >= 3)
1130 {
1131 break;
1132 }
1133 return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05001134 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1135 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1136 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1137 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1138 if(!S3TC_SUPPORT)
1139 {
1140 return error(GL_INVALID_ENUM);
1141 }
1142 break;
1143 default:
1144 return error(GL_INVALID_ENUM);
1145 }
John Bauman66b8ab22014-05-06 15:57:45 -04001146
Nicolas Capensf160b172014-11-26 11:58:23 -05001147 if(width == 0 || height == 0 || data == NULL)
1148 {
1149 return;
1150 }
John Bauman66b8ab22014-05-06 15:57:45 -04001151
Nicolas Capensf160b172014-11-26 11:58:23 -05001152 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001153
Nicolas Capensf160b172014-11-26 11:58:23 -05001154 if(context)
1155 {
Alexis Hetub027aa92015-01-19 15:56:12 -05001156 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Nicolas Capensf160b172014-11-26 11:58:23 -05001157 {
1158 return error(GL_INVALID_VALUE);
1159 }
John Bauman66b8ab22014-05-06 15:57:45 -04001160
Nicolas Capensf160b172014-11-26 11:58:23 -05001161 if(imageSize != es2::ComputeCompressedSize(width, height, format))
1162 {
1163 return error(GL_INVALID_VALUE);
1164 }
John Bauman66b8ab22014-05-06 15:57:45 -04001165
Nicolas Capensf160b172014-11-26 11:58:23 -05001166 if(xoffset % 4 != 0 || yoffset % 4 != 0)
1167 {
1168 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
1169 return error(GL_INVALID_OPERATION);
1170 }
John Bauman66b8ab22014-05-06 15:57:45 -04001171
Nicolas Capensf160b172014-11-26 11:58:23 -05001172 if(target == GL_TEXTURE_2D)
1173 {
1174 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04001175
Nicolas Capensf160b172014-11-26 11:58:23 -05001176 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
1177 {
1178 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
1179 }
1180 }
1181 else if(es2::IsCubemapTextureTarget(target))
1182 {
1183 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04001184
Nicolas Capensf160b172014-11-26 11:58:23 -05001185 if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture))
1186 {
1187 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
1188 }
1189 }
1190 else
1191 {
1192 UNREACHABLE();
1193 }
1194 }
John Bauman66b8ab22014-05-06 15:57:45 -04001195}
1196
1197void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
1198{
Nicolas Capensf160b172014-11-26 11:58:23 -05001199 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
1200 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
1201 target, level, internalformat, x, y, width, height, border);
John Bauman66b8ab22014-05-06 15:57:45 -04001202
Nicolas Capensf160b172014-11-26 11:58:23 -05001203 if(!validImageSize(level, width, height))
1204 {
1205 return error(GL_INVALID_VALUE);
1206 }
John Bauman66b8ab22014-05-06 15:57:45 -04001207
Nicolas Capensf160b172014-11-26 11:58:23 -05001208 if(border != 0)
1209 {
1210 return error(GL_INVALID_VALUE);
1211 }
John Bauman66b8ab22014-05-06 15:57:45 -04001212
Nicolas Capensf160b172014-11-26 11:58:23 -05001213 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001214
Nicolas Capensf160b172014-11-26 11:58:23 -05001215 if(context)
1216 {
1217 switch(target)
1218 {
1219 case GL_TEXTURE_2D:
1220 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
1221 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
1222 {
1223 return error(GL_INVALID_VALUE);
1224 }
1225 break;
1226 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1227 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1228 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1229 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1230 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1231 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1232 if(width != height)
1233 {
1234 return error(GL_INVALID_VALUE);
1235 }
John Bauman66b8ab22014-05-06 15:57:45 -04001236
Nicolas Capensf160b172014-11-26 11:58:23 -05001237 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
1238 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
1239 {
1240 return error(GL_INVALID_VALUE);
1241 }
1242 break;
1243 default:
1244 return error(GL_INVALID_ENUM);
1245 }
John Bauman66b8ab22014-05-06 15:57:45 -04001246
Nicolas Capensf160b172014-11-26 11:58:23 -05001247 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001248
Nicolas Capensf160b172014-11-26 11:58:23 -05001249 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1250 {
1251 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1252 }
John Bauman66b8ab22014-05-06 15:57:45 -04001253
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001254 if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
Nicolas Capensf160b172014-11-26 11:58:23 -05001255 {
1256 return error(GL_INVALID_OPERATION);
1257 }
John Bauman66b8ab22014-05-06 15:57:45 -04001258
Nicolas Capensf160b172014-11-26 11:58:23 -05001259 es2::Renderbuffer *source = framebuffer->getColorbuffer();
1260 GLenum colorbufferFormat = source->getFormat();
John Bauman66b8ab22014-05-06 15:57:45 -04001261
Alexis Hetub027aa92015-01-19 15:56:12 -05001262 if(!validateColorBufferFormat(internalformat, colorbufferFormat))
Nicolas Capensf160b172014-11-26 11:58:23 -05001263 {
Alexis Hetub027aa92015-01-19 15:56:12 -05001264 return;
Nicolas Capensf160b172014-11-26 11:58:23 -05001265 }
John Bauman66b8ab22014-05-06 15:57:45 -04001266
Nicolas Capensf160b172014-11-26 11:58:23 -05001267 if(target == GL_TEXTURE_2D)
1268 {
1269 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04001270
Nicolas Capensf160b172014-11-26 11:58:23 -05001271 if(!texture)
1272 {
1273 return error(GL_INVALID_OPERATION);
1274 }
John Bauman66b8ab22014-05-06 15:57:45 -04001275
Nicolas Capensf160b172014-11-26 11:58:23 -05001276 texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
1277 }
1278 else if(es2::IsCubemapTextureTarget(target))
1279 {
1280 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04001281
Nicolas Capensf160b172014-11-26 11:58:23 -05001282 if(!texture)
1283 {
1284 return error(GL_INVALID_OPERATION);
1285 }
John Bauman66b8ab22014-05-06 15:57:45 -04001286
Nicolas Capensf160b172014-11-26 11:58:23 -05001287 texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
1288 }
1289 else UNREACHABLE();
1290 }
John Bauman66b8ab22014-05-06 15:57:45 -04001291}
1292
1293void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1294{
Nicolas Capensf160b172014-11-26 11:58:23 -05001295 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1296 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1297 target, level, xoffset, yoffset, x, y, width, height);
John Bauman66b8ab22014-05-06 15:57:45 -04001298
Nicolas Capensf160b172014-11-26 11:58:23 -05001299 if(!es2::IsTextureTarget(target))
1300 {
1301 return error(GL_INVALID_ENUM);
1302 }
John Bauman66b8ab22014-05-06 15:57:45 -04001303
Nicolas Capensf160b172014-11-26 11:58:23 -05001304 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1305 {
1306 return error(GL_INVALID_VALUE);
1307 }
John Bauman66b8ab22014-05-06 15:57:45 -04001308
Nicolas Capensf160b172014-11-26 11:58:23 -05001309 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1310 {
1311 return error(GL_INVALID_VALUE);
1312 }
John Bauman66b8ab22014-05-06 15:57:45 -04001313
Nicolas Capensf160b172014-11-26 11:58:23 -05001314 if(width == 0 || height == 0)
1315 {
1316 return;
1317 }
John Bauman66b8ab22014-05-06 15:57:45 -04001318
Nicolas Capensf160b172014-11-26 11:58:23 -05001319 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001320
Nicolas Capensf160b172014-11-26 11:58:23 -05001321 if(context)
1322 {
Alexis Hetub027aa92015-01-19 15:56:12 -05001323 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Nicolas Capensf160b172014-11-26 11:58:23 -05001324 {
1325 return error(GL_INVALID_VALUE);
1326 }
John Bauman66b8ab22014-05-06 15:57:45 -04001327
Nicolas Capensf160b172014-11-26 11:58:23 -05001328 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
John Bauman66b8ab22014-05-06 15:57:45 -04001329
Nicolas Capensf160b172014-11-26 11:58:23 -05001330 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1331 {
1332 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1333 }
John Bauman66b8ab22014-05-06 15:57:45 -04001334
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001335 if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
Nicolas Capensf160b172014-11-26 11:58:23 -05001336 {
1337 return error(GL_INVALID_OPERATION);
1338 }
John Bauman66b8ab22014-05-06 15:57:45 -04001339
Nicolas Capensf160b172014-11-26 11:58:23 -05001340 es2::Renderbuffer *source = framebuffer->getColorbuffer();
1341 GLenum colorbufferFormat = source->getFormat();
1342 es2::Texture *texture = NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04001343
Nicolas Capensf160b172014-11-26 11:58:23 -05001344 if(target == GL_TEXTURE_2D)
1345 {
1346 texture = context->getTexture2D();
1347 }
1348 else if(es2::IsCubemapTextureTarget(target))
1349 {
1350 texture = context->getTextureCubeMap();
1351 }
1352 else UNREACHABLE();
John Bauman66b8ab22014-05-06 15:57:45 -04001353
Nicolas Capensf160b172014-11-26 11:58:23 -05001354 if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture))
1355 {
1356 return;
1357 }
1358
1359 GLenum textureFormat = texture->getFormat(target, level);
1360
Alexis Hetub027aa92015-01-19 15:56:12 -05001361 if(!validateColorBufferFormat(textureFormat, colorbufferFormat))
Nicolas Capensf160b172014-11-26 11:58:23 -05001362 {
Alexis Hetub027aa92015-01-19 15:56:12 -05001363 return;
Nicolas Capensf160b172014-11-26 11:58:23 -05001364 }
John Bauman66b8ab22014-05-06 15:57:45 -04001365
Alexis Hetub027aa92015-01-19 15:56:12 -05001366 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
Nicolas Capensf160b172014-11-26 11:58:23 -05001367 }
John Bauman66b8ab22014-05-06 15:57:45 -04001368}
1369
1370GLuint GL_APIENTRY glCreateProgram(void)
1371{
Nicolas Capensf160b172014-11-26 11:58:23 -05001372 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04001373
Nicolas Capensf160b172014-11-26 11:58:23 -05001374 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001375
Nicolas Capensf160b172014-11-26 11:58:23 -05001376 if(context)
1377 {
1378 return context->createProgram();
1379 }
John Bauman66b8ab22014-05-06 15:57:45 -04001380
Nicolas Capensf160b172014-11-26 11:58:23 -05001381 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001382}
1383
1384GLuint GL_APIENTRY glCreateShader(GLenum type)
1385{
Nicolas Capensf160b172014-11-26 11:58:23 -05001386 TRACE("(GLenum type = 0x%X)", type);
John Bauman66b8ab22014-05-06 15:57:45 -04001387
Nicolas Capensf160b172014-11-26 11:58:23 -05001388 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001389
Nicolas Capensf160b172014-11-26 11:58:23 -05001390 if(context)
1391 {
1392 switch(type)
1393 {
1394 case GL_FRAGMENT_SHADER:
1395 case GL_VERTEX_SHADER:
1396 return context->createShader(type);
1397 default:
1398 return error(GL_INVALID_ENUM, 0);
1399 }
1400 }
John Bauman66b8ab22014-05-06 15:57:45 -04001401
Nicolas Capensf160b172014-11-26 11:58:23 -05001402 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001403}
1404
1405void GL_APIENTRY glCullFace(GLenum mode)
1406{
Nicolas Capensf160b172014-11-26 11:58:23 -05001407 TRACE("(GLenum mode = 0x%X)", mode);
John Bauman66b8ab22014-05-06 15:57:45 -04001408
Nicolas Capensf160b172014-11-26 11:58:23 -05001409 switch(mode)
1410 {
1411 case GL_FRONT:
1412 case GL_BACK:
1413 case GL_FRONT_AND_BACK:
1414 {
1415 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001416
Nicolas Capensf160b172014-11-26 11:58:23 -05001417 if(context)
1418 {
1419 context->setCullMode(mode);
1420 }
1421 }
1422 break;
1423 default:
1424 return error(GL_INVALID_ENUM);
1425 }
John Bauman66b8ab22014-05-06 15:57:45 -04001426}
1427
1428void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
1429{
Nicolas Capensf160b172014-11-26 11:58:23 -05001430 TRACE("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
John Bauman66b8ab22014-05-06 15:57:45 -04001431
Nicolas Capensf160b172014-11-26 11:58:23 -05001432 if(n < 0)
1433 {
1434 return error(GL_INVALID_VALUE);
1435 }
John Bauman66b8ab22014-05-06 15:57:45 -04001436
Nicolas Capensf160b172014-11-26 11:58:23 -05001437 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001438
Nicolas Capensf160b172014-11-26 11:58:23 -05001439 if(context)
1440 {
1441 for(int i = 0; i < n; i++)
1442 {
1443 context->deleteBuffer(buffers[i]);
1444 }
1445 }
John Bauman66b8ab22014-05-06 15:57:45 -04001446}
1447
1448void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
1449{
Nicolas Capensf160b172014-11-26 11:58:23 -05001450 TRACE("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
John Bauman66b8ab22014-05-06 15:57:45 -04001451
Nicolas Capensf160b172014-11-26 11:58:23 -05001452 if(n < 0)
1453 {
1454 return error(GL_INVALID_VALUE);
1455 }
John Bauman66b8ab22014-05-06 15:57:45 -04001456
Nicolas Capensf160b172014-11-26 11:58:23 -05001457 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001458
Nicolas Capensf160b172014-11-26 11:58:23 -05001459 if(context)
1460 {
1461 for(int i = 0; i < n; i++)
1462 {
1463 context->deleteFence(fences[i]);
1464 }
1465 }
John Bauman66b8ab22014-05-06 15:57:45 -04001466}
1467
1468void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1469{
Nicolas Capensf160b172014-11-26 11:58:23 -05001470 TRACE("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
John Bauman66b8ab22014-05-06 15:57:45 -04001471
Nicolas Capensf160b172014-11-26 11:58:23 -05001472 if(n < 0)
1473 {
1474 return error(GL_INVALID_VALUE);
1475 }
John Bauman66b8ab22014-05-06 15:57:45 -04001476
Nicolas Capensf160b172014-11-26 11:58:23 -05001477 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001478
Nicolas Capensf160b172014-11-26 11:58:23 -05001479 if(context)
1480 {
1481 for(int i = 0; i < n; i++)
1482 {
1483 if(framebuffers[i] != 0)
1484 {
1485 context->deleteFramebuffer(framebuffers[i]);
1486 }
1487 }
1488 }
John Bauman66b8ab22014-05-06 15:57:45 -04001489}
1490
1491void GL_APIENTRY glDeleteProgram(GLuint program)
1492{
Nicolas Capensf160b172014-11-26 11:58:23 -05001493 TRACE("(GLuint program = %d)", program);
John Bauman66b8ab22014-05-06 15:57:45 -04001494
Nicolas Capensf160b172014-11-26 11:58:23 -05001495 if(program == 0)
1496 {
1497 return;
1498 }
John Bauman66b8ab22014-05-06 15:57:45 -04001499
Nicolas Capensf160b172014-11-26 11:58:23 -05001500 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001501
Nicolas Capensf160b172014-11-26 11:58:23 -05001502 if(context)
1503 {
1504 if(!context->getProgram(program))
1505 {
1506 if(context->getShader(program))
1507 {
1508 return error(GL_INVALID_OPERATION);
1509 }
1510 else
1511 {
1512 return error(GL_INVALID_VALUE);
1513 }
1514 }
John Bauman66b8ab22014-05-06 15:57:45 -04001515
Nicolas Capensf160b172014-11-26 11:58:23 -05001516 context->deleteProgram(program);
1517 }
John Bauman66b8ab22014-05-06 15:57:45 -04001518}
1519
1520void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
1521{
Nicolas Capensf160b172014-11-26 11:58:23 -05001522 TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
John Bauman66b8ab22014-05-06 15:57:45 -04001523
Nicolas Capensf160b172014-11-26 11:58:23 -05001524 if(n < 0)
1525 {
1526 return error(GL_INVALID_VALUE);
1527 }
John Bauman66b8ab22014-05-06 15:57:45 -04001528
Nicolas Capensf160b172014-11-26 11:58:23 -05001529 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001530
Nicolas Capensf160b172014-11-26 11:58:23 -05001531 if(context)
1532 {
1533 for(int i = 0; i < n; i++)
1534 {
1535 context->deleteQuery(ids[i]);
1536 }
1537 }
John Bauman66b8ab22014-05-06 15:57:45 -04001538}
1539
1540void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1541{
Nicolas Capensf160b172014-11-26 11:58:23 -05001542 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
John Bauman66b8ab22014-05-06 15:57:45 -04001543
Nicolas Capensf160b172014-11-26 11:58:23 -05001544 if(n < 0)
1545 {
1546 return error(GL_INVALID_VALUE);
1547 }
John Bauman66b8ab22014-05-06 15:57:45 -04001548
Nicolas Capensf160b172014-11-26 11:58:23 -05001549 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001550
Nicolas Capensf160b172014-11-26 11:58:23 -05001551 if(context)
1552 {
1553 for(int i = 0; i < n; i++)
1554 {
1555 context->deleteRenderbuffer(renderbuffers[i]);
1556 }
1557 }
John Bauman66b8ab22014-05-06 15:57:45 -04001558}
1559
1560void GL_APIENTRY glDeleteShader(GLuint shader)
1561{
Nicolas Capensf160b172014-11-26 11:58:23 -05001562 TRACE("(GLuint shader = %d)", shader);
John Bauman66b8ab22014-05-06 15:57:45 -04001563
Nicolas Capensf160b172014-11-26 11:58:23 -05001564 if(shader == 0)
1565 {
1566 return;
1567 }
John Bauman66b8ab22014-05-06 15:57:45 -04001568
Nicolas Capensf160b172014-11-26 11:58:23 -05001569 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001570
Nicolas Capensf160b172014-11-26 11:58:23 -05001571 if(context)
1572 {
1573 if(!context->getShader(shader))
1574 {
1575 if(context->getProgram(shader))
1576 {
1577 return error(GL_INVALID_OPERATION);
1578 }
1579 else
1580 {
1581 return error(GL_INVALID_VALUE);
1582 }
1583 }
John Bauman66b8ab22014-05-06 15:57:45 -04001584
Nicolas Capensf160b172014-11-26 11:58:23 -05001585 context->deleteShader(shader);
1586 }
John Bauman66b8ab22014-05-06 15:57:45 -04001587}
1588
1589void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
1590{
Nicolas Capensf160b172014-11-26 11:58:23 -05001591 TRACE("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
John Bauman66b8ab22014-05-06 15:57:45 -04001592
Nicolas Capensf160b172014-11-26 11:58:23 -05001593 if(n < 0)
1594 {
1595 return error(GL_INVALID_VALUE);
1596 }
John Bauman66b8ab22014-05-06 15:57:45 -04001597
Nicolas Capensf160b172014-11-26 11:58:23 -05001598 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001599
Nicolas Capensf160b172014-11-26 11:58:23 -05001600 if(context)
1601 {
1602 for(int i = 0; i < n; i++)
1603 {
1604 if(textures[i] != 0)
1605 {
1606 context->deleteTexture(textures[i]);
1607 }
1608 }
1609 }
John Bauman66b8ab22014-05-06 15:57:45 -04001610}
1611
1612void GL_APIENTRY glDepthFunc(GLenum func)
1613{
Nicolas Capensf160b172014-11-26 11:58:23 -05001614 TRACE("(GLenum func = 0x%X)", func);
John Bauman66b8ab22014-05-06 15:57:45 -04001615
Nicolas Capensf160b172014-11-26 11:58:23 -05001616 switch(func)
1617 {
1618 case GL_NEVER:
1619 case GL_ALWAYS:
1620 case GL_LESS:
1621 case GL_LEQUAL:
1622 case GL_EQUAL:
1623 case GL_GREATER:
1624 case GL_GEQUAL:
1625 case GL_NOTEQUAL:
1626 break;
1627 default:
1628 return error(GL_INVALID_ENUM);
1629 }
John Bauman66b8ab22014-05-06 15:57:45 -04001630
Nicolas Capensf160b172014-11-26 11:58:23 -05001631 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001632
Nicolas Capensf160b172014-11-26 11:58:23 -05001633 if(context)
1634 {
1635 context->setDepthFunc(func);
1636 }
John Bauman66b8ab22014-05-06 15:57:45 -04001637}
1638
1639void GL_APIENTRY glDepthMask(GLboolean flag)
1640{
Nicolas Capensf160b172014-11-26 11:58:23 -05001641 TRACE("(GLboolean flag = %d)", flag);
John Bauman66b8ab22014-05-06 15:57:45 -04001642
Nicolas Capensf160b172014-11-26 11:58:23 -05001643 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001644
Nicolas Capensf160b172014-11-26 11:58:23 -05001645 if(context)
1646 {
1647 context->setDepthMask(flag != GL_FALSE);
1648 }
John Bauman66b8ab22014-05-06 15:57:45 -04001649}
1650
1651void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)
1652{
Nicolas Capensf160b172014-11-26 11:58:23 -05001653 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
John Bauman66b8ab22014-05-06 15:57:45 -04001654
Nicolas Capensf160b172014-11-26 11:58:23 -05001655 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001656
Nicolas Capensf160b172014-11-26 11:58:23 -05001657 if(context)
1658 {
1659 context->setDepthRange(zNear, zFar);
1660 }
John Bauman66b8ab22014-05-06 15:57:45 -04001661}
1662
1663void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
1664{
Nicolas Capensf160b172014-11-26 11:58:23 -05001665 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
John Bauman66b8ab22014-05-06 15:57:45 -04001666
Nicolas Capensf160b172014-11-26 11:58:23 -05001667 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001668
Nicolas Capensf160b172014-11-26 11:58:23 -05001669 if(context)
1670 {
John Bauman66b8ab22014-05-06 15:57:45 -04001671
Nicolas Capensf160b172014-11-26 11:58:23 -05001672 es2::Program *programObject = context->getProgram(program);
1673 es2::Shader *shaderObject = context->getShader(shader);
Nicolas Capens08e90f02014-11-21 12:49:12 -05001674
Nicolas Capensf160b172014-11-26 11:58:23 -05001675 if(!programObject)
1676 {
1677 es2::Shader *shaderByProgramHandle;
1678 shaderByProgramHandle = context->getShader(program);
1679 if(!shaderByProgramHandle)
1680 {
1681 return error(GL_INVALID_VALUE);
1682 }
1683 else
1684 {
1685 return error(GL_INVALID_OPERATION);
1686 }
1687 }
John Bauman66b8ab22014-05-06 15:57:45 -04001688
Nicolas Capensf160b172014-11-26 11:58:23 -05001689 if(!shaderObject)
1690 {
1691 es2::Program *programByShaderHandle = context->getProgram(shader);
1692 if(!programByShaderHandle)
1693 {
1694 return error(GL_INVALID_VALUE);
1695 }
1696 else
1697 {
1698 return error(GL_INVALID_OPERATION);
1699 }
1700 }
John Bauman66b8ab22014-05-06 15:57:45 -04001701
Nicolas Capensf160b172014-11-26 11:58:23 -05001702 if(!programObject->detachShader(shaderObject))
1703 {
1704 return error(GL_INVALID_OPERATION);
1705 }
1706 }
John Bauman66b8ab22014-05-06 15:57:45 -04001707}
1708
1709void GL_APIENTRY glDisable(GLenum cap)
1710{
Nicolas Capensf160b172014-11-26 11:58:23 -05001711 TRACE("(GLenum cap = 0x%X)", cap);
John Bauman66b8ab22014-05-06 15:57:45 -04001712
Nicolas Capensf160b172014-11-26 11:58:23 -05001713 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001714
Nicolas Capensf160b172014-11-26 11:58:23 -05001715 if(context)
1716 {
1717 switch(cap)
1718 {
1719 case GL_CULL_FACE: context->setCullFace(false); break;
1720 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break;
1721 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break;
1722 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break;
1723 case GL_SCISSOR_TEST: context->setScissorTest(false); break;
1724 case GL_STENCIL_TEST: context->setStencilTest(false); break;
1725 case GL_DEPTH_TEST: context->setDepthTest(false); break;
1726 case GL_BLEND: context->setBlend(false); break;
1727 case GL_DITHER: context->setDither(false); break;
Alexis Hetufceb1832015-03-10 16:42:04 -04001728 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndex(false); break;
1729 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscard(false); break;
Nicolas Capensf160b172014-11-26 11:58:23 -05001730 default:
1731 return error(GL_INVALID_ENUM);
1732 }
1733 }
John Bauman66b8ab22014-05-06 15:57:45 -04001734}
1735
1736void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
1737{
Nicolas Capensf160b172014-11-26 11:58:23 -05001738 TRACE("(GLuint index = %d)", index);
John Bauman66b8ab22014-05-06 15:57:45 -04001739
Nicolas Capensf160b172014-11-26 11:58:23 -05001740 if(index >= es2::MAX_VERTEX_ATTRIBS)
1741 {
1742 return error(GL_INVALID_VALUE);
1743 }
John Bauman66b8ab22014-05-06 15:57:45 -04001744
Nicolas Capensf160b172014-11-26 11:58:23 -05001745 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001746
Nicolas Capensf160b172014-11-26 11:58:23 -05001747 if(context)
1748 {
1749 context->setEnableVertexAttribArray(index, false);
1750 }
John Bauman66b8ab22014-05-06 15:57:45 -04001751}
1752
1753void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
1754{
Nicolas Capensf160b172014-11-26 11:58:23 -05001755 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
John Bauman66b8ab22014-05-06 15:57:45 -04001756
Alexis Hetued306182015-04-02 12:02:28 -04001757 switch(mode)
1758 {
1759 case GL_POINTS:
1760 case GL_LINES:
1761 case GL_LINE_LOOP:
1762 case GL_LINE_STRIP:
1763 case GL_TRIANGLES:
1764 case GL_TRIANGLE_FAN:
1765 case GL_TRIANGLE_STRIP:
1766 break;
1767 default:
1768 return error(GL_INVALID_ENUM);
1769 }
1770
Nicolas Capensf160b172014-11-26 11:58:23 -05001771 if(count < 0 || first < 0)
1772 {
1773 return error(GL_INVALID_VALUE);
1774 }
John Bauman66b8ab22014-05-06 15:57:45 -04001775
Nicolas Capensf160b172014-11-26 11:58:23 -05001776 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001777
Nicolas Capensf160b172014-11-26 11:58:23 -05001778 if(context)
1779 {
1780 context->drawArrays(mode, first, count);
1781 }
John Bauman66b8ab22014-05-06 15:57:45 -04001782}
1783
1784void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1785{
Nicolas Capensf160b172014-11-26 11:58:23 -05001786 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
1787 mode, count, type, indices);
John Bauman66b8ab22014-05-06 15:57:45 -04001788
Alexis Hetued306182015-04-02 12:02:28 -04001789 switch(mode)
1790 {
1791 case GL_POINTS:
1792 case GL_LINES:
1793 case GL_LINE_LOOP:
1794 case GL_LINE_STRIP:
1795 case GL_TRIANGLES:
1796 case GL_TRIANGLE_FAN:
1797 case GL_TRIANGLE_STRIP:
1798 break;
1799 default:
1800 return error(GL_INVALID_ENUM);
1801 }
1802
Nicolas Capensf160b172014-11-26 11:58:23 -05001803 if(count < 0)
1804 {
1805 return error(GL_INVALID_VALUE);
1806 }
John Bauman66b8ab22014-05-06 15:57:45 -04001807
Nicolas Capensf160b172014-11-26 11:58:23 -05001808 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001809
Nicolas Capensf160b172014-11-26 11:58:23 -05001810 if(context)
1811 {
1812 switch(type)
1813 {
1814 case GL_UNSIGNED_BYTE:
1815 case GL_UNSIGNED_SHORT:
1816 case GL_UNSIGNED_INT:
1817 break;
1818 default:
1819 return error(GL_INVALID_ENUM);
1820 }
Nicolas Capens08e90f02014-11-21 12:49:12 -05001821
Alexis Hetu07334692015-04-10 14:51:27 -04001822 context->drawElements(mode, 0, UINT_MAX, count, type, indices);
Nicolas Capensf160b172014-11-26 11:58:23 -05001823 }
John Bauman66b8ab22014-05-06 15:57:45 -04001824}
1825
1826void GL_APIENTRY glEnable(GLenum cap)
1827{
Nicolas Capensf160b172014-11-26 11:58:23 -05001828 TRACE("(GLenum cap = 0x%X)", cap);
John Bauman66b8ab22014-05-06 15:57:45 -04001829
Nicolas Capensf160b172014-11-26 11:58:23 -05001830 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001831
Nicolas Capensf160b172014-11-26 11:58:23 -05001832 if(context)
1833 {
1834 switch(cap)
1835 {
1836 case GL_CULL_FACE: context->setCullFace(true); break;
1837 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break;
1838 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break;
1839 case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break;
1840 case GL_SCISSOR_TEST: context->setScissorTest(true); break;
1841 case GL_STENCIL_TEST: context->setStencilTest(true); break;
1842 case GL_DEPTH_TEST: context->setDepthTest(true); break;
1843 case GL_BLEND: context->setBlend(true); break;
1844 case GL_DITHER: context->setDither(true); break;
Alexis Hetufceb1832015-03-10 16:42:04 -04001845 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndex(true); break;
1846 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscard(true); break;
Nicolas Capensf160b172014-11-26 11:58:23 -05001847 default:
1848 return error(GL_INVALID_ENUM);
1849 }
1850 }
John Bauman66b8ab22014-05-06 15:57:45 -04001851}
1852
1853void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
1854{
Nicolas Capensf160b172014-11-26 11:58:23 -05001855 TRACE("(GLuint index = %d)", index);
John Bauman66b8ab22014-05-06 15:57:45 -04001856
Nicolas Capensf160b172014-11-26 11:58:23 -05001857 if(index >= es2::MAX_VERTEX_ATTRIBS)
1858 {
1859 return error(GL_INVALID_VALUE);
1860 }
John Bauman66b8ab22014-05-06 15:57:45 -04001861
Nicolas Capensf160b172014-11-26 11:58:23 -05001862 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001863
Nicolas Capensf160b172014-11-26 11:58:23 -05001864 if(context)
1865 {
1866 context->setEnableVertexAttribArray(index, true);
1867 }
John Bauman66b8ab22014-05-06 15:57:45 -04001868}
1869
1870void GL_APIENTRY glEndQueryEXT(GLenum target)
1871{
Nicolas Capensf160b172014-11-26 11:58:23 -05001872 TRACE("GLenum target = 0x%X)", target);
John Bauman66b8ab22014-05-06 15:57:45 -04001873
Nicolas Capensf160b172014-11-26 11:58:23 -05001874 switch(target)
1875 {
1876 case GL_ANY_SAMPLES_PASSED_EXT:
1877 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1878 break;
1879 default:
1880 return error(GL_INVALID_ENUM);
1881 }
John Bauman66b8ab22014-05-06 15:57:45 -04001882
Nicolas Capensf160b172014-11-26 11:58:23 -05001883 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001884
Nicolas Capensf160b172014-11-26 11:58:23 -05001885 if(context)
1886 {
1887 context->endQuery(target);
1888 }
John Bauman66b8ab22014-05-06 15:57:45 -04001889}
1890
1891void GL_APIENTRY glFinishFenceNV(GLuint fence)
1892{
Nicolas Capensf160b172014-11-26 11:58:23 -05001893 TRACE("(GLuint fence = %d)", fence);
John Bauman66b8ab22014-05-06 15:57:45 -04001894
Nicolas Capensf160b172014-11-26 11:58:23 -05001895 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001896
Nicolas Capensf160b172014-11-26 11:58:23 -05001897 if(context)
1898 {
1899 es2::Fence* fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04001900
Nicolas Capensf160b172014-11-26 11:58:23 -05001901 if(fenceObject == NULL)
1902 {
1903 return error(GL_INVALID_OPERATION);
1904 }
John Bauman66b8ab22014-05-06 15:57:45 -04001905
Nicolas Capensf160b172014-11-26 11:58:23 -05001906 fenceObject->finishFence();
1907 }
John Bauman66b8ab22014-05-06 15:57:45 -04001908}
1909
1910void GL_APIENTRY glFinish(void)
1911{
Nicolas Capensf160b172014-11-26 11:58:23 -05001912 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04001913
Nicolas Capensf160b172014-11-26 11:58:23 -05001914 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001915
Nicolas Capensf160b172014-11-26 11:58:23 -05001916 if(context)
1917 {
1918 context->finish();
1919 }
John Bauman66b8ab22014-05-06 15:57:45 -04001920}
1921
1922void GL_APIENTRY glFlush(void)
1923{
Nicolas Capensf160b172014-11-26 11:58:23 -05001924 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04001925
Nicolas Capensf160b172014-11-26 11:58:23 -05001926 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001927
Nicolas Capensf160b172014-11-26 11:58:23 -05001928 if(context)
1929 {
1930 context->flush();
1931 }
John Bauman66b8ab22014-05-06 15:57:45 -04001932}
1933
1934void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1935{
Nicolas Capensf160b172014-11-26 11:58:23 -05001936 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1937 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04001938
Nicolas Capensf160b172014-11-26 11:58:23 -05001939 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) ||
1940 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1941 {
1942 return error(GL_INVALID_ENUM);
1943 }
John Bauman66b8ab22014-05-06 15:57:45 -04001944
Nicolas Capensf160b172014-11-26 11:58:23 -05001945 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04001946
Nicolas Capensf160b172014-11-26 11:58:23 -05001947 if(context)
1948 {
1949 es2::Framebuffer *framebuffer = NULL;
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001950 GLuint framebufferName = 0;
Nicolas Capensf160b172014-11-26 11:58:23 -05001951 if(target == GL_READ_FRAMEBUFFER_ANGLE)
1952 {
1953 framebuffer = context->getReadFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001954 framebufferName = context->getReadFramebufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05001955 }
1956 else
1957 {
1958 framebuffer = context->getDrawFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001959 framebufferName = context->getDrawFramebufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05001960 }
John Bauman66b8ab22014-05-06 15:57:45 -04001961
Nicolas Capens7cc75e12015-01-29 14:44:24 -05001962 if(!framebuffer || (framebufferName == 0 && renderbuffer != 0))
Nicolas Capensf160b172014-11-26 11:58:23 -05001963 {
1964 return error(GL_INVALID_OPERATION);
1965 }
John Bauman66b8ab22014-05-06 15:57:45 -04001966
Nicolas Capensf160b172014-11-26 11:58:23 -05001967 switch(attachment)
1968 {
1969 case GL_COLOR_ATTACHMENT0:
1970 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer);
1971 break;
1972 case GL_DEPTH_ATTACHMENT:
1973 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1974 break;
1975 case GL_STENCIL_ATTACHMENT:
1976 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1977 break;
1978 default:
1979 return error(GL_INVALID_ENUM);
1980 }
1981 }
John Bauman66b8ab22014-05-06 15:57:45 -04001982}
1983
1984void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1985{
Nicolas Capensf160b172014-11-26 11:58:23 -05001986 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1987 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
John Bauman66b8ab22014-05-06 15:57:45 -04001988
Nicolas Capensf160b172014-11-26 11:58:23 -05001989 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
1990 {
1991 return error(GL_INVALID_ENUM);
1992 }
John Bauman66b8ab22014-05-06 15:57:45 -04001993
Nicolas Capensf160b172014-11-26 11:58:23 -05001994 switch(attachment)
1995 {
1996 case GL_COLOR_ATTACHMENT0:
1997 case GL_DEPTH_ATTACHMENT:
1998 case GL_STENCIL_ATTACHMENT:
1999 break;
2000 default:
2001 return error(GL_INVALID_ENUM);
2002 }
John Bauman66b8ab22014-05-06 15:57:45 -04002003
Nicolas Capensf160b172014-11-26 11:58:23 -05002004 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002005
Nicolas Capensf160b172014-11-26 11:58:23 -05002006 if(context)
2007 {
2008 if(texture == 0)
2009 {
2010 textarget = GL_NONE;
2011 }
2012 else
2013 {
2014 es2::Texture *tex = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -04002015
Nicolas Capensf160b172014-11-26 11:58:23 -05002016 if(tex == NULL)
2017 {
2018 return error(GL_INVALID_OPERATION);
2019 }
John Bauman66b8ab22014-05-06 15:57:45 -04002020
Nicolas Capensf160b172014-11-26 11:58:23 -05002021 if(tex->isCompressed(textarget, level))
2022 {
2023 return error(GL_INVALID_OPERATION);
2024 }
John Bauman66b8ab22014-05-06 15:57:45 -04002025
Nicolas Capensf160b172014-11-26 11:58:23 -05002026 switch(textarget)
2027 {
2028 case GL_TEXTURE_2D:
2029 if(tex->getTarget() != GL_TEXTURE_2D)
2030 {
2031 return error(GL_INVALID_OPERATION);
2032 }
2033 break;
2034 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2035 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2036 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2037 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2038 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2039 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2040 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2041 {
2042 return error(GL_INVALID_OPERATION);
2043 }
2044 break;
2045 default:
2046 return error(GL_INVALID_ENUM);
2047 }
John Bauman66b8ab22014-05-06 15:57:45 -04002048
Nicolas Capensf160b172014-11-26 11:58:23 -05002049 if(level != 0)
2050 {
2051 return error(GL_INVALID_VALUE);
2052 }
2053 }
John Bauman66b8ab22014-05-06 15:57:45 -04002054
Nicolas Capensf160b172014-11-26 11:58:23 -05002055 es2::Framebuffer *framebuffer = NULL;
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002056 GLuint framebufferName = 0;
Nicolas Capensf160b172014-11-26 11:58:23 -05002057 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2058 {
2059 framebuffer = context->getReadFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002060 framebufferName = context->getReadFramebufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05002061 }
2062 else
2063 {
2064 framebuffer = context->getDrawFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002065 framebufferName = context->getDrawFramebufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05002066 }
John Bauman66b8ab22014-05-06 15:57:45 -04002067
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002068 if(framebufferName == 0 || !framebuffer)
Nicolas Capensf160b172014-11-26 11:58:23 -05002069 {
2070 return error(GL_INVALID_OPERATION);
2071 }
John Bauman66b8ab22014-05-06 15:57:45 -04002072
Nicolas Capensf160b172014-11-26 11:58:23 -05002073 switch(attachment)
2074 {
2075 case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break;
2076 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
2077 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
2078 }
2079 }
John Bauman66b8ab22014-05-06 15:57:45 -04002080}
2081
2082void GL_APIENTRY glFrontFace(GLenum mode)
2083{
Nicolas Capensf160b172014-11-26 11:58:23 -05002084 TRACE("(GLenum mode = 0x%X)", mode);
John Bauman66b8ab22014-05-06 15:57:45 -04002085
Nicolas Capensf160b172014-11-26 11:58:23 -05002086 switch(mode)
2087 {
2088 case GL_CW:
2089 case GL_CCW:
2090 {
2091 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002092
Nicolas Capensf160b172014-11-26 11:58:23 -05002093 if(context)
2094 {
2095 context->setFrontFace(mode);
2096 }
2097 }
2098 break;
2099 default:
2100 return error(GL_INVALID_ENUM);
2101 }
John Bauman66b8ab22014-05-06 15:57:45 -04002102}
2103
2104void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
2105{
Nicolas Capensf160b172014-11-26 11:58:23 -05002106 TRACE("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
John Bauman66b8ab22014-05-06 15:57:45 -04002107
Nicolas Capensf160b172014-11-26 11:58:23 -05002108 if(n < 0)
2109 {
2110 return error(GL_INVALID_VALUE);
2111 }
John Bauman66b8ab22014-05-06 15:57:45 -04002112
Nicolas Capensf160b172014-11-26 11:58:23 -05002113 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002114
Nicolas Capensf160b172014-11-26 11:58:23 -05002115 if(context)
2116 {
2117 for(int i = 0; i < n; i++)
2118 {
2119 buffers[i] = context->createBuffer();
2120 }
2121 }
John Bauman66b8ab22014-05-06 15:57:45 -04002122}
2123
2124void GL_APIENTRY glGenerateMipmap(GLenum target)
2125{
Nicolas Capensf160b172014-11-26 11:58:23 -05002126 TRACE("(GLenum target = 0x%X)", target);
John Bauman66b8ab22014-05-06 15:57:45 -04002127
Nicolas Capensf160b172014-11-26 11:58:23 -05002128 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002129
Nicolas Capensf160b172014-11-26 11:58:23 -05002130 if(context)
2131 {
Alexis Hetued306182015-04-02 12:02:28 -04002132 es2::Texture *texture = nullptr;
2133
2134 egl::GLint clientVersion = context->getClientVersion();
John Bauman66b8ab22014-05-06 15:57:45 -04002135
Nicolas Capensf160b172014-11-26 11:58:23 -05002136 switch(target)
2137 {
2138 case GL_TEXTURE_2D:
2139 texture = context->getTexture2D();
2140 break;
2141 case GL_TEXTURE_CUBE_MAP:
2142 texture = context->getTextureCubeMap();
2143 break;
Alexis Hetued306182015-04-02 12:02:28 -04002144 case GL_TEXTURE_2D_ARRAY:
2145 if(clientVersion < 3)
2146 {
2147 return error(GL_INVALID_ENUM);
2148 }
2149 else
2150 {
2151 UNIMPLEMENTED();
2152 texture = context->getTexture3D();
2153 break;
2154 }
2155 case GL_TEXTURE_3D_OES:
2156 texture = context->getTexture3D();
2157 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05002158 default:
2159 return error(GL_INVALID_ENUM);
2160 }
John Bauman66b8ab22014-05-06 15:57:45 -04002161
Nicolas Capensf160b172014-11-26 11:58:23 -05002162 if(texture->isCompressed(target, 0) || texture->isDepth(target, 0))
2163 {
2164 return error(GL_INVALID_OPERATION);
2165 }
John Bauman66b8ab22014-05-06 15:57:45 -04002166
Nicolas Capensf160b172014-11-26 11:58:23 -05002167 texture->generateMipmaps();
2168 }
John Bauman66b8ab22014-05-06 15:57:45 -04002169}
2170
2171void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
2172{
Nicolas Capensf160b172014-11-26 11:58:23 -05002173 TRACE("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
John Bauman66b8ab22014-05-06 15:57:45 -04002174
Nicolas Capensf160b172014-11-26 11:58:23 -05002175 if(n < 0)
2176 {
2177 return error(GL_INVALID_VALUE);
2178 }
John Bauman66b8ab22014-05-06 15:57:45 -04002179
Nicolas Capensf160b172014-11-26 11:58:23 -05002180 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002181
Nicolas Capensf160b172014-11-26 11:58:23 -05002182 if(context)
2183 {
2184 for(int i = 0; i < n; i++)
2185 {
2186 fences[i] = context->createFence();
2187 }
2188 }
John Bauman66b8ab22014-05-06 15:57:45 -04002189}
2190
2191void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
2192{
Nicolas Capensf160b172014-11-26 11:58:23 -05002193 TRACE("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
John Bauman66b8ab22014-05-06 15:57:45 -04002194
Nicolas Capensf160b172014-11-26 11:58:23 -05002195 if(n < 0)
2196 {
2197 return error(GL_INVALID_VALUE);
2198 }
John Bauman66b8ab22014-05-06 15:57:45 -04002199
Nicolas Capensf160b172014-11-26 11:58:23 -05002200 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002201
Nicolas Capensf160b172014-11-26 11:58:23 -05002202 if(context)
2203 {
2204 for(int i = 0; i < n; i++)
2205 {
2206 framebuffers[i] = context->createFramebuffer();
2207 }
2208 }
John Bauman66b8ab22014-05-06 15:57:45 -04002209}
2210
2211void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)
2212{
Nicolas Capensf160b172014-11-26 11:58:23 -05002213 TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
John Bauman66b8ab22014-05-06 15:57:45 -04002214
Nicolas Capensf160b172014-11-26 11:58:23 -05002215 if(n < 0)
2216 {
2217 return error(GL_INVALID_VALUE);
2218 }
John Bauman66b8ab22014-05-06 15:57:45 -04002219
Nicolas Capensf160b172014-11-26 11:58:23 -05002220 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002221
Nicolas Capensf160b172014-11-26 11:58:23 -05002222 if(context)
2223 {
2224 for(int i = 0; i < n; i++)
2225 {
2226 ids[i] = context->createQuery();
2227 }
2228 }
John Bauman66b8ab22014-05-06 15:57:45 -04002229}
2230
2231void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2232{
Nicolas Capensf160b172014-11-26 11:58:23 -05002233 TRACE("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
John Bauman66b8ab22014-05-06 15:57:45 -04002234
Nicolas Capensf160b172014-11-26 11:58:23 -05002235 if(n < 0)
2236 {
2237 return error(GL_INVALID_VALUE);
2238 }
John Bauman66b8ab22014-05-06 15:57:45 -04002239
Nicolas Capensf160b172014-11-26 11:58:23 -05002240 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002241
Nicolas Capensf160b172014-11-26 11:58:23 -05002242 if(context)
2243 {
2244 for(int i = 0; i < n; i++)
2245 {
2246 renderbuffers[i] = context->createRenderbuffer();
2247 }
2248 }
John Bauman66b8ab22014-05-06 15:57:45 -04002249}
2250
2251void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
2252{
Nicolas Capensf160b172014-11-26 11:58:23 -05002253 TRACE("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
John Bauman66b8ab22014-05-06 15:57:45 -04002254
Nicolas Capensf160b172014-11-26 11:58:23 -05002255 if(n < 0)
2256 {
2257 return error(GL_INVALID_VALUE);
2258 }
John Bauman66b8ab22014-05-06 15:57:45 -04002259
Nicolas Capensf160b172014-11-26 11:58:23 -05002260 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002261
Nicolas Capensf160b172014-11-26 11:58:23 -05002262 if(context)
2263 {
2264 for(int i = 0; i < n; i++)
2265 {
2266 textures[i] = context->createTexture();
2267 }
2268 }
John Bauman66b8ab22014-05-06 15:57:45 -04002269}
2270
2271void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2272{
Nicolas Capensf160b172014-11-26 11:58:23 -05002273 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
2274 "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
2275 program, index, bufsize, length, size, type, name);
John Bauman66b8ab22014-05-06 15:57:45 -04002276
Nicolas Capensf160b172014-11-26 11:58:23 -05002277 if(bufsize < 0)
2278 {
2279 return error(GL_INVALID_VALUE);
2280 }
John Bauman66b8ab22014-05-06 15:57:45 -04002281
Nicolas Capensf160b172014-11-26 11:58:23 -05002282 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002283
Nicolas Capensf160b172014-11-26 11:58:23 -05002284 if(context)
2285 {
2286 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002287
Nicolas Capensf160b172014-11-26 11:58:23 -05002288 if(!programObject)
2289 {
2290 if(context->getShader(program))
2291 {
2292 return error(GL_INVALID_OPERATION);
2293 }
2294 else
2295 {
2296 return error(GL_INVALID_VALUE);
2297 }
2298 }
John Bauman66b8ab22014-05-06 15:57:45 -04002299
Nicolas Capensf160b172014-11-26 11:58:23 -05002300 if(index >= (GLuint)programObject->getActiveAttributeCount())
2301 {
2302 return error(GL_INVALID_VALUE);
2303 }
John Bauman66b8ab22014-05-06 15:57:45 -04002304
Nicolas Capensf160b172014-11-26 11:58:23 -05002305 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2306 }
John Bauman66b8ab22014-05-06 15:57:45 -04002307}
2308
2309void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2310{
Nicolas Capensf160b172014-11-26 11:58:23 -05002311 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2312 "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = %s)",
2313 program, index, bufsize, length, size, type, name);
John Bauman66b8ab22014-05-06 15:57:45 -04002314
Nicolas Capensf160b172014-11-26 11:58:23 -05002315 if(bufsize < 0)
2316 {
2317 return error(GL_INVALID_VALUE);
2318 }
John Bauman66b8ab22014-05-06 15:57:45 -04002319
Nicolas Capensf160b172014-11-26 11:58:23 -05002320 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002321
Nicolas Capensf160b172014-11-26 11:58:23 -05002322 if(context)
2323 {
2324 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002325
Nicolas Capensf160b172014-11-26 11:58:23 -05002326 if(!programObject)
2327 {
2328 if(context->getShader(program))
2329 {
2330 return error(GL_INVALID_OPERATION);
2331 }
2332 else
2333 {
2334 return error(GL_INVALID_VALUE);
2335 }
2336 }
John Bauman66b8ab22014-05-06 15:57:45 -04002337
Nicolas Capensf160b172014-11-26 11:58:23 -05002338 if(index >= (GLuint)programObject->getActiveUniformCount())
2339 {
2340 return error(GL_INVALID_VALUE);
2341 }
John Bauman66b8ab22014-05-06 15:57:45 -04002342
Nicolas Capensf160b172014-11-26 11:58:23 -05002343 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2344 }
John Bauman66b8ab22014-05-06 15:57:45 -04002345}
2346
2347void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2348{
Nicolas Capensf160b172014-11-26 11:58:23 -05002349 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
2350 program, maxcount, count, shaders);
John Bauman66b8ab22014-05-06 15:57:45 -04002351
Nicolas Capensf160b172014-11-26 11:58:23 -05002352 if(maxcount < 0)
2353 {
2354 return error(GL_INVALID_VALUE);
2355 }
John Bauman66b8ab22014-05-06 15:57:45 -04002356
Nicolas Capensf160b172014-11-26 11:58:23 -05002357 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002358
Nicolas Capensf160b172014-11-26 11:58:23 -05002359 if(context)
2360 {
2361 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002362
Nicolas Capensf160b172014-11-26 11:58:23 -05002363 if(!programObject)
2364 {
2365 if(context->getShader(program))
2366 {
2367 return error(GL_INVALID_OPERATION);
2368 }
2369 else
2370 {
2371 return error(GL_INVALID_VALUE);
2372 }
2373 }
John Bauman66b8ab22014-05-06 15:57:45 -04002374
Nicolas Capensf160b172014-11-26 11:58:23 -05002375 return programObject->getAttachedShaders(maxcount, count, shaders);
2376 }
John Bauman66b8ab22014-05-06 15:57:45 -04002377}
2378
2379int GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
2380{
Nicolas Capensf160b172014-11-26 11:58:23 -05002381 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
John Bauman66b8ab22014-05-06 15:57:45 -04002382
Nicolas Capensf160b172014-11-26 11:58:23 -05002383 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002384
Nicolas Capensf160b172014-11-26 11:58:23 -05002385 if(context)
2386 {
John Bauman66b8ab22014-05-06 15:57:45 -04002387
Nicolas Capensf160b172014-11-26 11:58:23 -05002388 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002389
Nicolas Capensf160b172014-11-26 11:58:23 -05002390 if(!programObject)
2391 {
2392 if(context->getShader(program))
2393 {
2394 return error(GL_INVALID_OPERATION, -1);
2395 }
2396 else
2397 {
2398 return error(GL_INVALID_VALUE, -1);
2399 }
2400 }
John Bauman66b8ab22014-05-06 15:57:45 -04002401
Nicolas Capensf160b172014-11-26 11:58:23 -05002402 if(!programObject->isLinked())
2403 {
2404 return error(GL_INVALID_OPERATION, -1);
2405 }
John Bauman66b8ab22014-05-06 15:57:45 -04002406
Nicolas Capensf160b172014-11-26 11:58:23 -05002407 return programObject->getAttributeLocation(name);
2408 }
John Bauman66b8ab22014-05-06 15:57:45 -04002409
Nicolas Capensf160b172014-11-26 11:58:23 -05002410 return -1;
John Bauman66b8ab22014-05-06 15:57:45 -04002411}
2412
2413void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
2414{
Nicolas Capensf160b172014-11-26 11:58:23 -05002415 TRACE("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002416
Nicolas Capensf160b172014-11-26 11:58:23 -05002417 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002418
Nicolas Capensf160b172014-11-26 11:58:23 -05002419 if(context)
2420 {
2421 if(!(context->getBooleanv(pname, params)))
2422 {
2423 GLenum nativeType;
2424 unsigned int numParams = 0;
2425 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2426 return error(GL_INVALID_ENUM);
John Bauman66b8ab22014-05-06 15:57:45 -04002427
Nicolas Capensf160b172014-11-26 11:58:23 -05002428 if(numParams == 0)
2429 return; // it is known that the pname is valid, but there are no parameters to return
John Bauman66b8ab22014-05-06 15:57:45 -04002430
Nicolas Capensf160b172014-11-26 11:58:23 -05002431 if(nativeType == GL_FLOAT)
2432 {
2433 GLfloat *floatParams = NULL;
2434 floatParams = new GLfloat[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002435
Nicolas Capensf160b172014-11-26 11:58:23 -05002436 context->getFloatv(pname, floatParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002437
Nicolas Capensf160b172014-11-26 11:58:23 -05002438 for(unsigned int i = 0; i < numParams; ++i)
2439 {
2440 if(floatParams[i] == 0.0f)
2441 params[i] = GL_FALSE;
2442 else
2443 params[i] = GL_TRUE;
2444 }
John Bauman66b8ab22014-05-06 15:57:45 -04002445
Nicolas Capensf160b172014-11-26 11:58:23 -05002446 delete [] floatParams;
2447 }
2448 else if(nativeType == GL_INT)
2449 {
2450 GLint *intParams = NULL;
2451 intParams = new GLint[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002452
Nicolas Capensf160b172014-11-26 11:58:23 -05002453 context->getIntegerv(pname, intParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002454
Nicolas Capensf160b172014-11-26 11:58:23 -05002455 for(unsigned int i = 0; i < numParams; ++i)
2456 {
2457 if(intParams[i] == 0)
2458 params[i] = GL_FALSE;
2459 else
2460 params[i] = GL_TRUE;
2461 }
John Bauman66b8ab22014-05-06 15:57:45 -04002462
Nicolas Capensf160b172014-11-26 11:58:23 -05002463 delete [] intParams;
2464 }
2465 }
2466 }
John Bauman66b8ab22014-05-06 15:57:45 -04002467}
2468
2469void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2470{
Nicolas Capensf160b172014-11-26 11:58:23 -05002471 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002472
Nicolas Capensf160b172014-11-26 11:58:23 -05002473 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002474
Nicolas Capensf160b172014-11-26 11:58:23 -05002475 if(context)
2476 {
2477 es2::Buffer *buffer;
Alexis Hetuf9b7cb12015-04-10 13:44:36 -04002478 if(!context->getBuffer(target, &buffer))
Nicolas Capensf160b172014-11-26 11:58:23 -05002479 {
Nicolas Capensf160b172014-11-26 11:58:23 -05002480 return error(GL_INVALID_ENUM);
2481 }
John Bauman66b8ab22014-05-06 15:57:45 -04002482
Nicolas Capensf160b172014-11-26 11:58:23 -05002483 if(!buffer)
2484 {
2485 // A null buffer means that "0" is bound to the requested buffer target
2486 return error(GL_INVALID_OPERATION);
2487 }
John Bauman66b8ab22014-05-06 15:57:45 -04002488
Alexis Hetued306182015-04-02 12:02:28 -04002489 egl::GLint clientVersion = context->getClientVersion();
2490
Nicolas Capensf160b172014-11-26 11:58:23 -05002491 switch(pname)
2492 {
2493 case GL_BUFFER_USAGE:
2494 *params = buffer->usage();
2495 break;
2496 case GL_BUFFER_SIZE:
2497 *params = buffer->size();
2498 break;
Alexis Hetued306182015-04-02 12:02:28 -04002499 case GL_BUFFER_ACCESS_FLAGS:
2500 if(clientVersion >= 3)
2501 {
2502 *params = buffer->access();
2503 break;
2504 }
2505 else return error(GL_INVALID_ENUM);
2506 case GL_BUFFER_MAPPED:
2507 if(clientVersion >= 3)
2508 {
2509 *params = buffer->isMapped();
2510 break;
2511 }
2512 else return error(GL_INVALID_ENUM);
2513 case GL_BUFFER_MAP_LENGTH:
2514 if(clientVersion >= 3)
2515 {
2516 *params = buffer->length();
2517 break;
2518 }
2519 else return error(GL_INVALID_ENUM);
2520 case GL_BUFFER_MAP_OFFSET:
2521 if(clientVersion >= 3)
2522 {
2523 *params = buffer->offset();
2524 break;
2525 }
2526 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05002527 default:
2528 return error(GL_INVALID_ENUM);
2529 }
2530 }
John Bauman66b8ab22014-05-06 15:57:45 -04002531}
2532
2533GLenum GL_APIENTRY glGetError(void)
2534{
Nicolas Capensf160b172014-11-26 11:58:23 -05002535 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04002536
Nicolas Capensf160b172014-11-26 11:58:23 -05002537 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002538
Nicolas Capensf160b172014-11-26 11:58:23 -05002539 if(context)
2540 {
2541 return context->getError();
2542 }
John Bauman66b8ab22014-05-06 15:57:45 -04002543
Nicolas Capensf160b172014-11-26 11:58:23 -05002544 return GL_NO_ERROR;
John Bauman66b8ab22014-05-06 15:57:45 -04002545}
2546
2547void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2548{
Nicolas Capensf160b172014-11-26 11:58:23 -05002549 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002550
Nicolas Capensf160b172014-11-26 11:58:23 -05002551 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002552
Nicolas Capensf160b172014-11-26 11:58:23 -05002553 if(context)
2554 {
2555 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04002556
Nicolas Capensf160b172014-11-26 11:58:23 -05002557 if(fenceObject == NULL)
2558 {
2559 return error(GL_INVALID_OPERATION);
2560 }
John Bauman66b8ab22014-05-06 15:57:45 -04002561
Nicolas Capensf160b172014-11-26 11:58:23 -05002562 fenceObject->getFenceiv(pname, params);
2563 }
John Bauman66b8ab22014-05-06 15:57:45 -04002564}
2565
2566void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
2567{
Nicolas Capensf160b172014-11-26 11:58:23 -05002568 TRACE("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002569
Nicolas Capensf160b172014-11-26 11:58:23 -05002570 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002571
Nicolas Capensf160b172014-11-26 11:58:23 -05002572 if(context)
2573 {
2574 if(!(context->getFloatv(pname, params)))
2575 {
2576 GLenum nativeType;
2577 unsigned int numParams = 0;
2578 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2579 return error(GL_INVALID_ENUM);
John Bauman66b8ab22014-05-06 15:57:45 -04002580
Nicolas Capensf160b172014-11-26 11:58:23 -05002581 if(numParams == 0)
2582 return; // it is known that the pname is valid, but that there are no parameters to return.
John Bauman66b8ab22014-05-06 15:57:45 -04002583
Nicolas Capensf160b172014-11-26 11:58:23 -05002584 if(nativeType == GL_BOOL)
2585 {
2586 GLboolean *boolParams = NULL;
2587 boolParams = new GLboolean[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002588
Nicolas Capensf160b172014-11-26 11:58:23 -05002589 context->getBooleanv(pname, boolParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002590
Nicolas Capensf160b172014-11-26 11:58:23 -05002591 for(unsigned int i = 0; i < numParams; ++i)
2592 {
2593 if(boolParams[i] == GL_FALSE)
2594 params[i] = 0.0f;
2595 else
2596 params[i] = 1.0f;
2597 }
John Bauman66b8ab22014-05-06 15:57:45 -04002598
Nicolas Capensf160b172014-11-26 11:58:23 -05002599 delete [] boolParams;
2600 }
2601 else if(nativeType == GL_INT)
2602 {
2603 GLint *intParams = NULL;
2604 intParams = new GLint[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002605
Nicolas Capensf160b172014-11-26 11:58:23 -05002606 context->getIntegerv(pname, intParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002607
Nicolas Capensf160b172014-11-26 11:58:23 -05002608 for(unsigned int i = 0; i < numParams; ++i)
2609 {
2610 params[i] = (GLfloat)intParams[i];
2611 }
John Bauman66b8ab22014-05-06 15:57:45 -04002612
Nicolas Capensf160b172014-11-26 11:58:23 -05002613 delete [] intParams;
2614 }
2615 }
2616 }
John Bauman66b8ab22014-05-06 15:57:45 -04002617}
2618
2619void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2620{
Nicolas Capensf160b172014-11-26 11:58:23 -05002621 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
2622 target, attachment, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002623
Nicolas Capensf160b172014-11-26 11:58:23 -05002624 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002625
Nicolas Capensf160b172014-11-26 11:58:23 -05002626 if(context)
2627 {
2628 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
2629 {
2630 return error(GL_INVALID_ENUM);
2631 }
John Bauman66b8ab22014-05-06 15:57:45 -04002632
Nicolas Capensf160b172014-11-26 11:58:23 -05002633 es2::Framebuffer *framebuffer = NULL;
2634 if(target == GL_READ_FRAMEBUFFER_ANGLE)
2635 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002636 if(context->getReadFramebufferName() == 0)
Nicolas Capensf160b172014-11-26 11:58:23 -05002637 {
2638 return error(GL_INVALID_OPERATION);
2639 }
John Bauman66b8ab22014-05-06 15:57:45 -04002640
Nicolas Capensf160b172014-11-26 11:58:23 -05002641 framebuffer = context->getReadFramebuffer();
2642 }
2643 else
2644 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002645 if(context->getDrawFramebufferName() == 0)
Nicolas Capensf160b172014-11-26 11:58:23 -05002646 {
2647 return error(GL_INVALID_OPERATION);
2648 }
John Bauman66b8ab22014-05-06 15:57:45 -04002649
Nicolas Capensf160b172014-11-26 11:58:23 -05002650 framebuffer = context->getDrawFramebuffer();
2651 }
John Bauman66b8ab22014-05-06 15:57:45 -04002652
Nicolas Capensf160b172014-11-26 11:58:23 -05002653 GLenum attachmentType;
2654 GLuint attachmentHandle;
2655 switch(attachment)
2656 {
2657 case GL_COLOR_ATTACHMENT0:
2658 attachmentType = framebuffer->getColorbufferType();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002659 attachmentHandle = framebuffer->getColorbufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05002660 break;
2661 case GL_DEPTH_ATTACHMENT:
2662 attachmentType = framebuffer->getDepthbufferType();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002663 attachmentHandle = framebuffer->getDepthbufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05002664 break;
2665 case GL_STENCIL_ATTACHMENT:
2666 attachmentType = framebuffer->getStencilbufferType();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002667 attachmentHandle = framebuffer->getStencilbufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05002668 break;
2669 default:
2670 return error(GL_INVALID_ENUM);
2671 }
John Bauman66b8ab22014-05-06 15:57:45 -04002672
Nicolas Capensf160b172014-11-26 11:58:23 -05002673 GLenum attachmentObjectType; // Type category
2674 if(attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
2675 {
2676 attachmentObjectType = attachmentType;
2677 }
2678 else if(es2::IsTextureTarget(attachmentType))
2679 {
2680 attachmentObjectType = GL_TEXTURE;
2681 }
2682 else UNREACHABLE();
John Bauman66b8ab22014-05-06 15:57:45 -04002683
Nicolas Capensf160b172014-11-26 11:58:23 -05002684 switch(pname)
2685 {
2686 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2687 *params = attachmentObjectType;
2688 break;
2689 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2690 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
2691 {
2692 *params = attachmentHandle;
2693 }
2694 else
2695 {
2696 return error(GL_INVALID_ENUM);
2697 }
2698 break;
2699 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2700 if(attachmentObjectType == GL_TEXTURE)
2701 {
2702 *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0
2703 }
2704 else
2705 {
2706 return error(GL_INVALID_ENUM);
2707 }
2708 break;
2709 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2710 if(attachmentObjectType == GL_TEXTURE)
2711 {
2712 if(es2::IsCubemapTextureTarget(attachmentType))
2713 {
2714 *params = attachmentType;
2715 }
2716 else
2717 {
2718 *params = 0;
2719 }
2720 }
2721 else
2722 {
2723 return error(GL_INVALID_ENUM);
2724 }
2725 break;
2726 default:
2727 return error(GL_INVALID_ENUM);
2728 }
2729 }
John Bauman66b8ab22014-05-06 15:57:45 -04002730}
2731
2732GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
2733{
Nicolas Capensf160b172014-11-26 11:58:23 -05002734 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04002735
Nicolas Capensf160b172014-11-26 11:58:23 -05002736 return GL_NO_ERROR;
John Bauman66b8ab22014-05-06 15:57:45 -04002737}
2738
2739void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
2740{
Nicolas Capensf160b172014-11-26 11:58:23 -05002741 TRACE("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002742
Nicolas Capensf160b172014-11-26 11:58:23 -05002743 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002744
Nicolas Capens7ae353d2015-03-13 17:59:58 -04002745 if(!context)
2746 {
Greg Hartman6074f122015-04-08 09:57:16 -07002747 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
2748 #ifdef __ANDROID__
2749 ALOGI("expected_badness glGetIntegerv() called without current context.");
2750 #else
2751 ERR("glGetIntegerv() called without current context.");
2752 #endif
Nicolas Capens7ae353d2015-03-13 17:59:58 -04002753
2754 // This is not spec compliant! When there is no current GL context, functions should
2755 // have no side effects. Google Maps queries these values before creating a context,
2756 // so we need this as a bug-compatible workaround.
2757 switch(pname)
2758 {
2759 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2760 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2761 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2762 case GL_STENCIL_BITS: *params = 8; return;
2763 case GL_ALIASED_LINE_WIDTH_RANGE:
2764 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2765 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2766 return;
2767 }
2768 }
2769
Nicolas Capensf160b172014-11-26 11:58:23 -05002770 if(context)
2771 {
2772 if(!(context->getIntegerv(pname, params)))
2773 {
2774 GLenum nativeType;
2775 unsigned int numParams = 0;
2776 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2777 return error(GL_INVALID_ENUM);
John Bauman66b8ab22014-05-06 15:57:45 -04002778
Nicolas Capensf160b172014-11-26 11:58:23 -05002779 if(numParams == 0)
2780 return; // it is known that pname is valid, but there are no parameters to return
John Bauman66b8ab22014-05-06 15:57:45 -04002781
Nicolas Capensf160b172014-11-26 11:58:23 -05002782 if(nativeType == GL_BOOL)
2783 {
2784 GLboolean *boolParams = NULL;
2785 boolParams = new GLboolean[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002786
Nicolas Capensf160b172014-11-26 11:58:23 -05002787 context->getBooleanv(pname, boolParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002788
Nicolas Capensf160b172014-11-26 11:58:23 -05002789 for(unsigned int i = 0; i < numParams; ++i)
2790 {
Alexis Hetued306182015-04-02 12:02:28 -04002791 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
Nicolas Capensf160b172014-11-26 11:58:23 -05002792 }
John Bauman66b8ab22014-05-06 15:57:45 -04002793
Nicolas Capensf160b172014-11-26 11:58:23 -05002794 delete [] boolParams;
2795 }
2796 else if(nativeType == GL_FLOAT)
2797 {
2798 GLfloat *floatParams = NULL;
2799 floatParams = new GLfloat[numParams];
John Bauman66b8ab22014-05-06 15:57:45 -04002800
Nicolas Capensf160b172014-11-26 11:58:23 -05002801 context->getFloatv(pname, floatParams);
John Bauman66b8ab22014-05-06 15:57:45 -04002802
Nicolas Capensf160b172014-11-26 11:58:23 -05002803 for(unsigned int i = 0; i < numParams; ++i)
2804 {
2805 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2806 {
Alexis Hetued306182015-04-02 12:02:28 -04002807 params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) * 0.5f);
Nicolas Capensf160b172014-11-26 11:58:23 -05002808 }
2809 else
2810 {
2811 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2812 }
2813 }
John Bauman66b8ab22014-05-06 15:57:45 -04002814
Nicolas Capensf160b172014-11-26 11:58:23 -05002815 delete [] floatParams;
2816 }
2817 }
2818 }
John Bauman66b8ab22014-05-06 15:57:45 -04002819}
2820
2821void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
2822{
Nicolas Capensf160b172014-11-26 11:58:23 -05002823 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", program, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002824
Nicolas Capensf160b172014-11-26 11:58:23 -05002825 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002826
Nicolas Capensf160b172014-11-26 11:58:23 -05002827 if(context)
2828 {
2829 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002830
Nicolas Capensf160b172014-11-26 11:58:23 -05002831 if(!programObject)
2832 {
2833 return error(GL_INVALID_VALUE);
2834 }
John Bauman66b8ab22014-05-06 15:57:45 -04002835
Nicolas Capensf160b172014-11-26 11:58:23 -05002836 switch(pname)
2837 {
2838 case GL_DELETE_STATUS:
2839 *params = programObject->isFlaggedForDeletion();
2840 return;
2841 case GL_LINK_STATUS:
2842 *params = programObject->isLinked();
2843 return;
2844 case GL_VALIDATE_STATUS:
2845 *params = programObject->isValidated();
2846 return;
2847 case GL_INFO_LOG_LENGTH:
2848 *params = programObject->getInfoLogLength();
2849 return;
2850 case GL_ATTACHED_SHADERS:
2851 *params = programObject->getAttachedShadersCount();
2852 return;
2853 case GL_ACTIVE_ATTRIBUTES:
2854 *params = programObject->getActiveAttributeCount();
2855 return;
2856 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2857 *params = programObject->getActiveAttributeMaxLength();
2858 return;
2859 case GL_ACTIVE_UNIFORMS:
2860 *params = programObject->getActiveUniformCount();
2861 return;
2862 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2863 *params = programObject->getActiveUniformMaxLength();
2864 return;
2865 default:
2866 return error(GL_INVALID_ENUM);
2867 }
2868 }
John Bauman66b8ab22014-05-06 15:57:45 -04002869}
2870
2871void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2872{
Nicolas Capensf160b172014-11-26 11:58:23 -05002873 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
2874 program, bufsize, length, infolog);
John Bauman66b8ab22014-05-06 15:57:45 -04002875
Nicolas Capensf160b172014-11-26 11:58:23 -05002876 if(bufsize < 0)
2877 {
2878 return error(GL_INVALID_VALUE);
2879 }
John Bauman66b8ab22014-05-06 15:57:45 -04002880
Nicolas Capensf160b172014-11-26 11:58:23 -05002881 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002882
Nicolas Capensf160b172014-11-26 11:58:23 -05002883 if(context)
2884 {
2885 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04002886
Nicolas Capensf160b172014-11-26 11:58:23 -05002887 if(!programObject)
2888 {
2889 return error(GL_INVALID_VALUE);
2890 }
John Bauman66b8ab22014-05-06 15:57:45 -04002891
Nicolas Capensf160b172014-11-26 11:58:23 -05002892 programObject->getInfoLog(bufsize, length, infolog);
2893 }
John Bauman66b8ab22014-05-06 15:57:45 -04002894}
2895
2896void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2897{
Nicolas Capensf160b172014-11-26 11:58:23 -05002898 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002899
Nicolas Capensf160b172014-11-26 11:58:23 -05002900 switch(pname)
2901 {
2902 case GL_CURRENT_QUERY_EXT:
2903 break;
2904 default:
2905 return error(GL_INVALID_ENUM);
2906 }
John Bauman66b8ab22014-05-06 15:57:45 -04002907
Nicolas Capensf160b172014-11-26 11:58:23 -05002908 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002909
Nicolas Capensf160b172014-11-26 11:58:23 -05002910 if(context)
2911 {
2912 params[0] = context->getActiveQuery(target);
2913 }
John Bauman66b8ab22014-05-06 15:57:45 -04002914}
2915
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002916void GL_APIENTRY glGetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
John Bauman66b8ab22014-05-06 15:57:45 -04002917{
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002918 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", name, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002919
Nicolas Capensf160b172014-11-26 11:58:23 -05002920 switch(pname)
2921 {
2922 case GL_QUERY_RESULT_EXT:
2923 case GL_QUERY_RESULT_AVAILABLE_EXT:
2924 break;
2925 default:
2926 return error(GL_INVALID_ENUM);
2927 }
John Bauman66b8ab22014-05-06 15:57:45 -04002928
Nicolas Capensf160b172014-11-26 11:58:23 -05002929 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002930
Nicolas Capensf160b172014-11-26 11:58:23 -05002931 if(context)
2932 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002933 es2::Query *queryObject = context->getQuery(name, false, GL_NONE);
John Bauman66b8ab22014-05-06 15:57:45 -04002934
Nicolas Capensf160b172014-11-26 11:58:23 -05002935 if(!queryObject)
2936 {
2937 return error(GL_INVALID_OPERATION);
2938 }
John Bauman66b8ab22014-05-06 15:57:45 -04002939
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002940 if(context->getActiveQuery(queryObject->getType()) == name)
Nicolas Capensf160b172014-11-26 11:58:23 -05002941 {
2942 return error(GL_INVALID_OPERATION);
2943 }
John Bauman66b8ab22014-05-06 15:57:45 -04002944
Nicolas Capensf160b172014-11-26 11:58:23 -05002945 switch(pname)
2946 {
2947 case GL_QUERY_RESULT_EXT:
2948 params[0] = queryObject->getResult();
2949 break;
2950 case GL_QUERY_RESULT_AVAILABLE_EXT:
2951 params[0] = queryObject->isResultAvailable();
2952 break;
2953 default:
2954 ASSERT(false);
2955 }
2956 }
John Bauman66b8ab22014-05-06 15:57:45 -04002957}
2958
2959void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
2960{
Nicolas Capensf160b172014-11-26 11:58:23 -05002961 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04002962
Nicolas Capensf160b172014-11-26 11:58:23 -05002963 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04002964
Nicolas Capensf160b172014-11-26 11:58:23 -05002965 if(context)
2966 {
2967 if(target != GL_RENDERBUFFER)
2968 {
2969 return error(GL_INVALID_ENUM);
2970 }
John Bauman66b8ab22014-05-06 15:57:45 -04002971
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002972 if(context->getRenderbufferName() == 0)
Nicolas Capensf160b172014-11-26 11:58:23 -05002973 {
2974 return error(GL_INVALID_OPERATION);
2975 }
John Bauman66b8ab22014-05-06 15:57:45 -04002976
Nicolas Capens7cc75e12015-01-29 14:44:24 -05002977 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
John Bauman66b8ab22014-05-06 15:57:45 -04002978
Nicolas Capensf160b172014-11-26 11:58:23 -05002979 switch(pname)
2980 {
2981 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
2982 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
2983 case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getFormat(); break;
2984 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
2985 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
2986 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
2987 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
2988 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
2989 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
2990 case GL_RENDERBUFFER_SAMPLES_ANGLE: *params = renderbuffer->getSamples(); break;
2991 default:
2992 return error(GL_INVALID_ENUM);
2993 }
2994 }
John Bauman66b8ab22014-05-06 15:57:45 -04002995}
2996
2997void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
2998{
Nicolas Capensf160b172014-11-26 11:58:23 -05002999 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003000
Nicolas Capensf160b172014-11-26 11:58:23 -05003001 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003002
Nicolas Capensf160b172014-11-26 11:58:23 -05003003 if(context)
3004 {
3005 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003006
Nicolas Capensf160b172014-11-26 11:58:23 -05003007 if(!shaderObject)
3008 {
3009 return error(GL_INVALID_VALUE);
3010 }
John Bauman66b8ab22014-05-06 15:57:45 -04003011
Nicolas Capensf160b172014-11-26 11:58:23 -05003012 switch(pname)
3013 {
3014 case GL_SHADER_TYPE:
3015 *params = shaderObject->getType();
3016 return;
3017 case GL_DELETE_STATUS:
3018 *params = shaderObject->isFlaggedForDeletion();
3019 return;
3020 case GL_COMPILE_STATUS:
3021 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3022 return;
3023 case GL_INFO_LOG_LENGTH:
3024 *params = shaderObject->getInfoLogLength();
3025 return;
3026 case GL_SHADER_SOURCE_LENGTH:
3027 *params = shaderObject->getSourceLength();
3028 return;
3029 default:
3030 return error(GL_INVALID_ENUM);
3031 }
3032 }
John Bauman66b8ab22014-05-06 15:57:45 -04003033}
3034
3035void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3036{
Nicolas Capensf160b172014-11-26 11:58:23 -05003037 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
3038 shader, bufsize, length, infolog);
John Bauman66b8ab22014-05-06 15:57:45 -04003039
Nicolas Capensf160b172014-11-26 11:58:23 -05003040 if(bufsize < 0)
3041 {
3042 return error(GL_INVALID_VALUE);
3043 }
John Bauman66b8ab22014-05-06 15:57:45 -04003044
Nicolas Capensf160b172014-11-26 11:58:23 -05003045 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003046
Nicolas Capensf160b172014-11-26 11:58:23 -05003047 if(context)
3048 {
3049 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003050
Nicolas Capensf160b172014-11-26 11:58:23 -05003051 if(!shaderObject)
3052 {
3053 return error(GL_INVALID_VALUE);
3054 }
John Bauman66b8ab22014-05-06 15:57:45 -04003055
Nicolas Capensf160b172014-11-26 11:58:23 -05003056 shaderObject->getInfoLog(bufsize, length, infolog);
3057 }
John Bauman66b8ab22014-05-06 15:57:45 -04003058}
3059
3060void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3061{
Nicolas Capensf160b172014-11-26 11:58:23 -05003062 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
3063 shadertype, precisiontype, range, precision);
John Bauman66b8ab22014-05-06 15:57:45 -04003064
Nicolas Capensf160b172014-11-26 11:58:23 -05003065 switch(shadertype)
3066 {
3067 case GL_VERTEX_SHADER:
3068 case GL_FRAGMENT_SHADER:
3069 break;
3070 default:
3071 return error(GL_INVALID_ENUM);
3072 }
John Bauman66b8ab22014-05-06 15:57:45 -04003073
Nicolas Capensf160b172014-11-26 11:58:23 -05003074 switch(precisiontype)
3075 {
3076 case GL_LOW_FLOAT:
3077 case GL_MEDIUM_FLOAT:
3078 case GL_HIGH_FLOAT:
3079 // IEEE 754 single-precision
3080 range[0] = 127;
3081 range[1] = 127;
3082 *precision = 23;
3083 break;
3084 case GL_LOW_INT:
3085 case GL_MEDIUM_INT:
3086 case GL_HIGH_INT:
3087 // Single-precision floating-point numbers can accurately represent integers up to +/-16777216
3088 range[0] = 24;
3089 range[1] = 24;
3090 *precision = 0;
3091 break;
3092 default:
3093 return error(GL_INVALID_ENUM);
3094 }
John Bauman66b8ab22014-05-06 15:57:45 -04003095}
3096
3097void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3098{
Nicolas Capensf160b172014-11-26 11:58:23 -05003099 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
3100 shader, bufsize, length, source);
John Bauman66b8ab22014-05-06 15:57:45 -04003101
Nicolas Capensf160b172014-11-26 11:58:23 -05003102 if(bufsize < 0)
3103 {
3104 return error(GL_INVALID_VALUE);
3105 }
John Bauman66b8ab22014-05-06 15:57:45 -04003106
Nicolas Capensf160b172014-11-26 11:58:23 -05003107 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003108
Nicolas Capensf160b172014-11-26 11:58:23 -05003109 if(context)
3110 {
3111 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003112
Nicolas Capensf160b172014-11-26 11:58:23 -05003113 if(!shaderObject)
3114 {
3115 return error(GL_INVALID_OPERATION);
3116 }
John Bauman66b8ab22014-05-06 15:57:45 -04003117
Nicolas Capensf160b172014-11-26 11:58:23 -05003118 shaderObject->getSource(bufsize, length, source);
3119 }
John Bauman66b8ab22014-05-06 15:57:45 -04003120}
3121
3122const GLubyte* GL_APIENTRY glGetString(GLenum name)
3123{
Nicolas Capensf160b172014-11-26 11:58:23 -05003124 TRACE("(GLenum name = 0x%X)", name);
John Bauman66b8ab22014-05-06 15:57:45 -04003125
Nicolas Capensf160b172014-11-26 11:58:23 -05003126 switch(name)
3127 {
3128 case GL_VENDOR:
Alexis Hetu8141d7c2015-04-02 16:45:59 -04003129 return (GLubyte*)"Google Inc.";
Nicolas Capensf160b172014-11-26 11:58:23 -05003130 case GL_RENDERER:
3131 return (GLubyte*)"SwiftShader";
3132 case GL_VERSION:
3133 return (GLubyte*)"OpenGL ES 2.0 SwiftShader " VERSION_STRING;
3134 case GL_SHADING_LANGUAGE_VERSION:
3135 return (GLubyte*)"OpenGL ES GLSL ES 1.00 SwiftShader " VERSION_STRING;
3136 case GL_EXTENSIONS:
Alexis Hetu8141d7c2015-04-02 16:45:59 -04003137 {
3138 es2::Context *context = es2::getContext();
3139 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)NULL;
3140 }
Nicolas Capensf160b172014-11-26 11:58:23 -05003141 default:
3142 return error(GL_INVALID_ENUM, (GLubyte*)NULL);
3143 }
John Bauman66b8ab22014-05-06 15:57:45 -04003144}
3145
3146void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3147{
Nicolas Capensf160b172014-11-26 11:58:23 -05003148 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003149
Nicolas Capensf160b172014-11-26 11:58:23 -05003150 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003151
Nicolas Capensf160b172014-11-26 11:58:23 -05003152 if(context)
3153 {
3154 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04003155
Alexis Hetued306182015-04-02 12:02:28 -04003156 egl::GLint clientVersion = context->getClientVersion();
3157
Nicolas Capensf160b172014-11-26 11:58:23 -05003158 switch(target)
3159 {
3160 case GL_TEXTURE_2D:
3161 texture = context->getTexture2D();
3162 break;
3163 case GL_TEXTURE_CUBE_MAP:
3164 texture = context->getTextureCubeMap();
3165 break;
3166 case GL_TEXTURE_EXTERNAL_OES:
3167 texture = context->getTextureExternal();
3168 break;
Alexis Hetued306182015-04-02 12:02:28 -04003169 case GL_TEXTURE_2D_ARRAY:
3170 if(clientVersion < 3)
3171 {
3172 return error(GL_INVALID_ENUM);
3173 }
3174 else
3175 {
3176 UNIMPLEMENTED();
3177 texture = context->getTexture3D();
3178 break;
3179 }
3180 case GL_TEXTURE_3D_OES:
3181 texture = context->getTexture3D();
3182 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05003183 default:
3184 return error(GL_INVALID_ENUM);
3185 }
John Bauman66b8ab22014-05-06 15:57:45 -04003186
Nicolas Capensf160b172014-11-26 11:58:23 -05003187 switch(pname)
3188 {
3189 case GL_TEXTURE_MAG_FILTER:
3190 *params = (GLfloat)texture->getMagFilter();
3191 break;
3192 case GL_TEXTURE_MIN_FILTER:
3193 *params = (GLfloat)texture->getMinFilter();
3194 break;
3195 case GL_TEXTURE_WRAP_S:
3196 *params = (GLfloat)texture->getWrapS();
3197 break;
3198 case GL_TEXTURE_WRAP_T:
3199 *params = (GLfloat)texture->getWrapT();
3200 break;
Alexis Hetub027aa92015-01-19 15:56:12 -05003201 case GL_TEXTURE_WRAP_R_OES:
3202 *params = (GLfloat)texture->getWrapR();
3203 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05003204 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3205 *params = texture->getMaxAnisotropy();
3206 break;
3207 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3208 *params = (GLfloat)1;
3209 break;
Alexis Hetued306182015-04-02 12:02:28 -04003210 case GL_TEXTURE_BASE_LEVEL:
3211 if(clientVersion >= 3)
3212 {
3213 *params = (GLfloat)texture->getBaseLevel();
3214 break;
3215 }
3216 else return error(GL_INVALID_ENUM);
3217 case GL_TEXTURE_COMPARE_FUNC:
3218 if(clientVersion >= 3)
3219 {
3220 *params = (GLfloat)texture->getCompareFunc();
3221 break;
3222 }
3223 else return error(GL_INVALID_ENUM);
3224 case GL_TEXTURE_COMPARE_MODE:
3225 if(clientVersion >= 3)
3226 {
3227 *params = (GLfloat)texture->getCompareMode();
3228 break;
3229 }
3230 else return error(GL_INVALID_ENUM);
3231 case GL_TEXTURE_IMMUTABLE_FORMAT:
3232 if(clientVersion >= 3)
3233 {
3234 *params = (GLfloat)texture->getImmutableFormat();
3235 break;
3236 }
3237 else return error(GL_INVALID_ENUM);
3238 case GL_TEXTURE_MAX_LEVEL:
3239 if(clientVersion >= 3)
3240 {
3241 *params = (GLfloat)texture->getMaxLevel();
3242 break;
3243 }
3244 else return error(GL_INVALID_ENUM);
3245 case GL_TEXTURE_MAX_LOD:
3246 if(clientVersion >= 3)
3247 {
3248 *params = texture->getMaxLOD();
3249 break;
3250 }
3251 else return error(GL_INVALID_ENUM);
3252 case GL_TEXTURE_MIN_LOD:
3253 if(clientVersion >= 3)
3254 {
3255 *params = texture->getMinLOD();
3256 break;
3257 }
3258 else return error(GL_INVALID_ENUM);
3259 case GL_TEXTURE_SWIZZLE_R:
3260 if(clientVersion >= 3)
3261 {
3262 *params = (GLfloat)texture->getSwizzleR();
3263 break;
3264 }
3265 else return error(GL_INVALID_ENUM);
3266 case GL_TEXTURE_SWIZZLE_G:
3267 if(clientVersion >= 3)
3268 {
3269 *params = (GLfloat)texture->getSwizzleG();
3270 break;
3271 }
3272 else return error(GL_INVALID_ENUM);
3273 case GL_TEXTURE_SWIZZLE_B:
3274 if(clientVersion >= 3)
3275 {
3276 *params = (GLfloat)texture->getSwizzleB();
3277 break;
3278 }
3279 else return error(GL_INVALID_ENUM);
3280 case GL_TEXTURE_SWIZZLE_A:
3281 if(clientVersion >= 3)
3282 {
3283 *params = (GLfloat)texture->getSwizzleA();
3284 break;
3285 }
3286 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05003287 default:
3288 return error(GL_INVALID_ENUM);
3289 }
3290 }
John Bauman66b8ab22014-05-06 15:57:45 -04003291}
3292
3293void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3294{
Nicolas Capensf160b172014-11-26 11:58:23 -05003295 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003296
Nicolas Capensf160b172014-11-26 11:58:23 -05003297 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003298
Nicolas Capensf160b172014-11-26 11:58:23 -05003299 if(context)
3300 {
3301 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04003302
Alexis Hetued306182015-04-02 12:02:28 -04003303 egl::GLint clientVersion = context->getClientVersion();
3304
Nicolas Capensf160b172014-11-26 11:58:23 -05003305 switch(target)
3306 {
3307 case GL_TEXTURE_2D:
3308 texture = context->getTexture2D();
3309 break;
3310 case GL_TEXTURE_CUBE_MAP:
3311 texture = context->getTextureCubeMap();
3312 break;
3313 case GL_TEXTURE_EXTERNAL_OES:
3314 texture = context->getTextureExternal();
3315 break;
Alexis Hetued306182015-04-02 12:02:28 -04003316 case GL_TEXTURE_2D_ARRAY:
3317 if(clientVersion < 3)
3318 {
3319 return error(GL_INVALID_ENUM);
3320 }
3321 else
3322 {
3323 UNIMPLEMENTED();
3324 texture = context->getTexture3D();
3325 break;
3326 }
3327 case GL_TEXTURE_3D_OES:
3328 texture = context->getTexture3D();
3329 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05003330 default:
3331 return error(GL_INVALID_ENUM);
3332 }
John Bauman66b8ab22014-05-06 15:57:45 -04003333
Nicolas Capensf160b172014-11-26 11:58:23 -05003334 switch(pname)
3335 {
3336 case GL_TEXTURE_MAG_FILTER:
3337 *params = texture->getMagFilter();
3338 break;
3339 case GL_TEXTURE_MIN_FILTER:
3340 *params = texture->getMinFilter();
3341 break;
3342 case GL_TEXTURE_WRAP_S:
3343 *params = texture->getWrapS();
3344 break;
3345 case GL_TEXTURE_WRAP_T:
3346 *params = texture->getWrapT();
3347 break;
Alexis Hetub027aa92015-01-19 15:56:12 -05003348 case GL_TEXTURE_WRAP_R_OES:
3349 *params = texture->getWrapR();
3350 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05003351 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3352 *params = (GLint)texture->getMaxAnisotropy();
3353 break;
3354 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3355 *params = 1;
3356 break;
Alexis Hetued306182015-04-02 12:02:28 -04003357 case GL_TEXTURE_BASE_LEVEL:
3358 if(clientVersion >= 3)
3359 {
3360 *params = texture->getBaseLevel();
3361 break;
3362 }
3363 else return error(GL_INVALID_ENUM);
3364 case GL_TEXTURE_COMPARE_FUNC:
3365 if(clientVersion >= 3)
3366 {
3367 *params = (GLint)texture->getCompareFunc();
3368 break;
3369 }
3370 else return error(GL_INVALID_ENUM);
3371 case GL_TEXTURE_COMPARE_MODE:
3372 if(clientVersion >= 3)
3373 {
3374 *params = (GLint)texture->getCompareMode();
3375 break;
3376 }
3377 else return error(GL_INVALID_ENUM);
3378 case GL_TEXTURE_IMMUTABLE_FORMAT:
3379 if(clientVersion >= 3)
3380 {
3381 *params = (GLint)texture->getImmutableFormat();
3382 break;
3383 }
3384 else return error(GL_INVALID_ENUM);
3385 case GL_TEXTURE_MAX_LEVEL:
3386 if(clientVersion >= 3)
3387 {
3388 *params = texture->getMaxLevel();
3389 break;
3390 }
3391 else return error(GL_INVALID_ENUM);
3392 case GL_TEXTURE_MAX_LOD:
3393 if(clientVersion >= 3)
3394 {
3395 *params = (GLint)texture->getMaxLOD();
3396 break;
3397 }
3398 else return error(GL_INVALID_ENUM);
3399 case GL_TEXTURE_MIN_LOD:
3400 if(clientVersion >= 3)
3401 {
3402 *params = (GLint)texture->getMinLOD();
3403 break;
3404 }
3405 else return error(GL_INVALID_ENUM);
3406 case GL_TEXTURE_SWIZZLE_R:
3407 if(clientVersion >= 3)
3408 {
3409 *params = (GLint)texture->getSwizzleR();
3410 break;
3411 }
3412 else return error(GL_INVALID_ENUM);
3413 case GL_TEXTURE_SWIZZLE_G:
3414 if(clientVersion >= 3)
3415 {
3416 *params = (GLint)texture->getSwizzleG();
3417 break;
3418 }
3419 else return error(GL_INVALID_ENUM);
3420 case GL_TEXTURE_SWIZZLE_B:
3421 if(clientVersion >= 3)
3422 {
3423 *params = (GLint)texture->getSwizzleB();
3424 break;
3425 }
3426 else return error(GL_INVALID_ENUM);
3427 case GL_TEXTURE_SWIZZLE_A:
3428 if(clientVersion >= 3)
3429 {
3430 *params = (GLint)texture->getSwizzleA();
3431 break;
3432 }
3433 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05003434 default:
3435 return error(GL_INVALID_ENUM);
3436 }
3437 }
John Bauman66b8ab22014-05-06 15:57:45 -04003438}
3439
3440void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3441{
Nicolas Capensf160b172014-11-26 11:58:23 -05003442 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
3443 program, location, bufSize, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003444
Nicolas Capensf160b172014-11-26 11:58:23 -05003445 if(bufSize < 0)
3446 {
3447 return error(GL_INVALID_VALUE);
3448 }
John Bauman66b8ab22014-05-06 15:57:45 -04003449
Nicolas Capensf160b172014-11-26 11:58:23 -05003450 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003451
Nicolas Capensf160b172014-11-26 11:58:23 -05003452 if(context)
3453 {
3454 if(program == 0)
3455 {
3456 return error(GL_INVALID_VALUE);
3457 }
John Bauman66b8ab22014-05-06 15:57:45 -04003458
Nicolas Capensf160b172014-11-26 11:58:23 -05003459 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003460
Nicolas Capensf160b172014-11-26 11:58:23 -05003461 if(!programObject || !programObject->isLinked())
3462 {
3463 return error(GL_INVALID_OPERATION);
3464 }
John Bauman66b8ab22014-05-06 15:57:45 -04003465
Nicolas Capensf160b172014-11-26 11:58:23 -05003466 if(!programObject->getUniformfv(location, &bufSize, params))
3467 {
3468 return error(GL_INVALID_OPERATION);
3469 }
3470 }
John Bauman66b8ab22014-05-06 15:57:45 -04003471}
3472
3473void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
3474{
Nicolas Capensf160b172014-11-26 11:58:23 -05003475 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003476
Nicolas Capensf160b172014-11-26 11:58:23 -05003477 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003478
Nicolas Capensf160b172014-11-26 11:58:23 -05003479 if(context)
3480 {
3481 if(program == 0)
3482 {
3483 return error(GL_INVALID_VALUE);
3484 }
John Bauman66b8ab22014-05-06 15:57:45 -04003485
Nicolas Capensf160b172014-11-26 11:58:23 -05003486 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003487
Nicolas Capensf160b172014-11-26 11:58:23 -05003488 if(!programObject || !programObject->isLinked())
3489 {
3490 return error(GL_INVALID_OPERATION);
3491 }
John Bauman66b8ab22014-05-06 15:57:45 -04003492
Nicolas Capensf160b172014-11-26 11:58:23 -05003493 if(!programObject->getUniformfv(location, NULL, params))
3494 {
3495 return error(GL_INVALID_OPERATION);
3496 }
3497 }
John Bauman66b8ab22014-05-06 15:57:45 -04003498}
3499
3500void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3501{
Nicolas Capensf160b172014-11-26 11:58:23 -05003502 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
3503 program, location, bufSize, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003504
Nicolas Capensf160b172014-11-26 11:58:23 -05003505 if(bufSize < 0)
3506 {
3507 return error(GL_INVALID_VALUE);
3508 }
John Bauman66b8ab22014-05-06 15:57:45 -04003509
Nicolas Capensf160b172014-11-26 11:58:23 -05003510 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003511
Nicolas Capensf160b172014-11-26 11:58:23 -05003512 if(context)
3513 {
3514 if(program == 0)
3515 {
3516 return error(GL_INVALID_VALUE);
3517 }
John Bauman66b8ab22014-05-06 15:57:45 -04003518
Nicolas Capensf160b172014-11-26 11:58:23 -05003519 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003520
Nicolas Capensf160b172014-11-26 11:58:23 -05003521 if(!programObject || !programObject->isLinked())
3522 {
3523 return error(GL_INVALID_OPERATION);
3524 }
John Bauman66b8ab22014-05-06 15:57:45 -04003525
Nicolas Capensf160b172014-11-26 11:58:23 -05003526 if(!programObject)
3527 {
3528 return error(GL_INVALID_OPERATION);
3529 }
John Bauman66b8ab22014-05-06 15:57:45 -04003530
Nicolas Capensf160b172014-11-26 11:58:23 -05003531 if(!programObject->getUniformiv(location, &bufSize, params))
3532 {
3533 return error(GL_INVALID_OPERATION);
3534 }
3535 }
John Bauman66b8ab22014-05-06 15:57:45 -04003536}
3537
3538void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
3539{
Nicolas Capensf160b172014-11-26 11:58:23 -05003540 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003541
Nicolas Capensf160b172014-11-26 11:58:23 -05003542 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003543
Nicolas Capensf160b172014-11-26 11:58:23 -05003544 if(context)
3545 {
3546 if(program == 0)
3547 {
3548 return error(GL_INVALID_VALUE);
3549 }
John Bauman66b8ab22014-05-06 15:57:45 -04003550
Nicolas Capensf160b172014-11-26 11:58:23 -05003551 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003552
Nicolas Capensf160b172014-11-26 11:58:23 -05003553 if(!programObject || !programObject->isLinked())
3554 {
3555 return error(GL_INVALID_OPERATION);
3556 }
John Bauman66b8ab22014-05-06 15:57:45 -04003557
Nicolas Capensf160b172014-11-26 11:58:23 -05003558 if(!programObject)
3559 {
3560 return error(GL_INVALID_OPERATION);
3561 }
John Bauman66b8ab22014-05-06 15:57:45 -04003562
Nicolas Capensf160b172014-11-26 11:58:23 -05003563 if(!programObject->getUniformiv(location, NULL, params))
3564 {
3565 return error(GL_INVALID_OPERATION);
3566 }
3567 }
John Bauman66b8ab22014-05-06 15:57:45 -04003568}
3569
3570int GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
3571{
Nicolas Capensf160b172014-11-26 11:58:23 -05003572 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
John Bauman66b8ab22014-05-06 15:57:45 -04003573
Nicolas Capensf160b172014-11-26 11:58:23 -05003574 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003575
Nicolas Capensf160b172014-11-26 11:58:23 -05003576 if(strstr(name, "gl_") == name)
3577 {
3578 return -1;
3579 }
John Bauman66b8ab22014-05-06 15:57:45 -04003580
Nicolas Capensf160b172014-11-26 11:58:23 -05003581 if(context)
3582 {
3583 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003584
Nicolas Capensf160b172014-11-26 11:58:23 -05003585 if(!programObject)
3586 {
3587 if(context->getShader(program))
3588 {
3589 return error(GL_INVALID_OPERATION, -1);
3590 }
3591 else
3592 {
3593 return error(GL_INVALID_VALUE, -1);
3594 }
3595 }
John Bauman66b8ab22014-05-06 15:57:45 -04003596
Nicolas Capensf160b172014-11-26 11:58:23 -05003597 if(!programObject->isLinked())
3598 {
3599 return error(GL_INVALID_OPERATION, -1);
3600 }
John Bauman66b8ab22014-05-06 15:57:45 -04003601
Nicolas Capensf160b172014-11-26 11:58:23 -05003602 return programObject->getUniformLocation(name);
3603 }
John Bauman66b8ab22014-05-06 15:57:45 -04003604
Nicolas Capensf160b172014-11-26 11:58:23 -05003605 return -1;
John Bauman66b8ab22014-05-06 15:57:45 -04003606}
3607
3608void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3609{
Nicolas Capensf160b172014-11-26 11:58:23 -05003610 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003611
Nicolas Capensf160b172014-11-26 11:58:23 -05003612 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003613
Nicolas Capensf160b172014-11-26 11:58:23 -05003614 if(context)
3615 {
3616 if(index >= es2::MAX_VERTEX_ATTRIBS)
3617 {
3618 return error(GL_INVALID_VALUE);
3619 }
John Bauman66b8ab22014-05-06 15:57:45 -04003620
Nicolas Capensf160b172014-11-26 11:58:23 -05003621 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
Alexis Hetued306182015-04-02 12:02:28 -04003622
3623 egl::GLint clientVersion = context->getClientVersion();
John Bauman66b8ab22014-05-06 15:57:45 -04003624
Nicolas Capensf160b172014-11-26 11:58:23 -05003625 switch(pname)
3626 {
3627 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3628 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3629 break;
3630 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3631 *params = (GLfloat)attribState.mSize;
3632 break;
3633 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3634 *params = (GLfloat)attribState.mStride;
3635 break;
3636 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3637 *params = (GLfloat)attribState.mType;
3638 break;
3639 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3640 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3641 break;
3642 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003643 *params = (GLfloat)attribState.mBoundBuffer.name();
Nicolas Capensf160b172014-11-26 11:58:23 -05003644 break;
3645 case GL_CURRENT_VERTEX_ATTRIB:
3646 for(int i = 0; i < 4; ++i)
3647 {
Alexis Hetu93ae1032015-04-10 14:31:01 -04003648 params[i] = attribState.getCurrentValue(i);
Nicolas Capensf160b172014-11-26 11:58:23 -05003649 }
3650 break;
Alexis Hetued306182015-04-02 12:02:28 -04003651 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
3652 if(clientVersion >= 3)
3653 {
3654 switch(attribState.mType)
3655 {
3656 case GL_BYTE:
3657 case GL_UNSIGNED_BYTE:
3658 case GL_SHORT:
3659 case GL_UNSIGNED_SHORT:
3660 case GL_INT:
3661 case GL_INT_2_10_10_10_REV:
3662 case GL_UNSIGNED_INT:
3663 case GL_FIXED:
3664 *params = (GLfloat)GL_TRUE;
3665 break;
3666 default:
3667 *params = (GLfloat)GL_FALSE;
3668 break;
3669 }
3670 break;
3671 }
3672 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05003673 default: return error(GL_INVALID_ENUM);
3674 }
3675 }
John Bauman66b8ab22014-05-06 15:57:45 -04003676}
3677
3678void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3679{
Nicolas Capensf160b172014-11-26 11:58:23 -05003680 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
John Bauman66b8ab22014-05-06 15:57:45 -04003681
Nicolas Capensf160b172014-11-26 11:58:23 -05003682 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003683
Nicolas Capensf160b172014-11-26 11:58:23 -05003684 if(context)
3685 {
3686 if(index >= es2::MAX_VERTEX_ATTRIBS)
3687 {
3688 return error(GL_INVALID_VALUE);
3689 }
John Bauman66b8ab22014-05-06 15:57:45 -04003690
Nicolas Capensf160b172014-11-26 11:58:23 -05003691 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
John Bauman66b8ab22014-05-06 15:57:45 -04003692
Alexis Hetued306182015-04-02 12:02:28 -04003693 egl::GLint clientVersion = context->getClientVersion();
3694
Nicolas Capensf160b172014-11-26 11:58:23 -05003695 switch(pname)
3696 {
3697 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3698 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3699 break;
3700 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3701 *params = attribState.mSize;
3702 break;
3703 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3704 *params = attribState.mStride;
3705 break;
3706 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3707 *params = attribState.mType;
3708 break;
3709 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3710 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3711 break;
3712 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003713 *params = attribState.mBoundBuffer.name();
Nicolas Capensf160b172014-11-26 11:58:23 -05003714 break;
3715 case GL_CURRENT_VERTEX_ATTRIB:
3716 for(int i = 0; i < 4; ++i)
3717 {
Alexis Hetu93ae1032015-04-10 14:31:01 -04003718 float currentValue = attribState.getCurrentValue(i);
Nicolas Capensf160b172014-11-26 11:58:23 -05003719 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3720 }
3721 break;
Alexis Hetued306182015-04-02 12:02:28 -04003722 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
3723 if(clientVersion >= 3)
3724 {
3725 switch(attribState.mType)
3726 {
3727 case GL_BYTE:
3728 case GL_UNSIGNED_BYTE:
3729 case GL_SHORT:
3730 case GL_UNSIGNED_SHORT:
3731 case GL_INT:
3732 case GL_INT_2_10_10_10_REV:
3733 case GL_UNSIGNED_INT:
3734 case GL_FIXED:
3735 *params = GL_TRUE;
3736 break;
3737 default:
3738 *params = GL_FALSE;
3739 break;
3740 }
3741 break;
3742 }
3743 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05003744 default: return error(GL_INVALID_ENUM);
3745 }
3746 }
John Bauman66b8ab22014-05-06 15:57:45 -04003747}
3748
3749void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3750{
Nicolas Capensf160b172014-11-26 11:58:23 -05003751 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
John Bauman66b8ab22014-05-06 15:57:45 -04003752
Nicolas Capensf160b172014-11-26 11:58:23 -05003753 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003754
Nicolas Capensf160b172014-11-26 11:58:23 -05003755 if(context)
3756 {
3757 if(index >= es2::MAX_VERTEX_ATTRIBS)
3758 {
3759 return error(GL_INVALID_VALUE);
3760 }
John Bauman66b8ab22014-05-06 15:57:45 -04003761
Nicolas Capensf160b172014-11-26 11:58:23 -05003762 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3763 {
3764 return error(GL_INVALID_ENUM);
3765 }
John Bauman66b8ab22014-05-06 15:57:45 -04003766
Nicolas Capensf160b172014-11-26 11:58:23 -05003767 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3768 }
John Bauman66b8ab22014-05-06 15:57:45 -04003769}
3770
3771void GL_APIENTRY glHint(GLenum target, GLenum mode)
3772{
Nicolas Capensf160b172014-11-26 11:58:23 -05003773 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
John Bauman66b8ab22014-05-06 15:57:45 -04003774
Nicolas Capensf160b172014-11-26 11:58:23 -05003775 switch(mode)
3776 {
3777 case GL_FASTEST:
3778 case GL_NICEST:
3779 case GL_DONT_CARE:
3780 break;
3781 default:
3782 return error(GL_INVALID_ENUM);
3783 }
John Bauman66b8ab22014-05-06 15:57:45 -04003784
Nicolas Capensf160b172014-11-26 11:58:23 -05003785 es2::Context *context = es2::getContext();
3786 switch(target)
3787 {
3788 case GL_GENERATE_MIPMAP_HINT:
3789 if(context) context->setGenerateMipmapHint(mode);
3790 break;
3791 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3792 if(context) context->setFragmentShaderDerivativeHint(mode);
3793 break;
3794 default:
3795 return error(GL_INVALID_ENUM);
3796 }
John Bauman66b8ab22014-05-06 15:57:45 -04003797}
3798
3799GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
3800{
Nicolas Capensf160b172014-11-26 11:58:23 -05003801 TRACE("(GLuint buffer = %d)", buffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003802
Nicolas Capensf160b172014-11-26 11:58:23 -05003803 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003804
Nicolas Capensf160b172014-11-26 11:58:23 -05003805 if(context && buffer)
3806 {
3807 es2::Buffer *bufferObject = context->getBuffer(buffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003808
Nicolas Capensf160b172014-11-26 11:58:23 -05003809 if(bufferObject)
3810 {
3811 return GL_TRUE;
3812 }
3813 }
John Bauman66b8ab22014-05-06 15:57:45 -04003814
Nicolas Capensf160b172014-11-26 11:58:23 -05003815 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003816}
3817
3818GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
3819{
Nicolas Capensf160b172014-11-26 11:58:23 -05003820 TRACE("(GLenum cap = 0x%X)", cap);
John Bauman66b8ab22014-05-06 15:57:45 -04003821
Nicolas Capensf160b172014-11-26 11:58:23 -05003822 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003823
Nicolas Capensf160b172014-11-26 11:58:23 -05003824 if(context)
3825 {
3826 switch(cap)
3827 {
3828 case GL_CULL_FACE: return context->isCullFaceEnabled();
3829 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3830 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3831 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3832 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3833 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3834 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3835 case GL_BLEND: return context->isBlendEnabled();
3836 case GL_DITHER: return context->isDitherEnabled();
3837 default:
3838 return error(GL_INVALID_ENUM, false);
3839 }
3840 }
John Bauman66b8ab22014-05-06 15:57:45 -04003841
Nicolas Capensf160b172014-11-26 11:58:23 -05003842 return false;
John Bauman66b8ab22014-05-06 15:57:45 -04003843}
3844
3845GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
3846{
Nicolas Capensf160b172014-11-26 11:58:23 -05003847 TRACE("(GLuint fence = %d)", fence);
John Bauman66b8ab22014-05-06 15:57:45 -04003848
Nicolas Capensf160b172014-11-26 11:58:23 -05003849 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003850
Nicolas Capensf160b172014-11-26 11:58:23 -05003851 if(context)
3852 {
3853 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04003854
Nicolas Capensf160b172014-11-26 11:58:23 -05003855 if(fenceObject == NULL)
3856 {
3857 return GL_FALSE;
3858 }
John Bauman66b8ab22014-05-06 15:57:45 -04003859
Nicolas Capensf160b172014-11-26 11:58:23 -05003860 return fenceObject->isFence();
3861 }
John Bauman66b8ab22014-05-06 15:57:45 -04003862
Nicolas Capensf160b172014-11-26 11:58:23 -05003863 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003864}
3865
3866GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
3867{
Nicolas Capensf160b172014-11-26 11:58:23 -05003868 TRACE("(GLuint framebuffer = %d)", framebuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003869
Nicolas Capensf160b172014-11-26 11:58:23 -05003870 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003871
Nicolas Capensf160b172014-11-26 11:58:23 -05003872 if(context && framebuffer)
3873 {
3874 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003875
Nicolas Capensf160b172014-11-26 11:58:23 -05003876 if(framebufferObject)
3877 {
3878 return GL_TRUE;
3879 }
3880 }
John Bauman66b8ab22014-05-06 15:57:45 -04003881
Nicolas Capensf160b172014-11-26 11:58:23 -05003882 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003883}
3884
3885GLboolean GL_APIENTRY glIsProgram(GLuint program)
3886{
Nicolas Capensf160b172014-11-26 11:58:23 -05003887 TRACE("(GLuint program = %d)", program);
John Bauman66b8ab22014-05-06 15:57:45 -04003888
Nicolas Capensf160b172014-11-26 11:58:23 -05003889 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003890
Nicolas Capensf160b172014-11-26 11:58:23 -05003891 if(context && program)
3892 {
3893 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04003894
Nicolas Capensf160b172014-11-26 11:58:23 -05003895 if(programObject)
3896 {
3897 return GL_TRUE;
3898 }
3899 }
John Bauman66b8ab22014-05-06 15:57:45 -04003900
Nicolas Capensf160b172014-11-26 11:58:23 -05003901 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003902}
3903
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003904GLboolean GL_APIENTRY glIsQueryEXT(GLuint name)
John Bauman66b8ab22014-05-06 15:57:45 -04003905{
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003906 TRACE("(GLuint name = %d)", name);
John Bauman66b8ab22014-05-06 15:57:45 -04003907
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003908 if(name == 0)
Nicolas Capensf160b172014-11-26 11:58:23 -05003909 {
3910 return GL_FALSE;
3911 }
John Bauman66b8ab22014-05-06 15:57:45 -04003912
Nicolas Capensf160b172014-11-26 11:58:23 -05003913 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003914
Nicolas Capensf160b172014-11-26 11:58:23 -05003915 if(context)
3916 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -05003917 es2::Query *queryObject = context->getQuery(name, false, GL_NONE);
John Bauman66b8ab22014-05-06 15:57:45 -04003918
Nicolas Capensf160b172014-11-26 11:58:23 -05003919 if(queryObject)
3920 {
3921 return GL_TRUE;
3922 }
3923 }
John Bauman66b8ab22014-05-06 15:57:45 -04003924
Nicolas Capensf160b172014-11-26 11:58:23 -05003925 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003926}
3927
3928GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
3929{
Nicolas Capensf160b172014-11-26 11:58:23 -05003930 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003931
Nicolas Capensf160b172014-11-26 11:58:23 -05003932 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003933
Nicolas Capensf160b172014-11-26 11:58:23 -05003934 if(context && renderbuffer)
3935 {
3936 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
John Bauman66b8ab22014-05-06 15:57:45 -04003937
Nicolas Capensf160b172014-11-26 11:58:23 -05003938 if(renderbufferObject)
3939 {
3940 return GL_TRUE;
3941 }
3942 }
John Bauman66b8ab22014-05-06 15:57:45 -04003943
Nicolas Capensf160b172014-11-26 11:58:23 -05003944 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003945}
3946
3947GLboolean GL_APIENTRY glIsShader(GLuint shader)
3948{
Nicolas Capensf160b172014-11-26 11:58:23 -05003949 TRACE("(GLuint shader = %d)", shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003950
Nicolas Capensf160b172014-11-26 11:58:23 -05003951 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003952
Nicolas Capensf160b172014-11-26 11:58:23 -05003953 if(context && shader)
3954 {
3955 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04003956
Nicolas Capensf160b172014-11-26 11:58:23 -05003957 if(shaderObject)
3958 {
3959 return GL_TRUE;
3960 }
3961 }
John Bauman66b8ab22014-05-06 15:57:45 -04003962
Nicolas Capensf160b172014-11-26 11:58:23 -05003963 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003964}
3965
3966GLboolean GL_APIENTRY glIsTexture(GLuint texture)
3967{
Nicolas Capensf160b172014-11-26 11:58:23 -05003968 TRACE("(GLuint texture = %d)", texture);
John Bauman66b8ab22014-05-06 15:57:45 -04003969
Nicolas Capensf160b172014-11-26 11:58:23 -05003970 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003971
Nicolas Capensf160b172014-11-26 11:58:23 -05003972 if(context && texture)
3973 {
3974 es2::Texture *textureObject = context->getTexture(texture);
John Bauman66b8ab22014-05-06 15:57:45 -04003975
Nicolas Capensf160b172014-11-26 11:58:23 -05003976 if(textureObject)
3977 {
3978 return GL_TRUE;
3979 }
3980 }
John Bauman66b8ab22014-05-06 15:57:45 -04003981
Nicolas Capensf160b172014-11-26 11:58:23 -05003982 return GL_FALSE;
John Bauman66b8ab22014-05-06 15:57:45 -04003983}
3984
3985void GL_APIENTRY glLineWidth(GLfloat width)
3986{
Nicolas Capensf160b172014-11-26 11:58:23 -05003987 TRACE("(GLfloat width = %f)", width);
John Bauman66b8ab22014-05-06 15:57:45 -04003988
Nicolas Capensf160b172014-11-26 11:58:23 -05003989 if(width <= 0.0f)
3990 {
3991 return error(GL_INVALID_VALUE);
3992 }
John Bauman66b8ab22014-05-06 15:57:45 -04003993
Nicolas Capensf160b172014-11-26 11:58:23 -05003994 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04003995
Nicolas Capensf160b172014-11-26 11:58:23 -05003996 if(context)
3997 {
3998 context->setLineWidth(width);
3999 }
John Bauman66b8ab22014-05-06 15:57:45 -04004000}
4001
4002void GL_APIENTRY glLinkProgram(GLuint program)
4003{
Nicolas Capensf160b172014-11-26 11:58:23 -05004004 TRACE("(GLuint program = %d)", program);
John Bauman66b8ab22014-05-06 15:57:45 -04004005
Nicolas Capensf160b172014-11-26 11:58:23 -05004006 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004007
Nicolas Capensf160b172014-11-26 11:58:23 -05004008 if(context)
4009 {
4010 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04004011
Nicolas Capensf160b172014-11-26 11:58:23 -05004012 if(!programObject)
4013 {
4014 if(context->getShader(program))
4015 {
4016 return error(GL_INVALID_OPERATION);
4017 }
4018 else
4019 {
4020 return error(GL_INVALID_VALUE);
4021 }
4022 }
John Bauman66b8ab22014-05-06 15:57:45 -04004023
Nicolas Capensf160b172014-11-26 11:58:23 -05004024 programObject->link();
4025 }
John Bauman66b8ab22014-05-06 15:57:45 -04004026}
4027
4028void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
4029{
Nicolas Capensf160b172014-11-26 11:58:23 -05004030 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
John Bauman66b8ab22014-05-06 15:57:45 -04004031
Nicolas Capensf160b172014-11-26 11:58:23 -05004032 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004033
Nicolas Capensf160b172014-11-26 11:58:23 -05004034 if(context)
4035 {
Alexis Hetued306182015-04-02 12:02:28 -04004036 egl::GLint clientVersion = context->getClientVersion();
4037
Nicolas Capensf160b172014-11-26 11:58:23 -05004038 switch(pname)
4039 {
4040 case GL_UNPACK_ALIGNMENT:
4041 if(param != 1 && param != 2 && param != 4 && param != 8)
4042 {
4043 return error(GL_INVALID_VALUE);
4044 }
4045 context->setUnpackAlignment(param);
4046 break;
4047 case GL_PACK_ALIGNMENT:
4048 if(param != 1 && param != 2 && param != 4 && param != 8)
4049 {
4050 return error(GL_INVALID_VALUE);
4051 }
4052 context->setPackAlignment(param);
4053 break;
Alexis Hetued306182015-04-02 12:02:28 -04004054 case GL_PACK_ROW_LENGTH:
4055 case GL_PACK_SKIP_PIXELS:
4056 case GL_PACK_SKIP_ROWS:
4057 case GL_UNPACK_ROW_LENGTH:
4058 case GL_UNPACK_IMAGE_HEIGHT:
4059 case GL_UNPACK_SKIP_PIXELS:
4060 case GL_UNPACK_SKIP_ROWS:
4061 case GL_UNPACK_SKIP_IMAGES:
4062 if(clientVersion >= 3)
4063 {
4064 UNIMPLEMENTED();
4065 break;
4066 }
4067 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05004068 default:
4069 return error(GL_INVALID_ENUM);
4070 }
4071 }
John Bauman66b8ab22014-05-06 15:57:45 -04004072}
4073
4074void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
4075{
Nicolas Capensf160b172014-11-26 11:58:23 -05004076 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
John Bauman66b8ab22014-05-06 15:57:45 -04004077
Nicolas Capensf160b172014-11-26 11:58:23 -05004078 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004079
Nicolas Capensf160b172014-11-26 11:58:23 -05004080 if(context)
4081 {
4082 context->setPolygonOffsetParams(factor, units);
4083 }
John Bauman66b8ab22014-05-06 15:57:45 -04004084}
4085
4086void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
Nicolas Capensf160b172014-11-26 11:58:23 -05004087 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
John Bauman66b8ab22014-05-06 15:57:45 -04004088{
Nicolas Capensf160b172014-11-26 11:58:23 -05004089 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4090 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
4091 x, y, width, height, format, type, bufSize, data);
John Bauman66b8ab22014-05-06 15:57:45 -04004092
Nicolas Capensf160b172014-11-26 11:58:23 -05004093 if(width < 0 || height < 0 || bufSize < 0)
4094 {
4095 return error(GL_INVALID_VALUE);
4096 }
John Bauman66b8ab22014-05-06 15:57:45 -04004097
Nicolas Capensf160b172014-11-26 11:58:23 -05004098 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004099
Nicolas Capensf160b172014-11-26 11:58:23 -05004100 if(context)
4101 {
4102 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4103 }
John Bauman66b8ab22014-05-06 15:57:45 -04004104}
4105
4106void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4107{
Nicolas Capensf160b172014-11-26 11:58:23 -05004108 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4109 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
4110 x, y, width, height, format, type, pixels);
John Bauman66b8ab22014-05-06 15:57:45 -04004111
Nicolas Capensf160b172014-11-26 11:58:23 -05004112 if(width < 0 || height < 0)
4113 {
4114 return error(GL_INVALID_VALUE);
4115 }
John Bauman66b8ab22014-05-06 15:57:45 -04004116
Nicolas Capensf160b172014-11-26 11:58:23 -05004117 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004118
Nicolas Capensf160b172014-11-26 11:58:23 -05004119 if(context)
4120 {
4121 context->readPixels(x, y, width, height, format, type, NULL, pixels);
4122 }
John Bauman66b8ab22014-05-06 15:57:45 -04004123}
4124
4125void GL_APIENTRY glReleaseShaderCompiler(void)
4126{
Nicolas Capensf160b172014-11-26 11:58:23 -05004127 TRACE("()");
John Bauman66b8ab22014-05-06 15:57:45 -04004128
Nicolas Capensf160b172014-11-26 11:58:23 -05004129 es2::Shader::releaseCompiler();
John Bauman66b8ab22014-05-06 15:57:45 -04004130}
4131
4132void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4133{
Nicolas Capensf160b172014-11-26 11:58:23 -05004134 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4135 target, samples, internalformat, width, height);
John Bauman66b8ab22014-05-06 15:57:45 -04004136
Nicolas Capensf160b172014-11-26 11:58:23 -05004137 switch(target)
4138 {
4139 case GL_RENDERBUFFER:
4140 break;
4141 default:
4142 return error(GL_INVALID_ENUM);
4143 }
John Bauman66b8ab22014-05-06 15:57:45 -04004144
Nicolas Capensf160b172014-11-26 11:58:23 -05004145 if(!es2::IsColorRenderable(internalformat) && !es2::IsDepthRenderable(internalformat) && !es2::IsStencilRenderable(internalformat))
4146 {
4147 return error(GL_INVALID_ENUM);
4148 }
John Bauman66b8ab22014-05-06 15:57:45 -04004149
Nicolas Capensf160b172014-11-26 11:58:23 -05004150 if(width < 0 || height < 0 || samples < 0)
4151 {
4152 return error(GL_INVALID_VALUE);
4153 }
John Bauman66b8ab22014-05-06 15:57:45 -04004154
Nicolas Capensf160b172014-11-26 11:58:23 -05004155 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004156
Nicolas Capensf160b172014-11-26 11:58:23 -05004157 if(context)
4158 {
4159 if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4160 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4161 samples > es2::IMPLEMENTATION_MAX_SAMPLES)
4162 {
4163 return error(GL_INVALID_VALUE);
4164 }
John Bauman66b8ab22014-05-06 15:57:45 -04004165
Nicolas Capens7cc75e12015-01-29 14:44:24 -05004166 GLuint handle = context->getRenderbufferName();
Nicolas Capensf160b172014-11-26 11:58:23 -05004167 if(handle == 0)
4168 {
4169 return error(GL_INVALID_OPERATION);
4170 }
John Bauman66b8ab22014-05-06 15:57:45 -04004171
Nicolas Capensf160b172014-11-26 11:58:23 -05004172 switch(internalformat)
4173 {
4174 case GL_DEPTH_COMPONENT16:
4175 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, samples));
4176 break;
4177 case GL_RGBA4:
4178 case GL_RGB5_A1:
4179 case GL_RGB565:
4180 case GL_RGB8_OES:
4181 case GL_RGBA8_OES:
4182 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
4183 break;
4184 case GL_STENCIL_INDEX8:
4185 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4186 break;
4187 case GL_DEPTH24_STENCIL8_OES:
4188 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, samples));
4189 break;
4190 default:
4191 return error(GL_INVALID_ENUM);
4192 }
4193 }
John Bauman66b8ab22014-05-06 15:57:45 -04004194}
4195
4196void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4197{
Nicolas Capensf160b172014-11-26 11:58:23 -05004198 glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
John Bauman66b8ab22014-05-06 15:57:45 -04004199}
4200
4201void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)
4202{
Nicolas Capensf160b172014-11-26 11:58:23 -05004203 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
John Bauman66b8ab22014-05-06 15:57:45 -04004204
Nicolas Capensf160b172014-11-26 11:58:23 -05004205 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004206
Nicolas Capensf160b172014-11-26 11:58:23 -05004207 if(context)
4208 {
4209 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4210 }
John Bauman66b8ab22014-05-06 15:57:45 -04004211}
4212
4213void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
4214{
Nicolas Capensf160b172014-11-26 11:58:23 -05004215 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
John Bauman66b8ab22014-05-06 15:57:45 -04004216
Nicolas Capensf160b172014-11-26 11:58:23 -05004217 if(condition != GL_ALL_COMPLETED_NV)
4218 {
4219 return error(GL_INVALID_ENUM);
4220 }
John Bauman66b8ab22014-05-06 15:57:45 -04004221
Nicolas Capensf160b172014-11-26 11:58:23 -05004222 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004223
Nicolas Capensf160b172014-11-26 11:58:23 -05004224 if(context)
4225 {
4226 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004227
Nicolas Capensf160b172014-11-26 11:58:23 -05004228 if(fenceObject == NULL)
4229 {
4230 return error(GL_INVALID_OPERATION);
4231 }
John Bauman66b8ab22014-05-06 15:57:45 -04004232
Nicolas Capensf160b172014-11-26 11:58:23 -05004233 fenceObject->setFence(condition);
4234 }
John Bauman66b8ab22014-05-06 15:57:45 -04004235}
4236
4237void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
4238{
Nicolas Capensf160b172014-11-26 11:58:23 -05004239 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
John Bauman66b8ab22014-05-06 15:57:45 -04004240
Nicolas Capensf160b172014-11-26 11:58:23 -05004241 if(width < 0 || height < 0)
4242 {
4243 return error(GL_INVALID_VALUE);
4244 }
John Bauman66b8ab22014-05-06 15:57:45 -04004245
Nicolas Capensf160b172014-11-26 11:58:23 -05004246 es2::Context* context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004247
Nicolas Capensf160b172014-11-26 11:58:23 -05004248 if(context)
4249 {
4250 context->setScissorParams(x, y, width, height);
4251 }
John Bauman66b8ab22014-05-06 15:57:45 -04004252}
4253
4254void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4255{
Nicolas Capensf160b172014-11-26 11:58:23 -05004256 TRACE("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
4257 "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
4258 n, shaders, binaryformat, binary, length);
John Bauman66b8ab22014-05-06 15:57:45 -04004259
Nicolas Capensf160b172014-11-26 11:58:23 -05004260 // No binary shader formats are supported.
4261 return error(GL_INVALID_ENUM);
John Bauman66b8ab22014-05-06 15:57:45 -04004262}
4263
Nicolas Capensb0e93552014-10-28 11:54:43 -04004264void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
John Bauman66b8ab22014-05-06 15:57:45 -04004265{
Nicolas Capensf160b172014-11-26 11:58:23 -05004266 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
4267 shader, count, string, length);
John Bauman66b8ab22014-05-06 15:57:45 -04004268
Nicolas Capensf160b172014-11-26 11:58:23 -05004269 if(count < 0)
4270 {
4271 return error(GL_INVALID_VALUE);
4272 }
John Bauman66b8ab22014-05-06 15:57:45 -04004273
Nicolas Capensf160b172014-11-26 11:58:23 -05004274 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004275
Nicolas Capensf160b172014-11-26 11:58:23 -05004276 if(context)
4277 {
4278 es2::Shader *shaderObject = context->getShader(shader);
John Bauman66b8ab22014-05-06 15:57:45 -04004279
Nicolas Capensf160b172014-11-26 11:58:23 -05004280 if(!shaderObject)
4281 {
4282 if(context->getProgram(shader))
4283 {
4284 return error(GL_INVALID_OPERATION);
4285 }
4286 else
4287 {
4288 return error(GL_INVALID_VALUE);
4289 }
4290 }
John Bauman66b8ab22014-05-06 15:57:45 -04004291
Nicolas Capensf160b172014-11-26 11:58:23 -05004292 shaderObject->setSource(count, string, length);
4293 }
John Bauman66b8ab22014-05-06 15:57:45 -04004294}
4295
4296void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
4297{
Nicolas Capensf160b172014-11-26 11:58:23 -05004298 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
John Bauman66b8ab22014-05-06 15:57:45 -04004299}
4300
4301void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4302{
Nicolas Capensf160b172014-11-26 11:58:23 -05004303 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
John Bauman66b8ab22014-05-06 15:57:45 -04004304
Nicolas Capensf160b172014-11-26 11:58:23 -05004305 switch(face)
4306 {
4307 case GL_FRONT:
4308 case GL_BACK:
4309 case GL_FRONT_AND_BACK:
4310 break;
4311 default:
4312 return error(GL_INVALID_ENUM);
4313 }
John Bauman66b8ab22014-05-06 15:57:45 -04004314
Nicolas Capensf160b172014-11-26 11:58:23 -05004315 switch(func)
4316 {
4317 case GL_NEVER:
4318 case GL_ALWAYS:
4319 case GL_LESS:
4320 case GL_LEQUAL:
4321 case GL_EQUAL:
4322 case GL_GEQUAL:
4323 case GL_GREATER:
4324 case GL_NOTEQUAL:
4325 break;
4326 default:
4327 return error(GL_INVALID_ENUM);
4328 }
John Bauman66b8ab22014-05-06 15:57:45 -04004329
Nicolas Capensf160b172014-11-26 11:58:23 -05004330 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004331
Nicolas Capensf160b172014-11-26 11:58:23 -05004332 if(context)
4333 {
4334 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4335 {
4336 context->setStencilParams(func, ref, mask);
4337 }
John Bauman66b8ab22014-05-06 15:57:45 -04004338
Nicolas Capensf160b172014-11-26 11:58:23 -05004339 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4340 {
4341 context->setStencilBackParams(func, ref, mask);
4342 }
4343 }
John Bauman66b8ab22014-05-06 15:57:45 -04004344}
4345
4346void GL_APIENTRY glStencilMask(GLuint mask)
4347{
Nicolas Capensf160b172014-11-26 11:58:23 -05004348 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
John Bauman66b8ab22014-05-06 15:57:45 -04004349}
4350
4351void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
4352{
Nicolas Capensf160b172014-11-26 11:58:23 -05004353 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
John Bauman66b8ab22014-05-06 15:57:45 -04004354
Nicolas Capensf160b172014-11-26 11:58:23 -05004355 switch(face)
4356 {
4357 case GL_FRONT:
4358 case GL_BACK:
4359 case GL_FRONT_AND_BACK:
4360 break;
4361 default:
4362 return error(GL_INVALID_ENUM);
4363 }
John Bauman66b8ab22014-05-06 15:57:45 -04004364
Nicolas Capensf160b172014-11-26 11:58:23 -05004365 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004366
Nicolas Capensf160b172014-11-26 11:58:23 -05004367 if(context)
4368 {
4369 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4370 {
4371 context->setStencilWritemask(mask);
4372 }
John Bauman66b8ab22014-05-06 15:57:45 -04004373
Nicolas Capensf160b172014-11-26 11:58:23 -05004374 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4375 {
4376 context->setStencilBackWritemask(mask);
4377 }
4378 }
John Bauman66b8ab22014-05-06 15:57:45 -04004379}
4380
4381void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4382{
Nicolas Capensf160b172014-11-26 11:58:23 -05004383 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
John Bauman66b8ab22014-05-06 15:57:45 -04004384}
4385
4386void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4387{
Nicolas Capensf160b172014-11-26 11:58:23 -05004388 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4389 face, fail, zfail, zpass);
John Bauman66b8ab22014-05-06 15:57:45 -04004390
Nicolas Capensf160b172014-11-26 11:58:23 -05004391 switch(face)
4392 {
4393 case GL_FRONT:
4394 case GL_BACK:
4395 case GL_FRONT_AND_BACK:
4396 break;
4397 default:
4398 return error(GL_INVALID_ENUM);
4399 }
John Bauman66b8ab22014-05-06 15:57:45 -04004400
Nicolas Capensf160b172014-11-26 11:58:23 -05004401 switch(fail)
4402 {
4403 case GL_ZERO:
4404 case GL_KEEP:
4405 case GL_REPLACE:
4406 case GL_INCR:
4407 case GL_DECR:
4408 case GL_INVERT:
4409 case GL_INCR_WRAP:
4410 case GL_DECR_WRAP:
4411 break;
4412 default:
4413 return error(GL_INVALID_ENUM);
4414 }
John Bauman66b8ab22014-05-06 15:57:45 -04004415
Nicolas Capensf160b172014-11-26 11:58:23 -05004416 switch(zfail)
4417 {
4418 case GL_ZERO:
4419 case GL_KEEP:
4420 case GL_REPLACE:
4421 case GL_INCR:
4422 case GL_DECR:
4423 case GL_INVERT:
4424 case GL_INCR_WRAP:
4425 case GL_DECR_WRAP:
4426 break;
4427 default:
4428 return error(GL_INVALID_ENUM);
4429 }
John Bauman66b8ab22014-05-06 15:57:45 -04004430
Nicolas Capensf160b172014-11-26 11:58:23 -05004431 switch(zpass)
4432 {
4433 case GL_ZERO:
4434 case GL_KEEP:
4435 case GL_REPLACE:
4436 case GL_INCR:
4437 case GL_DECR:
4438 case GL_INVERT:
4439 case GL_INCR_WRAP:
4440 case GL_DECR_WRAP:
4441 break;
4442 default:
4443 return error(GL_INVALID_ENUM);
4444 }
John Bauman66b8ab22014-05-06 15:57:45 -04004445
Nicolas Capensf160b172014-11-26 11:58:23 -05004446 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004447
Nicolas Capensf160b172014-11-26 11:58:23 -05004448 if(context)
4449 {
4450 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4451 {
4452 context->setStencilOperations(fail, zfail, zpass);
4453 }
John Bauman66b8ab22014-05-06 15:57:45 -04004454
Nicolas Capensf160b172014-11-26 11:58:23 -05004455 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4456 {
4457 context->setStencilBackOperations(fail, zfail, zpass);
4458 }
4459 }
John Bauman66b8ab22014-05-06 15:57:45 -04004460}
4461
4462GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
4463{
Nicolas Capensf160b172014-11-26 11:58:23 -05004464 TRACE("(GLuint fence = %d)", fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004465
Nicolas Capensf160b172014-11-26 11:58:23 -05004466 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04004467
Nicolas Capensf160b172014-11-26 11:58:23 -05004468 if(context)
4469 {
4470 es2::Fence *fenceObject = context->getFence(fence);
John Bauman66b8ab22014-05-06 15:57:45 -04004471
Nicolas Capensf160b172014-11-26 11:58:23 -05004472 if(fenceObject == NULL)
4473 {
4474 return error(GL_INVALID_OPERATION, GL_TRUE);
4475 }
John Bauman66b8ab22014-05-06 15:57:45 -04004476
Nicolas Capensf160b172014-11-26 11:58:23 -05004477 return fenceObject->testFence();
4478 }
Nicolas Capens08e90f02014-11-21 12:49:12 -05004479
Nicolas Capensf160b172014-11-26 11:58:23 -05004480 return GL_TRUE;
John Bauman66b8ab22014-05-06 15:57:45 -04004481}
4482
4483void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
4484 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
4485{
Nicolas Capensf160b172014-11-26 11:58:23 -05004486 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
4487 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
4488 target, level, internalformat, width, height, border, format, type, pixels);
John Bauman66b8ab22014-05-06 15:57:45 -04004489
Nicolas Capensf160b172014-11-26 11:58:23 -05004490 if(!validImageSize(level, width, height))
4491 {
4492 return error(GL_INVALID_VALUE);
4493 }
John Bauman66b8ab22014-05-06 15:57:45 -04004494
Nicolas Capensf160b172014-11-26 11:58:23 -05004495 es2::Context *context = es2::getContext();
4496
4497 if(context)
4498 {
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05004499 if(context->getClientVersion() < 3)
4500 {
4501 if(internalformat != format)
4502 {
4503 return error(GL_INVALID_OPERATION);
4504 }
4505 }
4506
4507 switch(format)
4508 {
4509 case GL_ALPHA:
4510 case GL_LUMINANCE:
4511 case GL_LUMINANCE_ALPHA:
4512 switch(type)
4513 {
4514 case GL_UNSIGNED_BYTE:
4515 case GL_FLOAT:
4516 case GL_HALF_FLOAT_OES:
4517 break;
4518 default:
4519 return error(GL_INVALID_ENUM);
4520 }
4521 break;
Alexis Hetued306182015-04-02 12:02:28 -04004522 case GL_RED:
4523 switch(internalformat)
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05004524 {
Alexis Hetued306182015-04-02 12:02:28 -04004525 case GL_R8:
4526 switch(type)
4527 {
4528 case GL_UNSIGNED_BYTE:
4529 break;
4530 default:
4531 return error(GL_INVALID_ENUM);
4532 }
4533 break;
4534 case GL_R8_SNORM:
4535 switch(type)
4536 {
4537 case GL_BYTE:
4538 break;
4539 default:
4540 return error(GL_INVALID_ENUM);
4541 }
4542 break;
4543 case GL_R16F:
4544 switch(type)
4545 {
4546 case GL_FLOAT:
4547 case GL_HALF_FLOAT:
4548 break;
4549 default:
4550 return error(GL_INVALID_ENUM);
4551 }
4552 break;
4553 case GL_R32F:
4554 switch(type)
4555 {
4556 case GL_FLOAT:
4557 break;
4558 default:
4559 return error(GL_INVALID_ENUM);
4560 }
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05004561 break;
4562 default:
Alexis Hetued306182015-04-02 12:02:28 -04004563 return error(GL_INVALID_VALUE);
4564 }
4565 break;
4566 case GL_RED_INTEGER:
4567 switch(internalformat)
4568 {
4569 case GL_R8UI:
4570 switch(type)
4571 {
4572 case GL_UNSIGNED_BYTE:
4573 break;
4574 default:
4575 return error(GL_INVALID_ENUM);
4576 }
4577 break;
4578 case GL_R8I:
4579 switch(type)
4580 {
4581 case GL_BYTE:
4582 break;
4583 default:
4584 return error(GL_INVALID_ENUM);
4585 }
4586 break;
4587 case GL_R16UI:
4588 switch(type)
4589 {
4590 case GL_UNSIGNED_SHORT:
4591 break;
4592 default:
4593 return error(GL_INVALID_ENUM);
4594 }
4595 break;
4596 case GL_R16I:
4597 switch(type)
4598 {
4599 case GL_SHORT:
4600 break;
4601 default:
4602 return error(GL_INVALID_ENUM);
4603 }
4604 break;
4605 case GL_R32UI:
4606 switch(type)
4607 {
4608 case GL_UNSIGNED_INT:
4609 break;
4610 default:
4611 return error(GL_INVALID_ENUM);
4612 }
4613 break;
4614 case GL_R32I:
4615 switch(type)
4616 {
4617 case GL_INT:
4618 break;
4619 default:
4620 return error(GL_INVALID_ENUM);
4621 }
4622 break;
4623 default:
4624 return error(GL_INVALID_VALUE);
4625 }
4626 break;
4627 case GL_RG_INTEGER:
4628 switch(internalformat)
4629 {
4630 case GL_RG8UI:
4631 switch(type)
4632 {
4633 case GL_UNSIGNED_BYTE:
4634 break;
4635 default:
4636 return error(GL_INVALID_ENUM);
4637 }
4638 break;
4639 case GL_RG8I:
4640 switch(type)
4641 {
4642 case GL_BYTE:
4643 break;
4644 default:
4645 return error(GL_INVALID_ENUM);
4646 }
4647 break;
4648 case GL_RG16UI:
4649 switch(type)
4650 {
4651 case GL_UNSIGNED_SHORT:
4652 break;
4653 default:
4654 return error(GL_INVALID_ENUM);
4655 }
4656 break;
4657 case GL_RG16I:
4658 switch(type)
4659 {
4660 case GL_SHORT:
4661 break;
4662 default:
4663 return error(GL_INVALID_ENUM);
4664 }
4665 break;
4666 case GL_RG32UI:
4667 switch(type)
4668 {
4669 case GL_UNSIGNED_INT:
4670 break;
4671 default:
4672 return error(GL_INVALID_ENUM);
4673 }
4674 break;
4675 case GL_RG32I:
4676 switch(type)
4677 {
4678 case GL_INT:
4679 break;
4680 default:
4681 return error(GL_INVALID_ENUM);
4682 }
4683 break;
4684 default:
4685 return error(GL_INVALID_VALUE);
4686 }
4687 break;
4688 case GL_RGB_INTEGER:
4689 switch(internalformat)
4690 {
4691 case GL_RGB8UI:
4692 switch(type)
4693 {
4694 case GL_UNSIGNED_BYTE:
4695 break;
4696 default:
4697 return error(GL_INVALID_ENUM);
4698 }
4699 break;
4700 case GL_RGB8I:
4701 switch(type)
4702 {
4703 case GL_BYTE:
4704 break;
4705 default:
4706 return error(GL_INVALID_ENUM);
4707 }
4708 break;
4709 case GL_RGB16UI:
4710 switch(type)
4711 {
4712 case GL_UNSIGNED_SHORT:
4713 break;
4714 default:
4715 return error(GL_INVALID_ENUM);
4716 }
4717 break;
4718 case GL_RGB16I:
4719 switch(type)
4720 {
4721 case GL_SHORT:
4722 break;
4723 default:
4724 return error(GL_INVALID_ENUM);
4725 }
4726 break;
4727 case GL_RGB32UI:
4728 switch(type)
4729 {
4730 case GL_UNSIGNED_INT:
4731 break;
4732 default:
4733 return error(GL_INVALID_ENUM);
4734 }
4735 break;
4736 case GL_RGB32I:
4737 switch(type)
4738 {
4739 case GL_INT:
4740 break;
4741 default:
4742 return error(GL_INVALID_ENUM);
4743 }
4744 break;
4745 default:
4746 return error(GL_INVALID_VALUE);
4747 }
4748 break;
4749 case GL_RGBA_INTEGER:
4750 switch(internalformat)
4751 {
4752 case GL_RGBA8UI:
4753 switch(type)
4754 {
4755 case GL_UNSIGNED_BYTE:
4756 break;
4757 default:
4758 return error(GL_INVALID_ENUM);
4759 }
4760 break;
4761 case GL_RGBA8I:
4762 switch(type)
4763 {
4764 case GL_BYTE:
4765 break;
4766 default:
4767 return error(GL_INVALID_ENUM);
4768 }
4769 break;
4770 case GL_RGB10_A2UI:
4771 switch(type)
4772 {
4773 case GL_UNSIGNED_INT_2_10_10_10_REV:
4774 break;
4775 default:
4776 return error(GL_INVALID_ENUM);
4777 }
4778 break;
4779 case GL_RGBA16UI:
4780 switch(type)
4781 {
4782 case GL_UNSIGNED_SHORT:
4783 break;
4784 default:
4785 return error(GL_INVALID_ENUM);
4786 }
4787 break;
4788 case GL_RGBA16I:
4789 switch(type)
4790 {
4791 case GL_SHORT:
4792 break;
4793 default:
4794 return error(GL_INVALID_ENUM);
4795 }
4796 break;
4797 case GL_RGBA32UI:
4798 switch(type)
4799 {
4800 case GL_INT:
4801 break;
4802 default:
4803 return error(GL_INVALID_ENUM);
4804 }
4805 break;
4806 case GL_RGBA32I:
4807 switch(type)
4808 {
4809 case GL_UNSIGNED_INT:
4810 break;
4811 default:
4812 return error(GL_INVALID_ENUM);
4813 }
4814 break;
4815 default:
4816 return error(GL_INVALID_VALUE);
4817 }
4818 break;
4819 case GL_RG:
4820 switch(internalformat)
4821 {
4822 case GL_RG8:
4823 switch(type)
4824 {
4825 case GL_UNSIGNED_BYTE:
4826 break;
4827 default:
4828 return error(GL_INVALID_ENUM);
4829 }
4830 break;
4831 case GL_RG8_SNORM:
4832 switch(type)
4833 {
4834 case GL_BYTE:
4835 break;
4836 default:
4837 return error(GL_INVALID_ENUM);
4838 }
4839 break;
4840 case GL_RG16F:
4841 switch(type)
4842 {
4843 case GL_FLOAT:
4844 case GL_HALF_FLOAT:
4845 break;
4846 default:
4847 return error(GL_INVALID_ENUM);
4848 }
4849 break;
4850 case GL_RG32F:
4851 switch(type)
4852 {
4853 case GL_FLOAT:
4854 break;
4855 default:
4856 return error(GL_INVALID_ENUM);
4857 }
4858 break;
4859 default:
4860 return error(GL_INVALID_VALUE);
4861 }
4862 break;
4863 case GL_RGB:
4864 switch(internalformat)
4865 {
4866 case GL_RGB:
4867 switch(type)
4868 {
4869 case GL_UNSIGNED_BYTE:
4870 case GL_UNSIGNED_SHORT_5_6_5:
4871 case GL_FLOAT:
4872 case GL_HALF_FLOAT_OES:
4873 break;
4874 default:
4875 return error(GL_INVALID_ENUM);
4876 }
4877 break;
4878 case GL_RGB8:
4879 switch(type)
4880 {
4881 case GL_UNSIGNED_BYTE:
4882 break;
4883 default:
4884 return error(GL_INVALID_ENUM);
4885 }
4886 break;
4887 case GL_SRGB8:
4888 switch(type)
4889 {
4890 case GL_UNSIGNED_BYTE:
4891 break;
4892 default:
4893 return error(GL_INVALID_ENUM);
4894 }
4895 break;
4896 case GL_RGB565:
4897 switch(type)
4898 {
4899 case GL_UNSIGNED_BYTE:
4900 case GL_UNSIGNED_SHORT_5_6_5:
4901 break;
4902 default:
4903 return error(GL_INVALID_ENUM);
4904 }
4905 break;
4906 case GL_RGB8_SNORM:
4907 switch(type)
4908 {
4909 case GL_BYTE:
4910 break;
4911 default:
4912 return error(GL_INVALID_ENUM);
4913 }
4914 break;
4915 case GL_R11F_G11F_B10F:
4916 switch(type)
4917 {
4918 case GL_UNSIGNED_INT_10F_11F_11F_REV:
4919 case GL_FLOAT:
4920 case GL_HALF_FLOAT:
4921 break;
4922 default:
4923 return error(GL_INVALID_ENUM);
4924 }
4925 break;
4926 case GL_RGB9_E5:
4927 switch(type)
4928 {
4929 case GL_UNSIGNED_INT_5_9_9_9_REV:
4930 case GL_FLOAT:
4931 case GL_HALF_FLOAT:
4932 break;
4933 default:
4934 return error(GL_INVALID_ENUM);
4935 }
4936 break;
4937 case GL_RGB16F:
4938 switch(type)
4939 {
4940 case GL_FLOAT:
4941 case GL_HALF_FLOAT:
4942 break;
4943 default:
4944 return error(GL_INVALID_ENUM);
4945 }
4946 break;
4947 case GL_RGB32F:
4948 switch(type)
4949 {
4950 case GL_FLOAT:
4951 break;
4952 default:
4953 return error(GL_INVALID_ENUM);
4954 }
4955 break;
4956 default:
4957 return error(GL_INVALID_VALUE);
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05004958 }
4959 break;
4960 case GL_RGBA:
Alexis Hetued306182015-04-02 12:02:28 -04004961 switch(internalformat)
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05004962 {
Alexis Hetued306182015-04-02 12:02:28 -04004963 case GL_RGBA:
4964 switch(type)
4965 {
4966 case GL_UNSIGNED_BYTE:
4967 case GL_UNSIGNED_SHORT_4_4_4_4:
4968 case GL_UNSIGNED_SHORT_5_5_5_1:
4969 case GL_FLOAT:
4970 case GL_HALF_FLOAT_OES:
4971 break;
4972 default:
4973 return error(GL_INVALID_ENUM);
4974 }
4975 break;
4976 case GL_RGBA8:
4977 switch(type)
4978 {
4979 case GL_UNSIGNED_BYTE:
4980 break;
4981 default:
4982 return error(GL_INVALID_ENUM);
4983 }
4984 break;
4985 case GL_SRGB8_ALPHA8:
4986 switch(type)
4987 {
4988 case GL_UNSIGNED_BYTE:
4989 break;
4990 default:
4991 return error(GL_INVALID_ENUM);
4992 }
4993 break;
4994 case GL_RGB5_A1:
4995 switch(type)
4996 {
4997 case GL_UNSIGNED_BYTE:
4998 case GL_UNSIGNED_SHORT_5_5_5_1:
4999 case GL_UNSIGNED_INT_2_10_10_10_REV:
5000 break;
5001 default:
5002 return error(GL_INVALID_ENUM);
5003 }
5004 break;
5005 case GL_RGBA8_SNORM:
5006 switch(type)
5007 {
5008 case GL_BYTE:
5009 break;
5010 default:
5011 return error(GL_INVALID_ENUM);
5012 }
5013 break;
5014 case GL_RGBA4:
5015 switch(type)
5016 {
5017 case GL_UNSIGNED_BYTE:
5018 case GL_UNSIGNED_SHORT_4_4_4_4:
5019 break;
5020 default:
5021 return error(GL_INVALID_ENUM);
5022 }
5023 break;
5024 case GL_RGB10_A2:
5025 switch(type)
5026 {
5027 case GL_UNSIGNED_INT_2_10_10_10_REV:
5028 break;
5029 default:
5030 return error(GL_INVALID_ENUM);
5031 }
5032 break;
5033 case GL_RGBA16F:
5034 switch(type)
5035 {
5036 case GL_FLOAT:
5037 case GL_HALF_FLOAT:
5038 break;
5039 default:
5040 return error(GL_INVALID_ENUM);
5041 }
5042 break;
5043 case GL_RGBA32F:
5044 switch(type)
5045 {
5046 case GL_FLOAT:
5047 break;
5048 default:
5049 return error(GL_INVALID_ENUM);
5050 }
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005051 break;
5052 default:
Alexis Hetued306182015-04-02 12:02:28 -04005053 return error(GL_INVALID_VALUE);
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005054 }
5055 break;
5056 case GL_BGRA_EXT:
5057 switch(type)
5058 {
5059 case GL_UNSIGNED_BYTE:
5060 break;
5061 default:
5062 return error(GL_INVALID_ENUM);
5063 }
5064 break;
5065 case GL_ETC1_RGB8_OES:
5066 return error(GL_INVALID_OPERATION);
5067 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
5068 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
5069 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
5070 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
5071 if(S3TC_SUPPORT)
5072 {
5073 return error(GL_INVALID_OPERATION);
5074 }
5075 else
5076 {
5077 return error(GL_INVALID_ENUM);
5078 }
5079 case GL_DEPTH_COMPONENT:
Alexis Hetued306182015-04-02 12:02:28 -04005080 switch(internalformat)
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005081 {
Alexis Hetued306182015-04-02 12:02:28 -04005082 case GL_DEPTH_COMPONENT:
5083 case GL_DEPTH_COMPONENT16:
5084 switch(type)
5085 {
5086 case GL_UNSIGNED_SHORT:
5087 case GL_UNSIGNED_INT:
5088 break;
5089 default:
5090 return error(GL_INVALID_ENUM);
5091 }
5092 break;
5093 case GL_DEPTH_COMPONENT24:
5094 switch(type)
5095 {
5096 case GL_UNSIGNED_INT:
5097 break;
5098 default:
5099 return error(GL_INVALID_ENUM);
5100 }
5101 break;
5102 case GL_DEPTH_COMPONENT32F:
5103 switch(type)
5104 {
5105 case GL_UNSIGNED_INT:
5106 break;
5107 default:
5108 return error(GL_INVALID_ENUM);
5109 }
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005110 break;
5111 default:
Alexis Hetued306182015-04-02 12:02:28 -04005112 return error(GL_INVALID_VALUE);
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005113 }
5114 break;
5115 case GL_DEPTH_STENCIL_OES:
Alexis Hetued306182015-04-02 12:02:28 -04005116 switch(internalformat)
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005117 {
Alexis Hetued306182015-04-02 12:02:28 -04005118 case GL_DEPTH_STENCIL_OES:
5119 case GL_DEPTH24_STENCIL8:
5120 switch(type)
5121 {
5122 case GL_UNSIGNED_INT_24_8_OES:
5123 break;
5124 default:
5125 return error(GL_INVALID_ENUM);
5126 }
5127 break;
5128 case GL_DEPTH32F_STENCIL8:
5129 switch(type)
5130 {
5131 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
5132 break;
5133 default:
5134 return error(GL_INVALID_ENUM);
5135 }
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005136 break;
5137 default:
Alexis Hetued306182015-04-02 12:02:28 -04005138 return error(GL_INVALID_VALUE);
Nicolas Capensb97ad2e2015-02-11 17:40:30 -05005139 }
5140 break;
5141 default:
5142 return error(GL_INVALID_VALUE);
5143 }
5144
5145 if(border != 0)
5146 {
5147 return error(GL_INVALID_VALUE);
5148 }
5149
Nicolas Capensf160b172014-11-26 11:58:23 -05005150 switch(target)
5151 {
Nicolas Capens22658242014-11-29 00:31:41 -05005152 case GL_TEXTURE_2D:
Nicolas Capensf160b172014-11-26 11:58:23 -05005153 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
5154 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
John Bauman66b8ab22014-05-06 15:57:45 -04005155 {
Nicolas Capensf160b172014-11-26 11:58:23 -05005156 return error(GL_INVALID_VALUE);
John Bauman66b8ab22014-05-06 15:57:45 -04005157 }
5158 break;
Nicolas Capens22658242014-11-29 00:31:41 -05005159 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
5160 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
5161 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
5162 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
5163 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
5164 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Nicolas Capensf160b172014-11-26 11:58:23 -05005165 if(width != height)
John Bauman66b8ab22014-05-06 15:57:45 -04005166 {
Nicolas Capensf160b172014-11-26 11:58:23 -05005167 return error(GL_INVALID_VALUE);
5168 }
5169
5170 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
5171 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
5172 {
5173 return error(GL_INVALID_VALUE);
John Bauman66b8ab22014-05-06 15:57:45 -04005174 }
5175 break;
Nicolas Capens22658242014-11-29 00:31:41 -05005176 default:
Nicolas Capensf160b172014-11-26 11:58:23 -05005177 return error(GL_INVALID_ENUM);
5178 }
John Bauman66b8ab22014-05-06 15:57:45 -04005179
Nicolas Capensf160b172014-11-26 11:58:23 -05005180 if(target == GL_TEXTURE_2D)
5181 {
5182 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04005183
Nicolas Capensf160b172014-11-26 11:58:23 -05005184 if(!texture)
5185 {
5186 return error(GL_INVALID_OPERATION);
5187 }
John Bauman66b8ab22014-05-06 15:57:45 -04005188
Nicolas Capensf160b172014-11-26 11:58:23 -05005189 texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels);
5190 }
5191 else
5192 {
5193 es2::TextureCubeMap *texture = context->getTextureCubeMap();
John Bauman66b8ab22014-05-06 15:57:45 -04005194
Nicolas Capensf160b172014-11-26 11:58:23 -05005195 if(!texture)
5196 {
5197 return error(GL_INVALID_OPERATION);
5198 }
Nicolas Capens08e90f02014-11-21 12:49:12 -05005199
Nicolas Capensf160b172014-11-26 11:58:23 -05005200 texture->setImage(target, level, width, height, format, type, context->getUnpackAlignment(), pixels);
5201 }
5202 }
John Bauman66b8ab22014-05-06 15:57:45 -04005203}
5204
5205void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
5206{
Nicolas Capensf160b172014-11-26 11:58:23 -05005207 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
John Bauman66b8ab22014-05-06 15:57:45 -04005208
Nicolas Capensf160b172014-11-26 11:58:23 -05005209 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005210
Nicolas Capensf160b172014-11-26 11:58:23 -05005211 if(context)
5212 {
5213 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04005214
Alexis Hetued306182015-04-02 12:02:28 -04005215 egl::GLint clientVersion = context->getClientVersion();
5216
Nicolas Capensf160b172014-11-26 11:58:23 -05005217 switch(target)
5218 {
5219 case GL_TEXTURE_2D:
5220 texture = context->getTexture2D();
5221 break;
Alexis Hetued306182015-04-02 12:02:28 -04005222 case GL_TEXTURE_2D_ARRAY:
5223 if(clientVersion < 3)
5224 {
5225 return error(GL_INVALID_ENUM);
5226 }
5227 else
5228 {
5229 UNIMPLEMENTED();
5230 texture = context->getTexture3D();
5231 break;
5232 }
Alexis Hetub027aa92015-01-19 15:56:12 -05005233 case GL_TEXTURE_3D_OES:
5234 texture = context->getTexture3D();
5235 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005236 case GL_TEXTURE_CUBE_MAP:
5237 texture = context->getTextureCubeMap();
5238 break;
5239 case GL_TEXTURE_EXTERNAL_OES:
5240 texture = context->getTextureExternal();
5241 break;
5242 default:
5243 return error(GL_INVALID_ENUM);
5244 }
John Bauman66b8ab22014-05-06 15:57:45 -04005245
Nicolas Capensf160b172014-11-26 11:58:23 -05005246 switch(pname)
5247 {
5248 case GL_TEXTURE_WRAP_S:
5249 if(!texture->setWrapS((GLenum)param))
5250 {
5251 return error(GL_INVALID_ENUM);
5252 }
5253 break;
5254 case GL_TEXTURE_WRAP_T:
5255 if(!texture->setWrapT((GLenum)param))
5256 {
5257 return error(GL_INVALID_ENUM);
5258 }
5259 break;
Alexis Hetub027aa92015-01-19 15:56:12 -05005260 case GL_TEXTURE_WRAP_R_OES:
5261 if(!texture->setWrapR((GLenum)param))
5262 {
5263 return error(GL_INVALID_ENUM);
5264 }
5265 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005266 case GL_TEXTURE_MIN_FILTER:
5267 if(!texture->setMinFilter((GLenum)param))
5268 {
5269 return error(GL_INVALID_ENUM);
5270 }
5271 break;
5272 case GL_TEXTURE_MAG_FILTER:
5273 if(!texture->setMagFilter((GLenum)param))
5274 {
5275 return error(GL_INVALID_ENUM);
5276 }
5277 break;
5278 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5279 if(!texture->setMaxAnisotropy(param))
5280 {
5281 return error(GL_INVALID_VALUE);
5282 }
5283 break;
Alexis Hetued306182015-04-02 12:02:28 -04005284 case GL_TEXTURE_BASE_LEVEL:
5285 if(clientVersion < 3 || !texture->setBaseLevel((GLint)param))
5286 {
5287 return error(GL_INVALID_VALUE);
5288 }
5289 break;
5290 case GL_TEXTURE_COMPARE_FUNC:
5291 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5292 {
5293 return error(GL_INVALID_VALUE);
5294 }
5295 break;
5296 case GL_TEXTURE_COMPARE_MODE:
5297 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5298 {
5299 return error(GL_INVALID_VALUE);
5300 }
5301 break;
5302 case GL_TEXTURE_IMMUTABLE_FORMAT:
5303 if(clientVersion < 3 || !texture->setCompareMode((GLboolean)param))
5304 {
5305 return error(GL_INVALID_VALUE);
5306 }
5307 break;
5308 case GL_TEXTURE_MAX_LEVEL:
5309 if(clientVersion < 3 || !texture->setMaxLevel((GLint)param))
5310 {
5311 return error(GL_INVALID_VALUE);
5312 }
5313 break;
5314 case GL_TEXTURE_MAX_LOD:
5315 if(clientVersion < 3 || !texture->setMaxLOD(param))
5316 {
5317 return error(GL_INVALID_VALUE);
5318 }
5319 break;
5320 case GL_TEXTURE_MIN_LOD:
5321 if(clientVersion < 3 || !texture->setMinLOD(param))
5322 {
5323 return error(GL_INVALID_VALUE);
5324 }
5325 break;
5326 case GL_TEXTURE_SWIZZLE_R:
5327 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5328 {
5329 return error(GL_INVALID_VALUE);
5330 }
5331 break;
5332 case GL_TEXTURE_SWIZZLE_G:
5333 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5334 {
5335 return error(GL_INVALID_VALUE);
5336 }
5337 break;
5338 case GL_TEXTURE_SWIZZLE_B:
5339 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5340 {
5341 return error(GL_INVALID_VALUE);
5342 }
5343 break;
5344 case GL_TEXTURE_SWIZZLE_A:
5345 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5346 {
5347 return error(GL_INVALID_VALUE);
5348 }
5349 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005350 default:
5351 return error(GL_INVALID_ENUM);
5352 }
5353 }
John Bauman66b8ab22014-05-06 15:57:45 -04005354}
5355
5356void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
5357{
Nicolas Capensf160b172014-11-26 11:58:23 -05005358 glTexParameterf(target, pname, *params);
John Bauman66b8ab22014-05-06 15:57:45 -04005359}
5360
5361void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
5362{
Nicolas Capensf160b172014-11-26 11:58:23 -05005363 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
John Bauman66b8ab22014-05-06 15:57:45 -04005364
Nicolas Capensf160b172014-11-26 11:58:23 -05005365 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005366
Nicolas Capensf160b172014-11-26 11:58:23 -05005367 if(context)
5368 {
5369 es2::Texture *texture;
John Bauman66b8ab22014-05-06 15:57:45 -04005370
Alexis Hetued306182015-04-02 12:02:28 -04005371 egl::GLint clientVersion = context->getClientVersion();
5372
Nicolas Capensf160b172014-11-26 11:58:23 -05005373 switch(target)
5374 {
5375 case GL_TEXTURE_2D:
5376 texture = context->getTexture2D();
5377 break;
Alexis Hetued306182015-04-02 12:02:28 -04005378 case GL_TEXTURE_2D_ARRAY:
5379 if(clientVersion < 3)
5380 {
5381 return error(GL_INVALID_ENUM);
5382 }
5383 else
5384 {
5385 UNIMPLEMENTED();
5386 texture = context->getTexture3D();
5387 break;
5388 }
Alexis Hetub027aa92015-01-19 15:56:12 -05005389 case GL_TEXTURE_3D_OES:
5390 texture = context->getTexture3D();
5391 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005392 case GL_TEXTURE_CUBE_MAP:
5393 texture = context->getTextureCubeMap();
5394 break;
5395 case GL_TEXTURE_EXTERNAL_OES:
Alexis Hetuf7be67f2015-02-11 16:11:07 -05005396 texture = context->getTextureExternal();
5397 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005398 default:
5399 return error(GL_INVALID_ENUM);
5400 }
John Bauman66b8ab22014-05-06 15:57:45 -04005401
Nicolas Capensf160b172014-11-26 11:58:23 -05005402 switch(pname)
5403 {
5404 case GL_TEXTURE_WRAP_S:
5405 if(!texture->setWrapS((GLenum)param))
5406 {
5407 return error(GL_INVALID_ENUM);
5408 }
5409 break;
5410 case GL_TEXTURE_WRAP_T:
5411 if(!texture->setWrapT((GLenum)param))
5412 {
5413 return error(GL_INVALID_ENUM);
5414 }
5415 break;
Alexis Hetub027aa92015-01-19 15:56:12 -05005416 case GL_TEXTURE_WRAP_R_OES:
5417 if(!texture->setWrapR((GLenum)param))
5418 {
5419 return error(GL_INVALID_ENUM);
5420 }
5421 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005422 case GL_TEXTURE_MIN_FILTER:
5423 if(!texture->setMinFilter((GLenum)param))
5424 {
5425 return error(GL_INVALID_ENUM);
5426 }
5427 break;
5428 case GL_TEXTURE_MAG_FILTER:
5429 if(!texture->setMagFilter((GLenum)param))
5430 {
5431 return error(GL_INVALID_ENUM);
5432 }
5433 break;
5434 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5435 if(!texture->setMaxAnisotropy((GLfloat)param))
5436 {
5437 return error(GL_INVALID_VALUE);
5438 }
5439 break;
Alexis Hetued306182015-04-02 12:02:28 -04005440 case GL_TEXTURE_BASE_LEVEL:
5441 if(clientVersion < 3 || !texture->setBaseLevel(param))
5442 {
5443 return error(GL_INVALID_VALUE);
5444 }
5445 break;
5446 case GL_TEXTURE_COMPARE_FUNC:
5447 if(clientVersion < 3 || !texture->setCompareFunc((GLenum)param))
5448 {
5449 return error(GL_INVALID_VALUE);
5450 }
5451 break;
5452 case GL_TEXTURE_COMPARE_MODE:
5453 if(clientVersion < 3 || !texture->setCompareMode((GLenum)param))
5454 {
5455 return error(GL_INVALID_VALUE);
5456 }
5457 case GL_TEXTURE_IMMUTABLE_FORMAT:
5458 if(clientVersion < 3 || !texture->setCompareMode((GLboolean)param))
5459 {
5460 return error(GL_INVALID_VALUE);
5461 }
5462 break;
5463 case GL_TEXTURE_MAX_LEVEL:
5464 if(clientVersion < 3 || !texture->setMaxLevel(param))
5465 {
5466 return error(GL_INVALID_VALUE);
5467 }
5468 break;
5469 case GL_TEXTURE_MAX_LOD:
5470 if(clientVersion < 3 || !texture->setMaxLOD((GLfloat)param))
5471 {
5472 return error(GL_INVALID_VALUE);
5473 }
5474 break;
5475 case GL_TEXTURE_MIN_LOD:
5476 if(clientVersion < 3 || !texture->setMinLOD((GLfloat)param))
5477 {
5478 return error(GL_INVALID_VALUE);
5479 }
5480 break;
5481 case GL_TEXTURE_SWIZZLE_R:
5482 if(clientVersion < 3 || !texture->setSwizzleR((GLenum)param))
5483 {
5484 return error(GL_INVALID_VALUE);
5485 }
5486 break;
5487 case GL_TEXTURE_SWIZZLE_G:
5488 if(clientVersion < 3 || !texture->setSwizzleG((GLenum)param))
5489 {
5490 return error(GL_INVALID_VALUE);
5491 }
5492 break;
5493 case GL_TEXTURE_SWIZZLE_B:
5494 if(clientVersion < 3 || !texture->setSwizzleB((GLenum)param))
5495 {
5496 return error(GL_INVALID_VALUE);
5497 }
5498 break;
5499 case GL_TEXTURE_SWIZZLE_A:
5500 if(clientVersion < 3 || !texture->setSwizzleA((GLenum)param))
5501 {
5502 return error(GL_INVALID_VALUE);
5503 }
5504 break;
Nicolas Capensf160b172014-11-26 11:58:23 -05005505 default:
5506 return error(GL_INVALID_ENUM);
5507 }
5508 }
John Bauman66b8ab22014-05-06 15:57:45 -04005509}
5510
5511void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
5512{
Nicolas Capensf160b172014-11-26 11:58:23 -05005513 glTexParameteri(target, pname, *params);
John Bauman66b8ab22014-05-06 15:57:45 -04005514}
5515
5516void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Nicolas Capensf160b172014-11-26 11:58:23 -05005517 GLenum format, GLenum type, const GLvoid* pixels)
John Bauman66b8ab22014-05-06 15:57:45 -04005518{
Nicolas Capensf160b172014-11-26 11:58:23 -05005519 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5520 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
5521 "const GLvoid* pixels = 0x%0.8p)",
5522 target, level, xoffset, yoffset, width, height, format, type, pixels);
John Bauman66b8ab22014-05-06 15:57:45 -04005523
Nicolas Capensf160b172014-11-26 11:58:23 -05005524 if(!es2::IsTextureTarget(target))
5525 {
5526 return error(GL_INVALID_ENUM);
5527 }
John Bauman66b8ab22014-05-06 15:57:45 -04005528
Nicolas Capensf160b172014-11-26 11:58:23 -05005529 if(level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
5530 {
5531 return error(GL_INVALID_VALUE);
5532 }
John Bauman66b8ab22014-05-06 15:57:45 -04005533
Nicolas Capensf160b172014-11-26 11:58:23 -05005534 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
5535 {
5536 return error(GL_INVALID_VALUE);
5537 }
John Bauman66b8ab22014-05-06 15:57:45 -04005538
Nicolas Capensf160b172014-11-26 11:58:23 -05005539 if(!es2::CheckTextureFormatType(format, type))
5540 {
5541 return error(GL_INVALID_ENUM);
5542 }
John Bauman66b8ab22014-05-06 15:57:45 -04005543
Nicolas Capensf160b172014-11-26 11:58:23 -05005544 if(width == 0 || height == 0 || pixels == NULL)
5545 {
5546 return;
5547 }
John Bauman66b8ab22014-05-06 15:57:45 -04005548
Nicolas Capensf160b172014-11-26 11:58:23 -05005549 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005550
Nicolas Capensf160b172014-11-26 11:58:23 -05005551 if(context)
5552 {
Alexis Hetub027aa92015-01-19 15:56:12 -05005553 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
Nicolas Capensf160b172014-11-26 11:58:23 -05005554 {
5555 return error(GL_INVALID_VALUE);
5556 }
John Bauman66b8ab22014-05-06 15:57:45 -04005557
Nicolas Capensf160b172014-11-26 11:58:23 -05005558 if(target == GL_TEXTURE_2D)
5559 {
5560 es2::Texture2D *texture = context->getTexture2D();
John Bauman66b8ab22014-05-06 15:57:45 -04005561
Nicolas Capensf160b172014-11-26 11:58:23 -05005562 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
5563 {
5564 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
5565 }
5566 }
5567 else if(es2::IsCubemapTextureTarget(target))
5568 {
5569 es2::TextureCubeMap *texture = context->getTextureCubeMap();
Nicolas Capens08e90f02014-11-21 12:49:12 -05005570
Nicolas Capensf160b172014-11-26 11:58:23 -05005571 if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture))
5572 {
5573 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels);
5574 }
5575 }
5576 else
5577 {
5578 UNREACHABLE();
5579 }
5580 }
John Bauman66b8ab22014-05-06 15:57:45 -04005581}
5582
5583void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
5584{
Nicolas Capensf160b172014-11-26 11:58:23 -05005585 glUniform1fv(location, 1, &x);
John Bauman66b8ab22014-05-06 15:57:45 -04005586}
5587
5588void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
5589{
Nicolas Capensf160b172014-11-26 11:58:23 -05005590 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005591
Nicolas Capensf160b172014-11-26 11:58:23 -05005592 if(count < 0)
5593 {
5594 return error(GL_INVALID_VALUE);
5595 }
John Bauman66b8ab22014-05-06 15:57:45 -04005596
Nicolas Capensf160b172014-11-26 11:58:23 -05005597 if(location == -1)
5598 {
5599 return;
5600 }
John Bauman66b8ab22014-05-06 15:57:45 -04005601
Nicolas Capensf160b172014-11-26 11:58:23 -05005602 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005603
Nicolas Capensf160b172014-11-26 11:58:23 -05005604 if(context)
5605 {
5606 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005607
Nicolas Capensf160b172014-11-26 11:58:23 -05005608 if(!program)
5609 {
5610 return error(GL_INVALID_OPERATION);
5611 }
John Bauman66b8ab22014-05-06 15:57:45 -04005612
Nicolas Capensf160b172014-11-26 11:58:23 -05005613 if(!program->setUniform1fv(location, count, v))
5614 {
5615 return error(GL_INVALID_OPERATION);
5616 }
5617 }
John Bauman66b8ab22014-05-06 15:57:45 -04005618}
5619
5620void GL_APIENTRY glUniform1i(GLint location, GLint x)
5621{
Nicolas Capensf160b172014-11-26 11:58:23 -05005622 glUniform1iv(location, 1, &x);
John Bauman66b8ab22014-05-06 15:57:45 -04005623}
5624
5625void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
5626{
Nicolas Capensf160b172014-11-26 11:58:23 -05005627 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005628
Nicolas Capensf160b172014-11-26 11:58:23 -05005629 if(count < 0)
5630 {
5631 return error(GL_INVALID_VALUE);
5632 }
John Bauman66b8ab22014-05-06 15:57:45 -04005633
Nicolas Capensf160b172014-11-26 11:58:23 -05005634 if(location == -1)
5635 {
5636 return;
5637 }
John Bauman66b8ab22014-05-06 15:57:45 -04005638
Nicolas Capensf160b172014-11-26 11:58:23 -05005639 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005640
Nicolas Capensf160b172014-11-26 11:58:23 -05005641 if(context)
5642 {
5643 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005644
Nicolas Capensf160b172014-11-26 11:58:23 -05005645 if(!program)
5646 {
5647 return error(GL_INVALID_OPERATION);
5648 }
John Bauman66b8ab22014-05-06 15:57:45 -04005649
Nicolas Capensf160b172014-11-26 11:58:23 -05005650 if(!program->setUniform1iv(location, count, v))
5651 {
5652 return error(GL_INVALID_OPERATION);
5653 }
5654 }
John Bauman66b8ab22014-05-06 15:57:45 -04005655}
5656
5657void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
5658{
Nicolas Capensf160b172014-11-26 11:58:23 -05005659 GLfloat xy[2] = {x, y};
John Bauman66b8ab22014-05-06 15:57:45 -04005660
Nicolas Capensf160b172014-11-26 11:58:23 -05005661 glUniform2fv(location, 1, (GLfloat*)&xy);
John Bauman66b8ab22014-05-06 15:57:45 -04005662}
5663
5664void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
5665{
Nicolas Capensf160b172014-11-26 11:58:23 -05005666 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005667
Nicolas Capensf160b172014-11-26 11:58:23 -05005668 if(count < 0)
5669 {
5670 return error(GL_INVALID_VALUE);
5671 }
Nicolas Capens08e90f02014-11-21 12:49:12 -05005672
Nicolas Capensf160b172014-11-26 11:58:23 -05005673 if(location == -1)
5674 {
5675 return;
5676 }
John Bauman66b8ab22014-05-06 15:57:45 -04005677
Nicolas Capensf160b172014-11-26 11:58:23 -05005678 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005679
Nicolas Capensf160b172014-11-26 11:58:23 -05005680 if(context)
5681 {
5682 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005683
Nicolas Capensf160b172014-11-26 11:58:23 -05005684 if(!program)
5685 {
5686 return error(GL_INVALID_OPERATION);
5687 }
John Bauman66b8ab22014-05-06 15:57:45 -04005688
Nicolas Capensf160b172014-11-26 11:58:23 -05005689 if(!program->setUniform2fv(location, count, v))
5690 {
5691 return error(GL_INVALID_OPERATION);
5692 }
5693 }
John Bauman66b8ab22014-05-06 15:57:45 -04005694}
5695
5696void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
5697{
Nicolas Capensf160b172014-11-26 11:58:23 -05005698 GLint xy[4] = {x, y};
John Bauman66b8ab22014-05-06 15:57:45 -04005699
Nicolas Capensf160b172014-11-26 11:58:23 -05005700 glUniform2iv(location, 1, (GLint*)&xy);
John Bauman66b8ab22014-05-06 15:57:45 -04005701}
5702
5703void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
5704{
Nicolas Capensf160b172014-11-26 11:58:23 -05005705 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005706
Nicolas Capensf160b172014-11-26 11:58:23 -05005707 if(count < 0)
5708 {
5709 return error(GL_INVALID_VALUE);
5710 }
John Bauman66b8ab22014-05-06 15:57:45 -04005711
Nicolas Capensf160b172014-11-26 11:58:23 -05005712 if(location == -1)
5713 {
5714 return;
5715 }
John Bauman66b8ab22014-05-06 15:57:45 -04005716
Nicolas Capensf160b172014-11-26 11:58:23 -05005717 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005718
Nicolas Capensf160b172014-11-26 11:58:23 -05005719 if(context)
5720 {
5721 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005722
Nicolas Capensf160b172014-11-26 11:58:23 -05005723 if(!program)
5724 {
5725 return error(GL_INVALID_OPERATION);
5726 }
John Bauman66b8ab22014-05-06 15:57:45 -04005727
Nicolas Capensf160b172014-11-26 11:58:23 -05005728 if(!program->setUniform2iv(location, count, v))
5729 {
5730 return error(GL_INVALID_OPERATION);
5731 }
5732 }
John Bauman66b8ab22014-05-06 15:57:45 -04005733}
5734
5735void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5736{
Nicolas Capensf160b172014-11-26 11:58:23 -05005737 GLfloat xyz[3] = {x, y, z};
John Bauman66b8ab22014-05-06 15:57:45 -04005738
Nicolas Capensf160b172014-11-26 11:58:23 -05005739 glUniform3fv(location, 1, (GLfloat*)&xyz);
John Bauman66b8ab22014-05-06 15:57:45 -04005740}
5741
5742void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
5743{
Nicolas Capensf160b172014-11-26 11:58:23 -05005744 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005745
Nicolas Capensf160b172014-11-26 11:58:23 -05005746 if(count < 0)
5747 {
5748 return error(GL_INVALID_VALUE);
5749 }
John Bauman66b8ab22014-05-06 15:57:45 -04005750
Nicolas Capensf160b172014-11-26 11:58:23 -05005751 if(location == -1)
5752 {
5753 return;
5754 }
John Bauman66b8ab22014-05-06 15:57:45 -04005755
Nicolas Capensf160b172014-11-26 11:58:23 -05005756 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005757
Nicolas Capensf160b172014-11-26 11:58:23 -05005758 if(context)
5759 {
5760 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005761
Nicolas Capensf160b172014-11-26 11:58:23 -05005762 if(!program)
5763 {
5764 return error(GL_INVALID_OPERATION);
5765 }
John Bauman66b8ab22014-05-06 15:57:45 -04005766
Nicolas Capensf160b172014-11-26 11:58:23 -05005767 if(!program->setUniform3fv(location, count, v))
5768 {
5769 return error(GL_INVALID_OPERATION);
5770 }
5771 }
John Bauman66b8ab22014-05-06 15:57:45 -04005772}
5773
5774void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
5775{
Nicolas Capensf160b172014-11-26 11:58:23 -05005776 GLint xyz[3] = {x, y, z};
John Bauman66b8ab22014-05-06 15:57:45 -04005777
Nicolas Capensf160b172014-11-26 11:58:23 -05005778 glUniform3iv(location, 1, (GLint*)&xyz);
John Bauman66b8ab22014-05-06 15:57:45 -04005779}
5780
5781void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
5782{
Nicolas Capensf160b172014-11-26 11:58:23 -05005783 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005784
Nicolas Capensf160b172014-11-26 11:58:23 -05005785 if(count < 0)
5786 {
5787 return error(GL_INVALID_VALUE);
5788 }
John Bauman66b8ab22014-05-06 15:57:45 -04005789
Nicolas Capensf160b172014-11-26 11:58:23 -05005790 if(location == -1)
5791 {
5792 return;
5793 }
John Bauman66b8ab22014-05-06 15:57:45 -04005794
Nicolas Capensf160b172014-11-26 11:58:23 -05005795 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005796
Nicolas Capensf160b172014-11-26 11:58:23 -05005797 if(context)
5798 {
5799 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005800
Nicolas Capensf160b172014-11-26 11:58:23 -05005801 if(!program)
5802 {
5803 return error(GL_INVALID_OPERATION);
5804 }
John Bauman66b8ab22014-05-06 15:57:45 -04005805
Nicolas Capensf160b172014-11-26 11:58:23 -05005806 if(!program->setUniform3iv(location, count, v))
5807 {
5808 return error(GL_INVALID_OPERATION);
5809 }
5810 }
John Bauman66b8ab22014-05-06 15:57:45 -04005811}
5812
5813void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5814{
Nicolas Capensf160b172014-11-26 11:58:23 -05005815 GLfloat xyzw[4] = {x, y, z, w};
John Bauman66b8ab22014-05-06 15:57:45 -04005816
Nicolas Capensf160b172014-11-26 11:58:23 -05005817 glUniform4fv(location, 1, (GLfloat*)&xyzw);
John Bauman66b8ab22014-05-06 15:57:45 -04005818}
5819
5820void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
5821{
Nicolas Capensf160b172014-11-26 11:58:23 -05005822 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005823
Nicolas Capensf160b172014-11-26 11:58:23 -05005824 if(count < 0)
5825 {
5826 return error(GL_INVALID_VALUE);
5827 }
John Bauman66b8ab22014-05-06 15:57:45 -04005828
Nicolas Capensf160b172014-11-26 11:58:23 -05005829 if(location == -1)
5830 {
5831 return;
5832 }
John Bauman66b8ab22014-05-06 15:57:45 -04005833
Nicolas Capensf160b172014-11-26 11:58:23 -05005834 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005835
Nicolas Capensf160b172014-11-26 11:58:23 -05005836 if(context)
5837 {
5838 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005839
Nicolas Capensf160b172014-11-26 11:58:23 -05005840 if(!program)
5841 {
5842 return error(GL_INVALID_OPERATION);
5843 }
John Bauman66b8ab22014-05-06 15:57:45 -04005844
Nicolas Capensf160b172014-11-26 11:58:23 -05005845 if(!program->setUniform4fv(location, count, v))
5846 {
5847 return error(GL_INVALID_OPERATION);
5848 }
5849 }
John Bauman66b8ab22014-05-06 15:57:45 -04005850}
5851
5852void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5853{
Nicolas Capensf160b172014-11-26 11:58:23 -05005854 GLint xyzw[4] = {x, y, z, w};
John Bauman66b8ab22014-05-06 15:57:45 -04005855
Nicolas Capensf160b172014-11-26 11:58:23 -05005856 glUniform4iv(location, 1, (GLint*)&xyzw);
John Bauman66b8ab22014-05-06 15:57:45 -04005857}
5858
5859void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
5860{
Nicolas Capensf160b172014-11-26 11:58:23 -05005861 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
John Bauman66b8ab22014-05-06 15:57:45 -04005862
Nicolas Capensf160b172014-11-26 11:58:23 -05005863 if(count < 0)
5864 {
5865 return error(GL_INVALID_VALUE);
5866 }
John Bauman66b8ab22014-05-06 15:57:45 -04005867
Nicolas Capensf160b172014-11-26 11:58:23 -05005868 if(location == -1)
5869 {
5870 return;
5871 }
John Bauman66b8ab22014-05-06 15:57:45 -04005872
Nicolas Capensf160b172014-11-26 11:58:23 -05005873 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005874
Nicolas Capensf160b172014-11-26 11:58:23 -05005875 if(context)
5876 {
5877 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005878
Nicolas Capensf160b172014-11-26 11:58:23 -05005879 if(!program)
5880 {
5881 return error(GL_INVALID_OPERATION);
5882 }
John Bauman66b8ab22014-05-06 15:57:45 -04005883
Nicolas Capensf160b172014-11-26 11:58:23 -05005884 if(!program->setUniform4iv(location, count, v))
5885 {
5886 return error(GL_INVALID_OPERATION);
5887 }
5888 }
John Bauman66b8ab22014-05-06 15:57:45 -04005889}
5890
5891void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5892{
Nicolas Capensf160b172014-11-26 11:58:23 -05005893 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5894 location, count, transpose, value);
John Bauman66b8ab22014-05-06 15:57:45 -04005895
Nicolas Capensf160b172014-11-26 11:58:23 -05005896 if(count < 0 || transpose != GL_FALSE)
5897 {
5898 return error(GL_INVALID_VALUE);
5899 }
John Bauman66b8ab22014-05-06 15:57:45 -04005900
Nicolas Capensf160b172014-11-26 11:58:23 -05005901 if(location == -1)
5902 {
5903 return;
5904 }
John Bauman66b8ab22014-05-06 15:57:45 -04005905
Nicolas Capensf160b172014-11-26 11:58:23 -05005906 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005907
Nicolas Capensf160b172014-11-26 11:58:23 -05005908 if(context)
5909 {
5910 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005911
Nicolas Capensf160b172014-11-26 11:58:23 -05005912 if(!program)
5913 {
5914 return error(GL_INVALID_OPERATION);
5915 }
John Bauman66b8ab22014-05-06 15:57:45 -04005916
Nicolas Capensf160b172014-11-26 11:58:23 -05005917 if(!program->setUniformMatrix2fv(location, count, value))
5918 {
5919 return error(GL_INVALID_OPERATION);
5920 }
5921 }
John Bauman66b8ab22014-05-06 15:57:45 -04005922}
5923
5924void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5925{
Nicolas Capensf160b172014-11-26 11:58:23 -05005926 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5927 location, count, transpose, value);
John Bauman66b8ab22014-05-06 15:57:45 -04005928
Nicolas Capensf160b172014-11-26 11:58:23 -05005929 if(count < 0 || transpose != GL_FALSE)
5930 {
5931 return error(GL_INVALID_VALUE);
5932 }
John Bauman66b8ab22014-05-06 15:57:45 -04005933
Nicolas Capensf160b172014-11-26 11:58:23 -05005934 if(location == -1)
5935 {
5936 return;
5937 }
John Bauman66b8ab22014-05-06 15:57:45 -04005938
Nicolas Capensf160b172014-11-26 11:58:23 -05005939 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005940
Nicolas Capensf160b172014-11-26 11:58:23 -05005941 if(context)
5942 {
5943 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005944
Nicolas Capensf160b172014-11-26 11:58:23 -05005945 if(!program)
5946 {
5947 return error(GL_INVALID_OPERATION);
5948 }
John Bauman66b8ab22014-05-06 15:57:45 -04005949
Nicolas Capensf160b172014-11-26 11:58:23 -05005950 if(!program->setUniformMatrix3fv(location, count, value))
5951 {
5952 return error(GL_INVALID_OPERATION);
5953 }
5954 }
John Bauman66b8ab22014-05-06 15:57:45 -04005955}
5956
5957void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5958{
Nicolas Capensf160b172014-11-26 11:58:23 -05005959 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)",
5960 location, count, transpose, value);
John Bauman66b8ab22014-05-06 15:57:45 -04005961
Nicolas Capensf160b172014-11-26 11:58:23 -05005962 if(count < 0 || transpose != GL_FALSE)
5963 {
5964 return error(GL_INVALID_VALUE);
5965 }
John Bauman66b8ab22014-05-06 15:57:45 -04005966
Nicolas Capensf160b172014-11-26 11:58:23 -05005967 if(location == -1)
5968 {
5969 return;
5970 }
John Bauman66b8ab22014-05-06 15:57:45 -04005971
Nicolas Capensf160b172014-11-26 11:58:23 -05005972 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005973
Nicolas Capensf160b172014-11-26 11:58:23 -05005974 if(context)
5975 {
5976 es2::Program *program = context->getCurrentProgram();
John Bauman66b8ab22014-05-06 15:57:45 -04005977
Nicolas Capensf160b172014-11-26 11:58:23 -05005978 if(!program)
5979 {
5980 return error(GL_INVALID_OPERATION);
5981 }
John Bauman66b8ab22014-05-06 15:57:45 -04005982
Nicolas Capensf160b172014-11-26 11:58:23 -05005983 if(!program->setUniformMatrix4fv(location, count, value))
5984 {
5985 return error(GL_INVALID_OPERATION);
5986 }
5987 }
John Bauman66b8ab22014-05-06 15:57:45 -04005988}
5989
5990void GL_APIENTRY glUseProgram(GLuint program)
5991{
Nicolas Capensf160b172014-11-26 11:58:23 -05005992 TRACE("(GLuint program = %d)", program);
John Bauman66b8ab22014-05-06 15:57:45 -04005993
Nicolas Capensf160b172014-11-26 11:58:23 -05005994 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04005995
Nicolas Capensf160b172014-11-26 11:58:23 -05005996 if(context)
5997 {
5998 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04005999
Nicolas Capensf160b172014-11-26 11:58:23 -05006000 if(!programObject && program != 0)
6001 {
6002 if(context->getShader(program))
6003 {
6004 return error(GL_INVALID_OPERATION);
6005 }
6006 else
6007 {
6008 return error(GL_INVALID_VALUE);
6009 }
6010 }
John Bauman66b8ab22014-05-06 15:57:45 -04006011
Nicolas Capensf160b172014-11-26 11:58:23 -05006012 if(program != 0 && !programObject->isLinked())
6013 {
6014 return error(GL_INVALID_OPERATION);
6015 }
John Bauman66b8ab22014-05-06 15:57:45 -04006016
Nicolas Capensf160b172014-11-26 11:58:23 -05006017 context->useProgram(program);
6018 }
John Bauman66b8ab22014-05-06 15:57:45 -04006019}
6020
6021void GL_APIENTRY glValidateProgram(GLuint program)
6022{
Nicolas Capensf160b172014-11-26 11:58:23 -05006023 TRACE("(GLuint program = %d)", program);
John Bauman66b8ab22014-05-06 15:57:45 -04006024
Nicolas Capensf160b172014-11-26 11:58:23 -05006025 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006026
Nicolas Capensf160b172014-11-26 11:58:23 -05006027 if(context)
6028 {
6029 es2::Program *programObject = context->getProgram(program);
John Bauman66b8ab22014-05-06 15:57:45 -04006030
Nicolas Capensf160b172014-11-26 11:58:23 -05006031 if(!programObject)
6032 {
6033 if(context->getShader(program))
6034 {
6035 return error(GL_INVALID_OPERATION);
6036 }
6037 else
6038 {
6039 return error(GL_INVALID_VALUE);
6040 }
6041 }
John Bauman66b8ab22014-05-06 15:57:45 -04006042
Nicolas Capensf160b172014-11-26 11:58:23 -05006043 programObject->validate();
6044 }
John Bauman66b8ab22014-05-06 15:57:45 -04006045}
6046
6047void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)
6048{
Nicolas Capensf160b172014-11-26 11:58:23 -05006049 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
John Bauman66b8ab22014-05-06 15:57:45 -04006050
Nicolas Capensf160b172014-11-26 11:58:23 -05006051 if(index >= es2::MAX_VERTEX_ATTRIBS)
6052 {
6053 return error(GL_INVALID_VALUE);
6054 }
John Bauman66b8ab22014-05-06 15:57:45 -04006055
Nicolas Capensf160b172014-11-26 11:58:23 -05006056 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006057
Nicolas Capensf160b172014-11-26 11:58:23 -05006058 if(context)
6059 {
6060 GLfloat vals[4] = { x, 0, 0, 1 };
6061 context->setVertexAttrib(index, vals);
6062 }
John Bauman66b8ab22014-05-06 15:57:45 -04006063}
6064
6065void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)
6066{
Nicolas Capensf160b172014-11-26 11:58:23 -05006067 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
John Bauman66b8ab22014-05-06 15:57:45 -04006068
Nicolas Capensf160b172014-11-26 11:58:23 -05006069 if(index >= es2::MAX_VERTEX_ATTRIBS)
6070 {
6071 return error(GL_INVALID_VALUE);
6072 }
John Bauman66b8ab22014-05-06 15:57:45 -04006073
Nicolas Capensf160b172014-11-26 11:58:23 -05006074 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006075
Nicolas Capensf160b172014-11-26 11:58:23 -05006076 if(context)
6077 {
6078 GLfloat vals[4] = { values[0], 0, 0, 1 };
6079 context->setVertexAttrib(index, vals);
6080 }
John Bauman66b8ab22014-05-06 15:57:45 -04006081}
6082
6083void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
6084{
Nicolas Capensf160b172014-11-26 11:58:23 -05006085 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
John Bauman66b8ab22014-05-06 15:57:45 -04006086
Nicolas Capensf160b172014-11-26 11:58:23 -05006087 if(index >= es2::MAX_VERTEX_ATTRIBS)
6088 {
6089 return error(GL_INVALID_VALUE);
6090 }
John Bauman66b8ab22014-05-06 15:57:45 -04006091
Nicolas Capensf160b172014-11-26 11:58:23 -05006092 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006093
Nicolas Capensf160b172014-11-26 11:58:23 -05006094 if(context)
6095 {
6096 GLfloat vals[4] = { x, y, 0, 1 };
6097 context->setVertexAttrib(index, vals);
6098 }
John Bauman66b8ab22014-05-06 15:57:45 -04006099}
6100
6101void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)
6102{
Nicolas Capensf160b172014-11-26 11:58:23 -05006103 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
John Bauman66b8ab22014-05-06 15:57:45 -04006104
Nicolas Capensf160b172014-11-26 11:58:23 -05006105 if(index >= es2::MAX_VERTEX_ATTRIBS)
6106 {
6107 return error(GL_INVALID_VALUE);
6108 }
John Bauman66b8ab22014-05-06 15:57:45 -04006109
Nicolas Capensf160b172014-11-26 11:58:23 -05006110 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006111
Nicolas Capensf160b172014-11-26 11:58:23 -05006112 if(context)
6113 {
6114 GLfloat vals[4] = { values[0], values[1], 0, 1 };
6115 context->setVertexAttrib(index, vals);
6116 }
John Bauman66b8ab22014-05-06 15:57:45 -04006117}
6118
6119void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
6120{
Nicolas Capensf160b172014-11-26 11:58:23 -05006121 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
John Bauman66b8ab22014-05-06 15:57:45 -04006122
Nicolas Capensf160b172014-11-26 11:58:23 -05006123 if(index >= es2::MAX_VERTEX_ATTRIBS)
6124 {
6125 return error(GL_INVALID_VALUE);
6126 }
John Bauman66b8ab22014-05-06 15:57:45 -04006127
Nicolas Capensf160b172014-11-26 11:58:23 -05006128 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006129
Nicolas Capensf160b172014-11-26 11:58:23 -05006130 if(context)
6131 {
6132 GLfloat vals[4] = { x, y, z, 1 };
6133 context->setVertexAttrib(index, vals);
6134 }
John Bauman66b8ab22014-05-06 15:57:45 -04006135}
6136
6137void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)
6138{
Nicolas Capensf160b172014-11-26 11:58:23 -05006139 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
John Bauman66b8ab22014-05-06 15:57:45 -04006140
Nicolas Capensf160b172014-11-26 11:58:23 -05006141 if(index >= es2::MAX_VERTEX_ATTRIBS)
6142 {
6143 return error(GL_INVALID_VALUE);
6144 }
John Bauman66b8ab22014-05-06 15:57:45 -04006145
Nicolas Capensf160b172014-11-26 11:58:23 -05006146 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006147
Nicolas Capensf160b172014-11-26 11:58:23 -05006148 if(context)
6149 {
6150 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
6151 context->setVertexAttrib(index, vals);
6152 }
John Bauman66b8ab22014-05-06 15:57:45 -04006153}
6154
6155void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
6156{
Nicolas Capensf160b172014-11-26 11:58:23 -05006157 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
John Bauman66b8ab22014-05-06 15:57:45 -04006158
Nicolas Capensf160b172014-11-26 11:58:23 -05006159 if(index >= es2::MAX_VERTEX_ATTRIBS)
6160 {
6161 return error(GL_INVALID_VALUE);
6162 }
John Bauman66b8ab22014-05-06 15:57:45 -04006163
Nicolas Capensf160b172014-11-26 11:58:23 -05006164 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006165
Nicolas Capensf160b172014-11-26 11:58:23 -05006166 if(context)
6167 {
6168 GLfloat vals[4] = { x, y, z, w };
6169 context->setVertexAttrib(index, vals);
6170 }
John Bauman66b8ab22014-05-06 15:57:45 -04006171}
6172
6173void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)
6174{
Nicolas Capensf160b172014-11-26 11:58:23 -05006175 TRACE("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
John Bauman66b8ab22014-05-06 15:57:45 -04006176
Nicolas Capensf160b172014-11-26 11:58:23 -05006177 if(index >= es2::MAX_VERTEX_ATTRIBS)
6178 {
6179 return error(GL_INVALID_VALUE);
6180 }
John Bauman66b8ab22014-05-06 15:57:45 -04006181
Nicolas Capensf160b172014-11-26 11:58:23 -05006182 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006183
Nicolas Capensf160b172014-11-26 11:58:23 -05006184 if(context)
6185 {
6186 context->setVertexAttrib(index, values);
6187 }
John Bauman66b8ab22014-05-06 15:57:45 -04006188}
6189
6190void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
6191{
Nicolas Capensf160b172014-11-26 11:58:23 -05006192 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
6193 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
6194 index, size, type, normalized, stride, ptr);
John Bauman66b8ab22014-05-06 15:57:45 -04006195
Nicolas Capensf160b172014-11-26 11:58:23 -05006196 if(index >= es2::MAX_VERTEX_ATTRIBS)
6197 {
6198 return error(GL_INVALID_VALUE);
6199 }
John Bauman66b8ab22014-05-06 15:57:45 -04006200
Nicolas Capensf160b172014-11-26 11:58:23 -05006201 if(size < 1 || size > 4)
6202 {
6203 return error(GL_INVALID_VALUE);
6204 }
John Bauman66b8ab22014-05-06 15:57:45 -04006205
Alexis Hetued306182015-04-02 12:02:28 -04006206 egl::GLint clientVersion = egl::getClientVersion();
6207
Nicolas Capensf160b172014-11-26 11:58:23 -05006208 switch(type)
6209 {
6210 case GL_BYTE:
6211 case GL_UNSIGNED_BYTE:
6212 case GL_SHORT:
6213 case GL_UNSIGNED_SHORT:
6214 case GL_FIXED:
6215 case GL_FLOAT:
6216 break;
Alexis Hetued306182015-04-02 12:02:28 -04006217 case GL_INT_2_10_10_10_REV:
6218 case GL_UNSIGNED_INT_2_10_10_10_REV:
6219 if(clientVersion >= 3)
6220 {
6221 if(size != 4)
6222 {
6223 return error(GL_INVALID_OPERATION);
6224 }
6225 break;
6226 }
6227 else return error(GL_INVALID_ENUM);
6228 case GL_INT:
6229 case GL_UNSIGNED_INT:
6230 case GL_HALF_FLOAT:
6231 if(clientVersion >= 3)
6232 {
6233 break;
6234 }
6235 else return error(GL_INVALID_ENUM);
Nicolas Capensf160b172014-11-26 11:58:23 -05006236 default:
6237 return error(GL_INVALID_ENUM);
6238 }
John Bauman66b8ab22014-05-06 15:57:45 -04006239
Nicolas Capensf160b172014-11-26 11:58:23 -05006240 if(stride < 0)
6241 {
6242 return error(GL_INVALID_VALUE);
6243 }
John Bauman66b8ab22014-05-06 15:57:45 -04006244
Nicolas Capensf160b172014-11-26 11:58:23 -05006245 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006246
Nicolas Capensf160b172014-11-26 11:58:23 -05006247 if(context)
6248 {
6249 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr);
6250 }
John Bauman66b8ab22014-05-06 15:57:45 -04006251}
6252
6253void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
6254{
Nicolas Capensf160b172014-11-26 11:58:23 -05006255 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
John Bauman66b8ab22014-05-06 15:57:45 -04006256
Nicolas Capensf160b172014-11-26 11:58:23 -05006257 if(width < 0 || height < 0)
6258 {
6259 return error(GL_INVALID_VALUE);
6260 }
John Bauman66b8ab22014-05-06 15:57:45 -04006261
Nicolas Capensf160b172014-11-26 11:58:23 -05006262 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006263
Nicolas Capensf160b172014-11-26 11:58:23 -05006264 if(context)
6265 {
6266 context->setViewportParams(x, y, width, height);
6267 }
John Bauman66b8ab22014-05-06 15:57:45 -04006268}
6269
Alexis Hetue9233fb2015-02-11 10:31:58 -05006270void GL_APIENTRY glBlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
John Bauman66b8ab22014-05-06 15:57:45 -04006271{
Nicolas Capensf160b172014-11-26 11:58:23 -05006272 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
6273 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
6274 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
6275 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
John Bauman66b8ab22014-05-06 15:57:45 -04006276
Nicolas Capensf160b172014-11-26 11:58:23 -05006277 switch(filter)
6278 {
6279 case GL_NEAREST:
6280 break;
6281 default:
6282 return error(GL_INVALID_ENUM);
6283 }
John Bauman66b8ab22014-05-06 15:57:45 -04006284
Nicolas Capensf160b172014-11-26 11:58:23 -05006285 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
6286 {
6287 return error(GL_INVALID_VALUE);
6288 }
John Bauman66b8ab22014-05-06 15:57:45 -04006289
Nicolas Capensf160b172014-11-26 11:58:23 -05006290 es2::Context *context = es2::getContext();
John Bauman66b8ab22014-05-06 15:57:45 -04006291
Nicolas Capensf160b172014-11-26 11:58:23 -05006292 if(context)
6293 {
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006294 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
Nicolas Capensf160b172014-11-26 11:58:23 -05006295 {
6296 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
6297 return error(GL_INVALID_OPERATION);
6298 }
John Bauman66b8ab22014-05-06 15:57:45 -04006299
Nicolas Capensf160b172014-11-26 11:58:23 -05006300 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
6301 }
John Bauman66b8ab22014-05-06 15:57:45 -04006302}
6303
Alexis Hetue9233fb2015-02-11 10:31:58 -05006304void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
6305 GLbitfield mask, GLenum filter)
6306{
6307 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
6308 {
6309 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
6310 return error(GL_INVALID_OPERATION);
6311 }
6312
6313 glBlitFramebufferNV(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
6314}
6315
John Bauman66b8ab22014-05-06 15:57:45 -04006316void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Nicolas Capensf160b172014-11-26 11:58:23 -05006317 GLint border, GLenum format, GLenum type, const GLvoid* pixels)
John Bauman66b8ab22014-05-06 15:57:45 -04006318{
Nicolas Capensf160b172014-11-26 11:58:23 -05006319 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
6320 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
6321 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
6322 target, level, internalformat, width, height, depth, border, format, type, pixels);
John Bauman66b8ab22014-05-06 15:57:45 -04006323
Alexis Hetub027aa92015-01-19 15:56:12 -05006324 switch(target)
6325 {
6326 case GL_TEXTURE_3D_OES:
6327 switch(format)
6328 {
6329 case GL_DEPTH_COMPONENT:
6330 case GL_DEPTH_STENCIL_OES:
6331 return error(GL_INVALID_OPERATION);
6332 default:
6333 break;
6334 }
6335 break;
6336 default:
6337 return error(GL_INVALID_ENUM);
6338 }
6339
6340 if(!ValidateType3D(type) || !ValidateFormat3D(format))
6341 {
6342 return error(GL_INVALID_ENUM);
6343 }
6344
6345 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6346 {
6347 return error(GL_INVALID_VALUE);
6348 }
6349
6350 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6351 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
6352 {
6353 return error(GL_INVALID_VALUE);
6354 }
6355
6356 if(border != 0)
6357 {
6358 return error(GL_INVALID_VALUE);
6359 }
6360
6361 if(!ValidateInternalFormat3D(internalformat, format, type))
6362 {
6363 return error(GL_INVALID_OPERATION);
6364 }
6365
6366 es2::Context *context = es2::getContext();
6367
6368 if(context)
6369 {
6370 es2::Texture3D *texture = context->getTexture3D();
6371
6372 if(!texture)
6373 {
6374 return error(GL_INVALID_OPERATION);
6375 }
6376
6377 texture->setImage(level, width, height, depth, internalformat, type, context->getUnpackAlignment(), pixels);
6378 }
John Bauman66b8ab22014-05-06 15:57:45 -04006379}
6380
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006381void GL_APIENTRY glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
6382{
Alexis Hetub027aa92015-01-19 15:56:12 -05006383 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6384 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6385 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006386 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
6387
Alexis Hetub027aa92015-01-19 15:56:12 -05006388 switch(target)
6389 {
6390 case GL_TEXTURE_3D_OES:
6391 break;
6392 default:
6393 return error(GL_INVALID_ENUM);
6394 }
6395
6396 if(!ValidateType3D(type) || !ValidateFormat3D(format))
6397 {
6398 return error(GL_INVALID_ENUM);
6399 }
6400
6401 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6402 {
6403 return error(GL_INVALID_VALUE);
6404 }
6405
6406 if((width < 0) || (height < 0) || (depth < 0))
6407 {
6408 return error(GL_INVALID_VALUE);
6409 }
6410
6411 es2::Context *context = es2::getContext();
6412
6413 if(context)
6414 {
6415 es2::Texture3D *texture = context->getTexture3D();
6416
6417 if(validateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, format, texture))
6418 {
6419 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackAlignment(), pixels);
6420 }
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006421 }
6422}
6423
6424void GL_APIENTRY glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
6425{
Alexis Hetub027aa92015-01-19 15:56:12 -05006426 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6427 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006428 target, level, xoffset, yoffset, zoffset, x, y, width, height);
6429
Alexis Hetub027aa92015-01-19 15:56:12 -05006430 switch(target)
6431 {
6432 case GL_TEXTURE_3D_OES:
6433 break;
6434 default:
6435 return error(GL_INVALID_ENUM);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006436 }
6437
Alexis Hetub027aa92015-01-19 15:56:12 -05006438 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6439 {
6440 return error(GL_INVALID_VALUE);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006441 }
6442
Alexis Hetub027aa92015-01-19 15:56:12 -05006443 es2::Context *context = es2::getContext();
6444
6445 if(context)
6446 {
6447 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
6448
6449 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
6450 {
6451 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
6452 }
6453
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006454 if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)
Alexis Hetub027aa92015-01-19 15:56:12 -05006455 {
6456 return error(GL_INVALID_OPERATION);
6457 }
6458
6459 es2::Renderbuffer *source = framebuffer->getColorbuffer();
6460 GLenum colorbufferFormat = source->getFormat();
6461 es2::Texture3D *texture = context->getTexture3D();
6462
6463 if(!validateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture))
6464 {
6465 return;
6466 }
6467
6468 GLenum textureFormat = texture->getFormat(target, level);
6469
6470 if(!validateColorBufferFormat(textureFormat, colorbufferFormat))
6471 {
6472 return;
6473 }
6474
6475 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006476 }
6477}
6478
6479void GL_APIENTRY glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
6480{
Alexis Hetub027aa92015-01-19 15:56:12 -05006481 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
6482 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
6483 target, level, internalformat, width, height, depth, border, imageSize, data);
6484
6485 switch(target)
6486 {
6487 case GL_TEXTURE_3D_OES:
6488 break;
6489 default:
6490 return error(GL_INVALID_ENUM);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006491 }
Alexis Hetub027aa92015-01-19 15:56:12 -05006492
6493 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
6494 {
6495 return error(GL_INVALID_VALUE);
6496 }
6497
6498 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
6499 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
6500 {
6501 return error(GL_INVALID_VALUE);
6502 }
6503
6504 switch(internalformat)
6505 {
6506 case GL_ETC1_RGB8_OES:
6507 break;
6508 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6509 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6510 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
6511 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
6512 if(!S3TC_SUPPORT)
6513 {
6514 return error(GL_INVALID_ENUM);
6515 }
6516 break;
6517 case GL_DEPTH_COMPONENT:
6518 case GL_DEPTH_COMPONENT16:
6519 case GL_DEPTH_COMPONENT32_OES:
6520 case GL_DEPTH_STENCIL_OES:
6521 case GL_DEPTH24_STENCIL8_OES:
6522 return error(GL_INVALID_OPERATION);
6523 default:
6524 return error(GL_INVALID_ENUM);
6525 }
6526
6527 if(imageSize != es2::ComputeCompressedSize(width, height, internalformat) * depth)
6528 {
6529 return error(GL_INVALID_VALUE);
6530 }
6531
6532 es2::Context *context = es2::getContext();
6533
6534 if(context)
6535 {
6536 es2::Texture3D *texture = context->getTexture3D();
6537
6538 if(!texture)
6539 {
6540 return error(GL_INVALID_OPERATION);
6541 }
6542
6543 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006544 }
6545}
6546
6547void GL_APIENTRY glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
6548{
Alexis Hetub027aa92015-01-19 15:56:12 -05006549 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
6550 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
6551 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = 0x%0.8p)",
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006552 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6553
Alexis Hetub027aa92015-01-19 15:56:12 -05006554 switch(target)
6555 {
6556 case GL_TEXTURE_3D_OES:
6557 break;
6558 default:
6559 return error(GL_INVALID_ENUM);
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006560 }
Alexis Hetub027aa92015-01-19 15:56:12 -05006561
6562 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
6563 {
6564 return error(GL_INVALID_VALUE);
6565 }
6566
6567 switch(format)
6568 {
6569 case GL_ETC1_RGB8_OES:
6570 break;
6571 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6572 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6573 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
6574 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
6575 if(!S3TC_SUPPORT)
6576 {
6577 return error(GL_INVALID_ENUM);
6578 }
6579 break;
6580 default:
6581 return error(GL_INVALID_ENUM);
6582 }
6583
6584 if(width == 0 || height == 0 || depth == 0 || data == NULL)
6585 {
6586 return;
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006587 }
6588
Alexis Hetub027aa92015-01-19 15:56:12 -05006589 es2::Context *context = es2::getContext();
6590
6591 if(context)
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006592 {
Alexis Hetub027aa92015-01-19 15:56:12 -05006593 es2::Texture3D *texture = context->getTexture3D();
6594
6595 if(!texture)
6596 {
6597 return error(GL_INVALID_OPERATION);
6598 }
6599
6600 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
6601 }
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006602}
6603
6604void GL_APIENTRY glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6605{
Alexis Hetub027aa92015-01-19 15:56:12 -05006606 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6607 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6608
6609 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE)
6610 {
6611 return error(GL_INVALID_ENUM);
6612 }
6613
6614 switch(attachment)
6615 {
6616 case GL_COLOR_ATTACHMENT0:
6617 case GL_DEPTH_ATTACHMENT:
6618 case GL_STENCIL_ATTACHMENT:
6619 break;
6620 default:
6621 return error(GL_INVALID_ENUM);
6622 }
6623
6624 es2::Context *context = es2::getContext();
6625
6626 if(context)
6627 {
6628 if(texture == 0)
6629 {
6630 textarget = GL_NONE;
6631 }
6632 else
6633 {
6634 es2::Texture *tex = context->getTexture(texture);
6635
6636 if(tex == NULL)
6637 {
6638 return error(GL_INVALID_OPERATION);
6639 }
6640
6641 if(tex->isCompressed(textarget, level))
6642 {
6643 return error(GL_INVALID_OPERATION);
6644 }
6645
6646 switch(textarget)
6647 {
6648 case GL_TEXTURE_3D_OES:
6649 if(tex->getTarget() != GL_TEXTURE_3D_OES)
6650 {
6651 return error(GL_INVALID_OPERATION);
6652 }
6653 break;
6654 default:
6655 return error(GL_INVALID_ENUM);
6656 }
6657
6658 if(level != 0)
6659 {
6660 return error(GL_INVALID_VALUE);
6661 }
6662 }
6663
6664 es2::Framebuffer *framebuffer = NULL;
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006665 GLuint framebufferName = 0;
Alexis Hetub027aa92015-01-19 15:56:12 -05006666 if(target == GL_READ_FRAMEBUFFER_ANGLE)
6667 {
6668 framebuffer = context->getReadFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006669 framebufferName = context->getReadFramebufferName();
Alexis Hetub027aa92015-01-19 15:56:12 -05006670 }
6671 else
6672 {
6673 framebuffer = context->getDrawFramebuffer();
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006674 framebufferName = context->getDrawFramebufferName();
Alexis Hetub027aa92015-01-19 15:56:12 -05006675 }
6676
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006677 if(framebufferName == 0 || !framebuffer)
Alexis Hetub027aa92015-01-19 15:56:12 -05006678 {
6679 return error(GL_INVALID_OPERATION);
6680 }
6681
6682 switch(attachment)
6683 {
6684 case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break;
6685 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break;
6686 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;
6687 }
Nicolas Capens7cc75e12015-01-29 14:44:24 -05006688 }
6689}
Alexis Hetub027aa92015-01-19 15:56:12 -05006690
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006691void GL_APIENTRY glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6692{
Nicolas Capensd76b5df2014-10-28 15:54:46 -04006693 if(egl::getClientVersion() == 1)
6694 {
Nicolas Capensa2308052015-04-15 16:50:21 -04006695 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
Nicolas Capensd76b5df2014-10-28 15:54:46 -04006696 }
6697
Nicolas Capensf160b172014-11-26 11:58:23 -05006698 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006699
Nicolas Capensf160b172014-11-26 11:58:23 -05006700 switch(target)
6701 {
6702 case GL_TEXTURE_2D:
6703 case GL_TEXTURE_EXTERNAL_OES:
6704 break;
6705 default:
6706 return error(GL_INVALID_ENUM);
6707 }
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006708
Nicolas Capensf160b172014-11-26 11:58:23 -05006709 if(!image)
6710 {
6711 return error(GL_INVALID_OPERATION);
6712 }
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006713
Nicolas Capensf160b172014-11-26 11:58:23 -05006714 es2::Context *context = es2::getContext();
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006715
Nicolas Capensf160b172014-11-26 11:58:23 -05006716 if(context)
6717 {
6718 es2::Texture2D *texture = 0;
Nicolas Capens08e90f02014-11-21 12:49:12 -05006719
Nicolas Capensf160b172014-11-26 11:58:23 -05006720 switch(target)
6721 {
6722 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
6723 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
6724 default: UNREACHABLE();
6725 }
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006726
Nicolas Capensf160b172014-11-26 11:58:23 -05006727 if(!texture)
6728 {
6729 return error(GL_INVALID_OPERATION);
6730 }
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006731
Nicolas Capensf160b172014-11-26 11:58:23 -05006732 egl::Image *glImage = static_cast<egl::Image*>(image);
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006733
Nicolas Capensf160b172014-11-26 11:58:23 -05006734 texture->setImage(glImage);
6735 }
Nicolas Capense9c5e4f2014-05-28 22:46:43 -04006736}
6737
Nicolas Capens7e12ac62014-11-05 17:07:53 -05006738void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6739{
6740 TRACE("(GLenum target = 0x%X, GLeglImageOES image = 0x%0.8p)", target, image);
6741
6742 UNIMPLEMENTED();
6743}
6744
Nicolas Capensa2308052015-04-15 16:50:21 -04006745__eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
John Bauman66b8ab22014-05-06 15:57:45 -04006746{
Nicolas Capensf160b172014-11-26 11:58:23 -05006747 struct Extension
6748 {
6749 const char *name;
6750 __eglMustCastToProperFunctionPointerType address;
6751 };
John Bauman66b8ab22014-05-06 15:57:45 -04006752
Nicolas Capensf160b172014-11-26 11:58:23 -05006753 static const Extension glExtensions[] =
6754 {
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006755 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6756
Nicolas Capensf160b172014-11-26 11:58:23 -05006757 EXTENSION(glTexImage3DOES),
6758 EXTENSION(glBlitFramebufferANGLE),
Alexis Hetue9233fb2015-02-11 10:31:58 -05006759 EXTENSION(glBlitFramebufferNV),
Nicolas Capensf160b172014-11-26 11:58:23 -05006760 EXTENSION(glRenderbufferStorageMultisampleANGLE),
6761 EXTENSION(glDeleteFencesNV),
6762 EXTENSION(glGenFencesNV),
6763 EXTENSION(glIsFenceNV),
6764 EXTENSION(glTestFenceNV),
6765 EXTENSION(glGetFenceivNV),
6766 EXTENSION(glFinishFenceNV),
6767 EXTENSION(glSetFenceNV),
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006768 EXTENSION(glGetGraphicsResetStatusEXT),
Nicolas Capensf160b172014-11-26 11:58:23 -05006769 EXTENSION(glReadnPixelsEXT),
6770 EXTENSION(glGetnUniformfvEXT),
6771 EXTENSION(glGetnUniformivEXT),
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006772 EXTENSION(glGenQueriesEXT),
Nicolas Capensf160b172014-11-26 11:58:23 -05006773 EXTENSION(glDeleteQueriesEXT),
6774 EXTENSION(glIsQueryEXT),
6775 EXTENSION(glBeginQueryEXT),
6776 EXTENSION(glEndQueryEXT),
6777 EXTENSION(glGetQueryivEXT),
6778 EXTENSION(glGetQueryObjectuivEXT),
6779 EXTENSION(glEGLImageTargetTexture2DOES),
Nicolas Capens7e12ac62014-11-05 17:07:53 -05006780 EXTENSION(glEGLImageTargetRenderbufferStorageOES),
Nicolas Capensf6b6d272014-11-03 11:11:08 -05006781
6782 #undef EXTENSION
Nicolas Capensf160b172014-11-26 11:58:23 -05006783 };
John Bauman66b8ab22014-05-06 15:57:45 -04006784
Nicolas Capensf160b172014-11-26 11:58:23 -05006785 for(int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++)
6786 {
6787 if(strcmp(procname, glExtensions[ext].name) == 0)
6788 {
6789 return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
6790 }
6791 }
John Bauman66b8ab22014-05-06 15:57:45 -04006792
Nicolas Capensf160b172014-11-26 11:58:23 -05006793 return NULL;
John Bauman66b8ab22014-05-06 15:57:45 -04006794}
6795
John Baumand4ae8632014-05-06 16:18:33 -04006796void GL_APIENTRY Register(const char *licenseKey)
6797{
6798 RegisterLicenseKey(licenseKey);
6799}
6800
John Bauman66b8ab22014-05-06 15:57:45 -04006801}