OSDN Git Service

Added utility function for OpenGL extension strings
[android-x86/external-swiftshader.git] / src / OpenGL / libGLESv2 / libGLESv3.cpp
1 // SwiftShader Software Renderer\r
2 //\r
3 // Copyright(c) 2015 Google Inc.\r
4 //\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,\r
6 // transcribed, stored in a retrieval system, translated into any human or computer\r
7 // language by any means, or disclosed to third parties without the explicit written\r
8 // agreement of Google Inc. Without such an agreement, no rights or licenses, express\r
9 // or implied, including but not limited to any patent rights, are granted to you.\r
10 //\r
11 // libGLESv3.cpp: Implements the exported OpenGL ES 3.0 functions.\r
12 \r
13 #include "main.h"\r
14 #include "Buffer.h"\r
15 #include "Framebuffer.h"\r
16 #include "Program.h"\r
17 #include "Query.h"\r
18 #include "Sampler.h"\r
19 #include "Texture.h"\r
20 #include "common/debug.h"\r
21 \r
22 #define GL_APICALL\r
23 #include <GLES3/gl3.h>\r
24 #include <GLES2/gl2ext.h>\r
25 \r
26 typedef std::pair<GLenum, GLenum> InternalFormatTypePair;\r
27 typedef std::map<InternalFormatTypePair, GLenum> FormatMap;\r
28 \r
29 // A helper function to insert data into the format map with fewer characters.\r
30 static void InsertFormatMapping(FormatMap& map, GLenum internalformat, GLenum format, GLenum type)\r
31 {\r
32         map[InternalFormatTypePair(internalformat, type)] = format;\r
33 }\r
34 \r
35 static bool validImageSize(GLint level, GLsizei width, GLsizei height)\r
36 {\r
37         if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)\r
38         {\r
39                 return false;\r
40         }\r
41 \r
42         return true;\r
43 }\r
44 \r
45 static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)\r
46 {\r
47         if(!texture)\r
48         {\r
49                 return error(GL_INVALID_OPERATION, false);\r
50         }\r
51 \r
52         if(compressed != texture->isCompressed(target, level))\r
53         {\r
54                 return error(GL_INVALID_OPERATION, false);\r
55         }\r
56 \r
57         if(format != GL_NONE && format != texture->getFormat(target, level))\r
58         {\r
59                 return error(GL_INVALID_OPERATION, false);\r
60         }\r
61 \r
62         if(compressed)\r
63         {\r
64                 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||\r
65                    (height % 4 != 0 && height != texture->getHeight(target, 0)))\r
66                 {\r
67                         return error(GL_INVALID_OPERATION, false);\r
68                 }\r
69         }\r
70 \r
71         if(xoffset + width > texture->getWidth(target, level) ||\r
72                 yoffset + height > texture->getHeight(target, level))\r
73         {\r
74                 return error(GL_INVALID_VALUE, false);\r
75         }\r
76 \r
77         return true;\r
78 }\r
79 \r
80 static 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)\r
81 {\r
82         if(!texture)\r
83         {\r
84                 return error(GL_INVALID_OPERATION, false);\r
85         }\r
86 \r
87         if(compressed != texture->isCompressed(target, level))\r
88         {\r
89                 return error(GL_INVALID_OPERATION, false);\r
90         }\r
91 \r
92         if(format != GL_NONE && format != texture->getFormat(target, level))\r
93         {\r
94                 return error(GL_INVALID_OPERATION, false);\r
95         }\r
96 \r
97         if(compressed)\r
98         {\r
99                 if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||\r
100                         (height % 4 != 0 && height != texture->getHeight(target, 0)) ||\r
101                         (depth % 4 != 0 && depth != texture->getDepth(target, 0)))\r
102                 {\r
103                         return error(GL_INVALID_OPERATION, false);\r
104                 }\r
105         }\r
106 \r
107         if(xoffset + width > texture->getWidth(target, level) ||\r
108                 yoffset + height > texture->getHeight(target, level) ||\r
109                 zoffset + depth > texture->getDepth(target, level))\r
110         {\r
111                 return error(GL_INVALID_VALUE, false);\r
112         }\r
113 \r
114         return true;\r
115 }\r
116 \r
117 static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)\r
118 {\r
119         switch(textureFormat)\r
120         {\r
121         case GL_ALPHA:\r
122                 if(colorbufferFormat != GL_ALPHA &&\r
123                         colorbufferFormat != GL_RGBA &&\r
124                         colorbufferFormat != GL_RGBA4 &&\r
125                         colorbufferFormat != GL_RGB5_A1 &&\r
126                         colorbufferFormat != GL_RGBA8)\r
127                 {\r
128                         return error(GL_INVALID_OPERATION, false);\r
129                 }\r
130                 break;\r
131         case GL_LUMINANCE:\r
132         case GL_RGB:\r
133                 if(colorbufferFormat != GL_RGB &&\r
134                         colorbufferFormat != GL_RGB565 &&\r
135                         colorbufferFormat != GL_RGB8 &&\r
136                         colorbufferFormat != GL_RGBA &&\r
137                         colorbufferFormat != GL_RGBA4 &&\r
138                         colorbufferFormat != GL_RGB5_A1 &&\r
139                         colorbufferFormat != GL_RGBA8)\r
140                 {\r
141                         return error(GL_INVALID_OPERATION, false);\r
142                 }\r
143                 break;\r
144         case GL_LUMINANCE_ALPHA:\r
145         case GL_RGBA:\r
146                 if(colorbufferFormat != GL_RGBA &&\r
147                         colorbufferFormat != GL_RGBA4 &&\r
148                         colorbufferFormat != GL_RGB5_A1 &&\r
149                         colorbufferFormat != GL_RGBA8)\r
150                 {\r
151                         return error(GL_INVALID_OPERATION, false);\r
152                 }\r
153                 break;\r
154         case GL_ETC1_RGB8_OES:\r
155                 return error(GL_INVALID_OPERATION, false);\r
156         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:\r
157         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:\r
158         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:\r
159         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:\r
160                 if(S3TC_SUPPORT)\r
161                 {\r
162                         return error(GL_INVALID_OPERATION, false);\r
163                 }\r
164                 else\r
165                 {\r
166                         return error(GL_INVALID_ENUM, false);\r
167                 }\r
168         case GL_DEPTH_COMPONENT:\r
169         case GL_DEPTH_STENCIL:\r
170                 return error(GL_INVALID_OPERATION, false);\r
171         default:\r
172                 return error(GL_INVALID_ENUM, false);\r
173         }\r
174         return true;\r
175 }\r
176 \r
177 static FormatMap BuildFormatMap3D()\r
178 {\r
179         FormatMap map;\r
180 \r
181         //                       Internal format | Format | Type\r
182         InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);\r
183         InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);\r
184         InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);\r
185         InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);\r
186         InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);\r
187         InsertFormatMapping(map, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);\r
188         InsertFormatMapping(map, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);\r
189         InsertFormatMapping(map, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);\r
190         InsertFormatMapping(map, GL_R8, GL_RED, GL_UNSIGNED_BYTE);\r
191         InsertFormatMapping(map, GL_R8_SNORM, GL_RED, GL_UNSIGNED_BYTE);\r
192         InsertFormatMapping(map, GL_R16F, GL_RED, GL_HALF_FLOAT);\r
193         InsertFormatMapping(map, GL_R16F, GL_RED, GL_FLOAT);\r
194         InsertFormatMapping(map, GL_R32F, GL_RED, GL_FLOAT);\r
195         InsertFormatMapping(map, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE);\r
196         InsertFormatMapping(map, GL_R8I, GL_RED_INTEGER, GL_BYTE);\r
197         InsertFormatMapping(map, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT);\r
198         InsertFormatMapping(map, GL_R16I, GL_RED_INTEGER, GL_SHORT);\r
199         InsertFormatMapping(map, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT);\r
200         InsertFormatMapping(map, GL_R32I, GL_RED_INTEGER, GL_INT);\r
201         InsertFormatMapping(map, GL_RG8, GL_RG, GL_UNSIGNED_BYTE);\r
202         InsertFormatMapping(map, GL_RG8_SNORM, GL_RG, GL_BYTE);\r
203         InsertFormatMapping(map, GL_R16F, GL_RED, GL_HALF_FLOAT);\r
204         InsertFormatMapping(map, GL_R16F, GL_RED, GL_FLOAT);\r
205         InsertFormatMapping(map, GL_RG32F, GL_RG, GL_FLOAT);\r
206         InsertFormatMapping(map, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE);\r
207         InsertFormatMapping(map, GL_RG8I, GL_RG_INTEGER, GL_BYTE);\r
208         InsertFormatMapping(map, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT);\r
209         InsertFormatMapping(map, GL_RG16I, GL_RG_INTEGER, GL_SHORT);\r
210         InsertFormatMapping(map, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT);\r
211         InsertFormatMapping(map, GL_RG32I, GL_RG_INTEGER, GL_INT);\r
212         InsertFormatMapping(map, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE);\r
213         InsertFormatMapping(map, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE);\r
214         InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE);\r
215         InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);\r
216         InsertFormatMapping(map, GL_RGB8_SNORM, GL_RGB, GL_BYTE);\r
217         InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV);\r
218         InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT);\r
219         InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);\r
220         InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);\r
221         InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT);\r
222         InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_FLOAT);\r
223         InsertFormatMapping(map, GL_RGB16F, GL_RGB, GL_HALF_FLOAT);\r
224         InsertFormatMapping(map, GL_RGB16F, GL_RGB, GL_FLOAT);\r
225         InsertFormatMapping(map, GL_RGB32F, GL_RGB, GL_FLOAT);\r
226         InsertFormatMapping(map, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE);\r
227         InsertFormatMapping(map, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE);\r
228         InsertFormatMapping(map, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT);\r
229         InsertFormatMapping(map, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT);\r
230         InsertFormatMapping(map, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT);\r
231         InsertFormatMapping(map, GL_RGB32I, GL_RGB_INTEGER, GL_INT);\r
232         InsertFormatMapping(map, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);\r
233         InsertFormatMapping(map, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE);\r
234         InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE);\r
235         InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);\r
236         InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);\r
237         InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE);\r
238         InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);\r
239         InsertFormatMapping(map, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);\r
240         InsertFormatMapping(map, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);\r
241         InsertFormatMapping(map, GL_RGBA16F, GL_RGBA, GL_FLOAT);\r
242         InsertFormatMapping(map, GL_RGBA32F, GL_RGBA, GL_FLOAT);\r
243         InsertFormatMapping(map, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE);\r
244         InsertFormatMapping(map, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE);\r
245         InsertFormatMapping(map, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV);\r
246         InsertFormatMapping(map, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT);\r
247         InsertFormatMapping(map, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT);\r
248         InsertFormatMapping(map, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);\r
249         InsertFormatMapping(map, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);\r
250 \r
251         InsertFormatMapping(map, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);\r
252         InsertFormatMapping(map, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);\r
253         InsertFormatMapping(map, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);\r
254         InsertFormatMapping(map, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);\r
255         InsertFormatMapping(map, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);\r
256         InsertFormatMapping(map, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);\r
257 \r
258         return map;\r
259 }\r
260 \r
261 static bool ValidateType3D(GLenum type)\r
262 {\r
263         switch(type)\r
264         {\r
265         case GL_UNSIGNED_BYTE:\r
266         case GL_BYTE:\r
267         case GL_UNSIGNED_SHORT:\r
268         case GL_SHORT:\r
269         case GL_UNSIGNED_INT:\r
270         case GL_INT:\r
271         case GL_HALF_FLOAT:\r
272         case GL_FLOAT:\r
273         case GL_UNSIGNED_SHORT_5_6_5:\r
274         case GL_UNSIGNED_SHORT_4_4_4_4:\r
275         case GL_UNSIGNED_SHORT_5_5_5_1:\r
276         case GL_UNSIGNED_INT_2_10_10_10_REV:\r
277         case GL_UNSIGNED_INT_10F_11F_11F_REV:\r
278         case GL_UNSIGNED_INT_5_9_9_9_REV:\r
279         case GL_UNSIGNED_INT_24_8:\r
280         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:\r
281                 return true;\r
282         default:\r
283                 break;\r
284         }\r
285         return false;\r
286 }\r
287 \r
288 static bool ValidateFormat3D(GLenum format)\r
289 {\r
290         switch(format)\r
291         {\r
292         case GL_RED:\r
293         case GL_RG:\r
294         case GL_RGB:\r
295         case GL_RGBA:\r
296         case GL_DEPTH_COMPONENT:\r
297         case GL_DEPTH_STENCIL:\r
298         case GL_LUMINANCE_ALPHA:\r
299         case GL_LUMINANCE:\r
300         case GL_ALPHA:\r
301         case GL_RED_INTEGER:\r
302         case GL_RG_INTEGER:\r
303         case GL_RGB_INTEGER:\r
304         case GL_RGBA_INTEGER:\r
305                 return true;\r
306         default:\r
307                 break;\r
308         }\r
309         return false;\r
310 }\r
311 \r
312 static bool ValidateInternalFormat3D(GLenum internalformat, GLenum format, GLenum type)\r
313 {\r
314         static const FormatMap formatMap = BuildFormatMap3D();\r
315         FormatMap::const_iterator iter = formatMap.find(InternalFormatTypePair(internalformat, type));\r
316         if(iter != formatMap.end())\r
317         {\r
318                 return iter->second == format;\r
319         }\r
320         return false;\r
321 }\r
322 \r
323 static bool ValidateQueryTarget(GLenum target)\r
324 {\r
325         switch(target)\r
326         {\r
327         case GL_ANY_SAMPLES_PASSED:\r
328         case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:\r
329         case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:\r
330                 break;\r
331         default:\r
332                 return false;\r
333         }\r
334 \r
335         return true;\r
336 }\r
337 \r
338 static bool ValidateBufferTarget(GLenum target)\r
339 {\r
340         switch(target)\r
341         {\r
342         case GL_ARRAY_BUFFER:\r
343         case GL_COPY_READ_BUFFER:\r
344         case GL_COPY_WRITE_BUFFER:\r
345         case GL_ELEMENT_ARRAY_BUFFER:\r
346         case GL_PIXEL_PACK_BUFFER:\r
347         case GL_PIXEL_UNPACK_BUFFER:\r
348         case GL_TRANSFORM_FEEDBACK_BUFFER:\r
349         case GL_UNIFORM_BUFFER:\r
350                 break;\r
351         default:\r
352                 return false;\r
353         }\r
354 \r
355         return true;\r
356 }\r
357 \r
358 extern "C"\r
359 {\r
360 \r
361 void GL_APIENTRY glReadBuffer(GLenum src)\r
362 {\r
363         TRACE("(GLenum src = 0x%X)", src);\r
364 \r
365         es2::Context *context = es2::getContext();\r
366 \r
367         switch(src)\r
368         {\r
369         case GL_BACK:\r
370         case GL_NONE:\r
371                 break;\r
372         case GL_COLOR_ATTACHMENT0:\r
373         case GL_COLOR_ATTACHMENT1:\r
374         case GL_COLOR_ATTACHMENT2:\r
375         case GL_COLOR_ATTACHMENT3:\r
376         case GL_COLOR_ATTACHMENT4:\r
377         case GL_COLOR_ATTACHMENT5:\r
378         case GL_COLOR_ATTACHMENT6:\r
379         case GL_COLOR_ATTACHMENT7:\r
380         case GL_COLOR_ATTACHMENT8:\r
381         case GL_COLOR_ATTACHMENT9:\r
382         case GL_COLOR_ATTACHMENT10:\r
383         case GL_COLOR_ATTACHMENT11:\r
384         case GL_COLOR_ATTACHMENT12:\r
385         case GL_COLOR_ATTACHMENT13:\r
386         case GL_COLOR_ATTACHMENT14:\r
387         case GL_COLOR_ATTACHMENT15:\r
388                 if((src - GL_COLOR_ATTACHMENT0) >= es2::IMPLEMENTATION_MAX_COLOR_ATTACHMENTS)\r
389                 {\r
390                         return error(GL_INVALID_ENUM);\r
391                 }\r
392                 break;\r
393         default:\r
394                 error(GL_INVALID_ENUM);\r
395         }\r
396 \r
397         UNIMPLEMENTED();\r
398 }\r
399 \r
400 void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)\r
401 {\r
402         TRACE("(GLenum mode = 0x%X, GLuint start = %d, GLuint end = %d, "\r
403                   "GLsizei count = %d, GLenum type = 0x%x, const void* indices = 0x%0.8p)",\r
404                   mode, start, end, count, type, indices);\r
405 \r
406         switch(mode)\r
407         {\r
408         case GL_POINTS:\r
409         case GL_LINES:\r
410         case GL_LINE_LOOP:\r
411         case GL_LINE_STRIP:\r
412         case GL_TRIANGLES:\r
413         case GL_TRIANGLE_FAN:\r
414         case GL_TRIANGLE_STRIP:\r
415                 break;\r
416         default:\r
417                 return error(GL_INVALID_ENUM);\r
418         }\r
419 \r
420         switch(type)\r
421         {\r
422         case GL_UNSIGNED_BYTE:\r
423         case GL_UNSIGNED_SHORT:\r
424         case GL_UNSIGNED_INT:\r
425                 break;\r
426         default:\r
427                 return error(GL_INVALID_ENUM);\r
428         }\r
429 \r
430         if((count < 0) || (end < start))\r
431         {\r
432                 return error(GL_INVALID_VALUE);\r
433         }\r
434 \r
435         UNIMPLEMENTED();\r
436 }\r
437 \r
438 void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)\r
439 {\r
440         TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "\r
441               "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "\r
442               "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",\r
443               target, level, internalformat, width, height, depth, border, format, type, pixels);\r
444 \r
445         switch(target)\r
446         {\r
447         case GL_TEXTURE_3D:\r
448         case GL_TEXTURE_2D_ARRAY:\r
449                 break;\r
450         default:\r
451                 return error(GL_INVALID_ENUM);\r
452         }\r
453 \r
454         if(!ValidateType3D(type) || !ValidateFormat3D(format))\r
455         {\r
456                 return error(GL_INVALID_ENUM);\r
457         }\r
458 \r
459         if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))\r
460         {\r
461                 return error(GL_INVALID_VALUE);\r
462         }\r
463 \r
464         const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;\r
465         if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))\r
466         {\r
467                 return error(GL_INVALID_VALUE);\r
468         }\r
469 \r
470         if(border != 0)\r
471         {\r
472                 return error(GL_INVALID_VALUE);\r
473         }\r
474 \r
475         if(!ValidateInternalFormat3D(internalformat, format, type))\r
476         {\r
477                 return error(GL_INVALID_OPERATION);\r
478         }\r
479 \r
480         es2::Context *context = es2::getContext();\r
481 \r
482         if(context)\r
483         {\r
484                 es2::Texture3D *texture = context->getTexture3D();\r
485 \r
486                 if(!texture)\r
487                 {\r
488                         return error(GL_INVALID_OPERATION);\r
489                 }\r
490 \r
491                 texture->setImage(level, width, height, depth, internalformat, type, context->getUnpackAlignment(), pixels);\r
492         }\r
493 }\r
494 \r
495 void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)\r
496 {\r
497         TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "\r
498                 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "\r
499                 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",\r
500                 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);\r
501 \r
502         switch(target)\r
503         {\r
504         case GL_TEXTURE_3D:\r
505         case GL_TEXTURE_2D_ARRAY:\r
506                 break;\r
507         default:\r
508                 return error(GL_INVALID_ENUM);\r
509         }\r
510 \r
511         if(!ValidateType3D(type) || !ValidateFormat3D(format))\r
512         {\r
513                 return error(GL_INVALID_ENUM);\r
514         }\r
515 \r
516         if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))\r
517         {\r
518                 return error(GL_INVALID_VALUE);\r
519         }\r
520 \r
521         if((width < 0) || (height < 0) || (depth < 0))\r
522         {\r
523                 return error(GL_INVALID_VALUE);\r
524         }\r
525 \r
526         es2::Context *context = es2::getContext();\r
527 \r
528         if(context)\r
529         {\r
530                 es2::Texture3D *texture = context->getTexture3D();\r
531 \r
532                 if(validateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, format, texture))\r
533                 {\r
534                         texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackAlignment(), pixels);\r
535                 }\r
536         }\r
537 }\r
538 \r
539 void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)\r
540 {\r
541         TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "\r
542                 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",\r
543                 target, level, xoffset, yoffset, zoffset, x, y, width, height);\r
544 \r
545         switch(target)\r
546         {\r
547         case GL_TEXTURE_3D:\r
548         case GL_TEXTURE_2D_ARRAY:\r
549                 break;\r
550         default:\r
551                 return error(GL_INVALID_ENUM);\r
552         }\r
553 \r
554         if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))\r
555         {\r
556                 return error(GL_INVALID_VALUE);\r
557         }\r
558 \r
559         es2::Context *context = es2::getContext();\r
560 \r
561         if(context)\r
562         {\r
563                 es2::Framebuffer *framebuffer = context->getReadFramebuffer();\r
564 \r
565                 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)\r
566                 {\r
567                         return error(GL_INVALID_FRAMEBUFFER_OPERATION);\r
568                 }\r
569 \r
570                 if(context->getReadFramebufferName() != 0 && framebuffer->getColorbuffer()->getSamples() > 1)\r
571                 {\r
572                         return error(GL_INVALID_OPERATION);\r
573                 }\r
574 \r
575                 es2::Renderbuffer *source = framebuffer->getColorbuffer();\r
576                 GLenum colorbufferFormat = source->getFormat();\r
577                 es2::Texture3D *texture = context->getTexture3D();\r
578 \r
579                 if(!validateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture))\r
580                 {\r
581                         return;\r
582                 }\r
583 \r
584                 GLenum textureFormat = texture->getFormat(target, level);\r
585 \r
586                 if(!validateColorBufferFormat(textureFormat, colorbufferFormat))\r
587                 {\r
588                         return;\r
589                 }\r
590 \r
591                 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);\r
592         }\r
593 }\r
594 \r
595 void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)\r
596 {\r
597         TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "\r
598                 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",\r
599                 target, level, internalformat, width, height, depth, border, imageSize, data);\r
600 \r
601         switch(target)\r
602         {\r
603         case GL_TEXTURE_3D:\r
604         case GL_TEXTURE_2D_ARRAY:\r
605                 break;\r
606         default:\r
607                 return error(GL_INVALID_ENUM);\r
608         }\r
609 \r
610         if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))\r
611         {\r
612                 return error(GL_INVALID_VALUE);\r
613         }\r
614 \r
615         const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;\r
616         if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) || (border != 0) || (imageSize < 0))\r
617         {\r
618                 return error(GL_INVALID_VALUE);\r
619         }\r
620 \r
621         switch(internalformat)\r
622         {\r
623         case GL_ETC1_RGB8_OES:\r
624         case GL_COMPRESSED_R11_EAC:\r
625         case GL_COMPRESSED_SIGNED_R11_EAC:\r
626         case GL_COMPRESSED_RG11_EAC:\r
627         case GL_COMPRESSED_SIGNED_RG11_EAC:\r
628         case GL_COMPRESSED_RGB8_ETC2:\r
629         case GL_COMPRESSED_SRGB8_ETC2:\r
630         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:\r
631         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:\r
632         case GL_COMPRESSED_RGBA8_ETC2_EAC:\r
633         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:\r
634                 break;\r
635         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:\r
636         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:\r
637         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:\r
638         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:\r
639                 if(!S3TC_SUPPORT)\r
640                 {\r
641                         return error(GL_INVALID_ENUM);\r
642                 }\r
643                 break;\r
644         case GL_DEPTH_COMPONENT:\r
645         case GL_DEPTH_COMPONENT16:\r
646         case GL_DEPTH_COMPONENT32_OES:\r
647         case GL_DEPTH_STENCIL:\r
648         case GL_DEPTH24_STENCIL8:\r
649                 return error(GL_INVALID_OPERATION);\r
650         default:\r
651                 return error(GL_INVALID_ENUM);\r
652         }\r
653 \r
654         if(imageSize != es2::ComputeCompressedSize(width, height, internalformat) * depth)\r
655         {\r
656                 return error(GL_INVALID_VALUE);\r
657         }\r
658 \r
659         es2::Context *context = es2::getContext();\r
660 \r
661         if(context)\r
662         {\r
663                 es2::Texture3D *texture = context->getTexture3D();\r
664 \r
665                 if(!texture)\r
666                 {\r
667                         return error(GL_INVALID_OPERATION);\r
668                 }\r
669 \r
670                 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);\r
671         }\r
672 }\r
673 \r
674 void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)\r
675 {\r
676         TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "\r
677               "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "\r
678               "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = 0x%0.8p)",\r
679               target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);\r
680 \r
681         switch(target)\r
682         {\r
683         case GL_TEXTURE_3D:\r
684         case GL_TEXTURE_2D_ARRAY:\r
685                 break;\r
686         default:\r
687                 return error(GL_INVALID_ENUM);\r
688         }\r
689 \r
690         if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)\r
691         {\r
692                 return error(GL_INVALID_VALUE);\r
693         }\r
694 \r
695         switch(format)\r
696         {\r
697         case GL_ETC1_RGB8_OES:\r
698         case GL_COMPRESSED_R11_EAC:\r
699         case GL_COMPRESSED_SIGNED_R11_EAC:\r
700         case GL_COMPRESSED_RG11_EAC:\r
701         case GL_COMPRESSED_SIGNED_RG11_EAC:\r
702         case GL_COMPRESSED_RGB8_ETC2:\r
703         case GL_COMPRESSED_SRGB8_ETC2:\r
704         case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:\r
705         case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:\r
706         case GL_COMPRESSED_RGBA8_ETC2_EAC:\r
707         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:\r
708                 break;\r
709         case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:\r
710         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:\r
711         case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:\r
712         case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:\r
713                 if(!S3TC_SUPPORT)\r
714                 {\r
715                         return error(GL_INVALID_ENUM);\r
716                 }\r
717                 break;\r
718         default:\r
719                 return error(GL_INVALID_ENUM);\r
720         }\r
721 \r
722         if(width == 0 || height == 0 || depth == 0 || data == NULL)\r
723         {\r
724                 return;\r
725         }\r
726 \r
727         es2::Context *context = es2::getContext();\r
728 \r
729         if(context)\r
730         {\r
731                 es2::Texture3D *texture = context->getTexture3D();\r
732 \r
733                 if(!texture)\r
734                 {\r
735                         return error(GL_INVALID_OPERATION);\r
736                 }\r
737 \r
738                 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);\r
739         }\r
740 }\r
741 \r
742 void GL_APIENTRY glGenQueries(GLsizei n, GLuint *ids)\r
743 {\r
744         TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);\r
745 \r
746         if(n < 0)\r
747         {\r
748                 return error(GL_INVALID_VALUE);\r
749         }\r
750 \r
751         es2::Context *context = es2::getContext();\r
752 \r
753         if(context)\r
754         {\r
755                 for(int i = 0; i < n; i++)\r
756                 {\r
757                         ids[i] = context->createQuery();\r
758                 }\r
759         }\r
760 }\r
761 \r
762 void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint *ids)\r
763 {\r
764         TRACE("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);\r
765 \r
766         if(n < 0)\r
767         {\r
768                 return error(GL_INVALID_VALUE);\r
769         }\r
770 \r
771         es2::Context *context = es2::getContext();\r
772 \r
773         if(context)\r
774         {\r
775                 for(int i = 0; i < n; i++)\r
776                 {\r
777                         context->deleteQuery(ids[i]);\r
778                 }\r
779         }\r
780 }\r
781 \r
782 GLboolean GL_APIENTRY glIsQuery(GLuint id)\r
783 {\r
784         TRACE("(GLuint id = %d)", id);\r
785 \r
786         if(id == 0)\r
787         {\r
788                 return GL_FALSE;\r
789         }\r
790 \r
791         es2::Context *context = es2::getContext();\r
792 \r
793         if(context)\r
794         {\r
795                 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);\r
796 \r
797                 if(queryObject)\r
798                 {\r
799                         return GL_TRUE;\r
800                 }\r
801         }\r
802 \r
803         return GL_FALSE;\r
804 }\r
805 \r
806 void GL_APIENTRY glBeginQuery(GLenum target, GLuint id)\r
807 {\r
808         TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);\r
809 \r
810         if(!ValidateQueryTarget(target))\r
811         {\r
812                 return error(GL_INVALID_ENUM);\r
813         }\r
814 \r
815         if(id == 0)\r
816         {\r
817                 return error(GL_INVALID_OPERATION);\r
818         }\r
819 \r
820         es2::Context *context = es2::getContext();\r
821 \r
822         if(context)\r
823         {\r
824                 context->beginQuery(target, id);\r
825         }\r
826 }\r
827 \r
828 void GL_APIENTRY glEndQuery(GLenum target)\r
829 {\r
830         TRACE("(GLenum target = 0x%X)", target);\r
831 \r
832         if(!ValidateQueryTarget(target))\r
833         {\r
834                 return error(GL_INVALID_ENUM);\r
835         }\r
836 \r
837         es2::Context *context = es2::getContext();\r
838 \r
839         if(context)\r
840         {\r
841                 context->endQuery(target);\r
842         }\r
843 }\r
844 \r
845 void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint *params)\r
846 {\r
847         TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
848                   target, pname, params);\r
849 \r
850         if(!ValidateQueryTarget(target) || (pname != GL_CURRENT_QUERY))\r
851         {\r
852                 return error(GL_INVALID_ENUM);\r
853         }\r
854 \r
855         es2::Context *context = es2::getContext();\r
856 \r
857         if(context)\r
858         {\r
859                 params[0] = context->getActiveQuery(target);\r
860         }\r
861 }\r
862 \r
863 void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)\r
864 {\r
865         TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
866               id, pname, params);\r
867 \r
868         switch(pname)\r
869         {\r
870         case GL_QUERY_RESULT:\r
871         case GL_QUERY_RESULT_AVAILABLE:\r
872                 break;\r
873         default:\r
874                 return error(GL_INVALID_ENUM);\r
875         }\r
876 \r
877         es2::Context *context = es2::getContext();\r
878 \r
879         if(context)\r
880         {\r
881                 es2::Query *queryObject = context->getQuery(id, false, GL_NONE);\r
882 \r
883                 if(!queryObject)\r
884                 {\r
885                         return error(GL_INVALID_OPERATION);\r
886                 }\r
887 \r
888                 if(context->getActiveQuery(queryObject->getType()) == id)\r
889                 {\r
890                         return error(GL_INVALID_OPERATION);\r
891                 }\r
892 \r
893                 switch(pname)\r
894                 {\r
895                 case GL_QUERY_RESULT:\r
896                         params[0] = queryObject->getResult();\r
897                         break;\r
898                 case GL_QUERY_RESULT_AVAILABLE:\r
899                         params[0] = queryObject->isResultAvailable();\r
900                         break;\r
901                 default:\r
902                         ASSERT(false);\r
903                 }\r
904         }\r
905 }\r
906 \r
907 GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)\r
908 {\r
909         TRACE("(GLenum target = 0x%X)", target);\r
910 \r
911         UNIMPLEMENTED();\r
912         return GL_FALSE;\r
913 }\r
914 \r
915 void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params)\r
916 {\r
917         TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
918               target, pname, params);\r
919 \r
920         if(!ValidateBufferTarget(target))\r
921         {\r
922                 return error(GL_INVALID_ENUM);\r
923         }\r
924 \r
925         if(pname != GL_BUFFER_MAP_POINTER)\r
926         {\r
927                 return error(GL_INVALID_ENUM);\r
928         }\r
929 \r
930         UNIMPLEMENTED();\r
931 }\r
932 \r
933 void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs)\r
934 {\r
935         TRACE("(GLsizei n = %d, const GLenum *bufs = 0x%0.8p)", n, bufs);\r
936 \r
937         UNIMPLEMENTED();\r
938 }\r
939 \r
940 void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
941 {\r
942         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
943 \r
944         if(count < 0 || transpose != GL_FALSE)\r
945         {\r
946                 return error(GL_INVALID_VALUE);\r
947         }\r
948 \r
949         if(location == -1)\r
950         {\r
951                 return;\r
952         }\r
953 \r
954         es2::Context *context = es2::getContext();\r
955 \r
956         if(context)\r
957         {\r
958                 es2::Program *program = context->getCurrentProgram();\r
959 \r
960                 if(!program)\r
961                 {\r
962                         return error(GL_INVALID_OPERATION);\r
963                 }\r
964 \r
965                 if(!program->setUniformMatrix2x3fv(location, count, value))\r
966                 {\r
967                         return error(GL_INVALID_OPERATION);\r
968                 }\r
969         }\r
970 }\r
971 \r
972 void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
973 {\r
974         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
975 \r
976         if(count < 0 || transpose != GL_FALSE)\r
977         {\r
978                 return error(GL_INVALID_VALUE);\r
979         }\r
980 \r
981         if(location == -1)\r
982         {\r
983                 return;\r
984         }\r
985 \r
986         es2::Context *context = es2::getContext();\r
987 \r
988         if(context)\r
989         {\r
990                 es2::Program *program = context->getCurrentProgram();\r
991 \r
992                 if(!program)\r
993                 {\r
994                         return error(GL_INVALID_OPERATION);\r
995                 }\r
996 \r
997                 if(!program->setUniformMatrix3x2fv(location, count, value))\r
998                 {\r
999                         return error(GL_INVALID_OPERATION);\r
1000                 }\r
1001         }\r
1002 }\r
1003 \r
1004 void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
1005 {\r
1006         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
1007 \r
1008         if(count < 0 || transpose != GL_FALSE)\r
1009         {\r
1010                 return error(GL_INVALID_VALUE);\r
1011         }\r
1012 \r
1013         if(location == -1)\r
1014         {\r
1015                 return;\r
1016         }\r
1017 \r
1018         es2::Context *context = es2::getContext();\r
1019 \r
1020         if(context)\r
1021         {\r
1022                 es2::Program *program = context->getCurrentProgram();\r
1023 \r
1024                 if(!program)\r
1025                 {\r
1026                         return error(GL_INVALID_OPERATION);\r
1027                 }\r
1028 \r
1029                 if(!program->setUniformMatrix2x4fv(location, count, value))\r
1030                 {\r
1031                         return error(GL_INVALID_OPERATION);\r
1032                 }\r
1033         }\r
1034 }\r
1035 \r
1036 void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
1037 {\r
1038         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
1039 \r
1040         if(count < 0 || transpose != GL_FALSE)\r
1041         {\r
1042                 return error(GL_INVALID_VALUE);\r
1043         }\r
1044 \r
1045         if(location == -1)\r
1046         {\r
1047                 return;\r
1048         }\r
1049 \r
1050         es2::Context *context = es2::getContext();\r
1051 \r
1052         if(context)\r
1053         {\r
1054                 es2::Program *program = context->getCurrentProgram();\r
1055 \r
1056                 if(!program)\r
1057                 {\r
1058                         return error(GL_INVALID_OPERATION);\r
1059                 }\r
1060 \r
1061                 if(!program->setUniformMatrix4x2fv(location, count, value))\r
1062                 {\r
1063                         return error(GL_INVALID_OPERATION);\r
1064                 }\r
1065         }\r
1066 }\r
1067 \r
1068 void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
1069 {\r
1070         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
1071 \r
1072         if(count < 0 || transpose != GL_FALSE)\r
1073         {\r
1074                 return error(GL_INVALID_VALUE);\r
1075         }\r
1076 \r
1077         if(location == -1)\r
1078         {\r
1079                 return;\r
1080         }\r
1081 \r
1082         es2::Context *context = es2::getContext();\r
1083 \r
1084         if(context)\r
1085         {\r
1086                 es2::Program *program = context->getCurrentProgram();\r
1087 \r
1088                 if(!program)\r
1089                 {\r
1090                         return error(GL_INVALID_OPERATION);\r
1091                 }\r
1092 \r
1093                 if(!program->setUniformMatrix3x4fv(location, count, value))\r
1094                 {\r
1095                         return error(GL_INVALID_OPERATION);\r
1096                 }\r
1097         }\r
1098 }\r
1099 \r
1100 void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)\r
1101 {\r
1102         TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = 0x%0.8p)", location, count, transpose, value);\r
1103 \r
1104         if(count < 0 || transpose != GL_FALSE)\r
1105         {\r
1106                 return error(GL_INVALID_VALUE);\r
1107         }\r
1108 \r
1109         if(location == -1)\r
1110         {\r
1111                 return;\r
1112         }\r
1113 \r
1114         es2::Context *context = es2::getContext();\r
1115 \r
1116         if(context)\r
1117         {\r
1118                 es2::Program *program = context->getCurrentProgram();\r
1119 \r
1120                 if(!program)\r
1121                 {\r
1122                         return error(GL_INVALID_OPERATION);\r
1123                 }\r
1124 \r
1125                 if(!program->setUniformMatrix4x3fv(location, count, value))\r
1126                 {\r
1127                         return error(GL_INVALID_OPERATION);\r
1128                 }\r
1129         }\r
1130 }\r
1131 \r
1132 void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)\r
1133 {\r
1134         TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "\r
1135               "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "\r
1136               "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",\r
1137               srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);\r
1138 \r
1139         switch(filter)\r
1140         {\r
1141         case GL_NEAREST:\r
1142         case GL_LINEAR:\r
1143                 break;\r
1144         default:\r
1145                 return error(GL_INVALID_ENUM);\r
1146         }\r
1147 \r
1148         if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)\r
1149         {\r
1150                 return error(GL_INVALID_VALUE);\r
1151         }\r
1152 \r
1153         es2::Context *context = es2::getContext();\r
1154 \r
1155         if(context)\r
1156         {\r
1157                 if(context->getReadFramebufferName() == context->getDrawFramebufferName())\r
1158                 {\r
1159                         ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");\r
1160                         return error(GL_INVALID_OPERATION);\r
1161                 }\r
1162 \r
1163                 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);\r
1164         }\r
1165 }\r
1166 \r
1167 void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)\r
1168 {\r
1169         TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",\r
1170               target, samples, internalformat, width, height);\r
1171 \r
1172         switch(target)\r
1173         {\r
1174         case GL_RENDERBUFFER:\r
1175                 break;\r
1176         default:\r
1177                 return error(GL_INVALID_ENUM);\r
1178         }\r
1179 \r
1180         if(!es2::IsColorRenderable(internalformat) && !es2::IsDepthRenderable(internalformat) && !es2::IsStencilRenderable(internalformat))\r
1181         {\r
1182                 return error(GL_INVALID_ENUM);\r
1183         }\r
1184 \r
1185         if(width < 0 || height < 0 || samples < 0)\r
1186         {\r
1187                 return error(GL_INVALID_VALUE);\r
1188         }\r
1189 \r
1190         es2::Context *context = es2::getContext();\r
1191 \r
1192         if(context)\r
1193         {\r
1194                 if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||\r
1195                         height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||\r
1196                         samples > es2::IMPLEMENTATION_MAX_SAMPLES)\r
1197                 {\r
1198                         return error(GL_INVALID_VALUE);\r
1199                 }\r
1200 \r
1201                 GLuint handle = context->getRenderbufferName();\r
1202                 if(handle == 0)\r
1203                 {\r
1204                         return error(GL_INVALID_OPERATION);\r
1205                 }\r
1206 \r
1207                 switch(internalformat)\r
1208                 {\r
1209                 case GL_DEPTH_COMPONENT16:\r
1210                 case GL_DEPTH_COMPONENT24:\r
1211                 case GL_DEPTH_COMPONENT32F:\r
1212                         context->setRenderbufferStorage(new es2::Depthbuffer(width, height, samples));\r
1213                         break;\r
1214                 case GL_R8UI:\r
1215                 case GL_R8I:\r
1216                 case GL_R16UI:\r
1217                 case GL_R16I:\r
1218                 case GL_R32UI:\r
1219                 case GL_R32I:\r
1220                 case GL_RG8UI:\r
1221                 case GL_RG8I:\r
1222                 case GL_RG16UI:\r
1223                 case GL_RG16I:\r
1224                 case GL_RG32UI:\r
1225                 case GL_RG32I:\r
1226                 case GL_RGB8UI:\r
1227                 case GL_RGB8I:\r
1228                 case GL_RGB16UI:\r
1229                 case GL_RGB16I:\r
1230                 case GL_RGB32UI:\r
1231                 case GL_RGB32I:\r
1232                 case GL_RGBA8UI:\r
1233                 case GL_RGBA8I:\r
1234                 case GL_RGB10_A2UI:\r
1235                 case GL_RGBA16UI:\r
1236                 case GL_RGBA16I:\r
1237                 case GL_RGBA32UI:\r
1238                 case GL_RGBA32I:\r
1239                         if(samples > 0)\r
1240                         {\r
1241                                 return error(GL_INVALID_OPERATION);\r
1242                         }\r
1243                 case GL_RGBA4:\r
1244                 case GL_RGB5_A1:\r
1245                 case GL_RGB565:\r
1246                 case GL_SRGB8_ALPHA8:\r
1247                 case GL_RGB10_A2:\r
1248                 case GL_R8:\r
1249                 case GL_RG8:\r
1250                 case GL_RGB8:\r
1251                 case GL_RGBA8:\r
1252                         context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));\r
1253                         break;\r
1254                 case GL_STENCIL_INDEX8:\r
1255                         context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));\r
1256                         break;\r
1257                 case GL_DEPTH24_STENCIL8:\r
1258                 case GL_DEPTH32F_STENCIL8:\r
1259                         context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, samples));\r
1260                         break;\r
1261 \r
1262                 default:\r
1263                         return error(GL_INVALID_ENUM);\r
1264                 }\r
1265         }\r
1266 }\r
1267 \r
1268 void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)\r
1269 {\r
1270         TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",\r
1271               target, attachment, texture, level, layer);\r
1272         \r
1273         switch(target)\r
1274         {\r
1275         case GL_DRAW_FRAMEBUFFER:\r
1276         case GL_READ_FRAMEBUFFER:\r
1277         case GL_FRAMEBUFFER:\r
1278                 break;\r
1279         default:\r
1280                 return error(GL_INVALID_ENUM);\r
1281         }\r
1282 \r
1283         switch(attachment)\r
1284         {\r
1285         case GL_COLOR_ATTACHMENT0:\r
1286         case GL_COLOR_ATTACHMENT1:\r
1287         case GL_COLOR_ATTACHMENT2:\r
1288         case GL_COLOR_ATTACHMENT3:\r
1289         case GL_COLOR_ATTACHMENT4:\r
1290         case GL_COLOR_ATTACHMENT5:\r
1291         case GL_COLOR_ATTACHMENT6:\r
1292         case GL_COLOR_ATTACHMENT7:\r
1293         case GL_COLOR_ATTACHMENT8:\r
1294         case GL_COLOR_ATTACHMENT9:\r
1295         case GL_COLOR_ATTACHMENT10:\r
1296         case GL_COLOR_ATTACHMENT11:\r
1297         case GL_COLOR_ATTACHMENT12:\r
1298         case GL_COLOR_ATTACHMENT13:\r
1299         case GL_COLOR_ATTACHMENT14:\r
1300         case GL_COLOR_ATTACHMENT15:\r
1301         case GL_DEPTH_ATTACHMENT:\r
1302         case GL_STENCIL_ATTACHMENT:\r
1303         case GL_DEPTH_STENCIL_ATTACHMENT:\r
1304                 break;\r
1305         default:\r
1306                 return error(GL_INVALID_ENUM);\r
1307         }\r
1308 \r
1309         UNIMPLEMENTED();\r
1310 }\r
1311 \r
1312 void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)\r
1313 {\r
1314         TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",\r
1315               target, offset, length, access);\r
1316 \r
1317         GLint bufferSize;\r
1318         glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufferSize);\r
1319         if((offset < 0) || (length<0) || ((offset + length) > bufferSize))\r
1320         {\r
1321                 error(GL_INVALID_VALUE);\r
1322         }\r
1323 \r
1324                 if((access & ~(GL_MAP_READ_BIT |\r
1325                                GL_MAP_WRITE_BIT |\r
1326                                GL_MAP_INVALIDATE_RANGE_BIT |\r
1327                                GL_MAP_INVALIDATE_BUFFER_BIT |\r
1328                                GL_MAP_FLUSH_EXPLICIT_BIT |\r
1329                                GL_MAP_UNSYNCHRONIZED_BIT)) != 0)\r
1330                 {\r
1331                         error(GL_INVALID_VALUE);\r
1332                 }\r
1333 \r
1334         UNIMPLEMENTED();\r
1335         return nullptr;\r
1336 }\r
1337 \r
1338 void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)\r
1339 {\r
1340         TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d)",\r
1341               target, offset, length);\r
1342 \r
1343         if(!ValidateBufferTarget(target))\r
1344         {\r
1345                 return error(GL_INVALID_ENUM);\r
1346         }\r
1347 \r
1348         if((offset < 0) || (length<0)) // FIXME: also check if offset + length exceeds the size of the mapping\r
1349         {\r
1350                 error(GL_INVALID_VALUE);\r
1351         }\r
1352 \r
1353         UNIMPLEMENTED();\r
1354 }\r
1355 \r
1356 void GL_APIENTRY glBindVertexArray(GLuint array)\r
1357 {\r
1358         TRACE("(GLuint array = %d)", array);\r
1359 \r
1360         if(array == 0)\r
1361         {\r
1362                 return;\r
1363         }\r
1364 \r
1365         es2::Context *context = es2::getContext();\r
1366 \r
1367         if(context && !context->bindVertexArray(array))\r
1368         {\r
1369                 return error(GL_INVALID_OPERATION);\r
1370         }\r
1371 }\r
1372 \r
1373 void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)\r
1374 {\r
1375         TRACE("(GLsizei n = %d, const GLuint *arrays = 0x%0.8p)", n, arrays);\r
1376 \r
1377         if(n < 0)\r
1378         {\r
1379                 return error(GL_INVALID_VALUE);\r
1380         }\r
1381 \r
1382         es2::Context *context = es2::getContext();\r
1383 \r
1384         if(context)\r
1385         {\r
1386                 for(int i = 0; i < n; i++)\r
1387                 {\r
1388                         context->deleteVertexArray(arrays[i]);\r
1389                 }\r
1390         }\r
1391 }\r
1392 \r
1393 void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)\r
1394 {\r
1395         TRACE("(GLsizei n = %d, const GLuint *arrays = 0x%0.8p)", n, arrays);\r
1396 \r
1397         if(n < 0)\r
1398         {\r
1399                 return error(GL_INVALID_VALUE);\r
1400         }\r
1401 \r
1402         es2::Context *context = es2::getContext();\r
1403 \r
1404         if(context)\r
1405         {\r
1406                 for(int i = 0; i < n; i++)\r
1407                 {\r
1408                         arrays[i] = context->createVertexArray();\r
1409                 }\r
1410         }\r
1411 }\r
1412 \r
1413 GLboolean GL_APIENTRY glIsVertexArray(GLuint array)\r
1414 {\r
1415         TRACE("(GLuint array = %d)", array);\r
1416 \r
1417         if(array == 0)\r
1418         {\r
1419                 return GL_FALSE;\r
1420         }\r
1421 \r
1422         es2::Context *context = es2::getContext();\r
1423 \r
1424         if(context)\r
1425         {\r
1426                 es2::VertexArray *arrayObject = context->getVertexArray(array);\r
1427 \r
1428                 if(arrayObject)\r
1429                 {\r
1430                         return GL_TRUE;\r
1431                 }\r
1432         }\r
1433 \r
1434         return GL_FALSE;\r
1435 }\r
1436 \r
1437 void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)\r
1438 {\r
1439         TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint* data = 0x%0.8p)",\r
1440               target, index, data);\r
1441 \r
1442         es2::Context *context = es2::getContext();\r
1443 \r
1444         if(context)\r
1445         {\r
1446                 if(!context->getTransformFeedbackiv(index, target, data) &&\r
1447                    !context->getIntegerv(target, data))\r
1448                 {\r
1449                         GLenum nativeType;\r
1450                         unsigned int numParams = 0;\r
1451                         if(!context->getQueryParameterInfo(target, &nativeType, &numParams))\r
1452                                 return error(GL_INVALID_ENUM);\r
1453 \r
1454                         if(numParams == 0)\r
1455                                 return; // it is known that target is valid, but there are no parameters to return\r
1456 \r
1457                         if(nativeType == GL_BOOL)\r
1458                         {\r
1459                                 GLboolean *boolParams = NULL;\r
1460                                 boolParams = new GLboolean[numParams];\r
1461 \r
1462                                 context->getBooleanv(target, boolParams);\r
1463 \r
1464                                 for(unsigned int i = 0; i < numParams; ++i)\r
1465                                 {\r
1466                                         data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;\r
1467                                 }\r
1468 \r
1469                                 delete[] boolParams;\r
1470                         }\r
1471                         else if(nativeType == GL_FLOAT)\r
1472                         {\r
1473                                 GLfloat *floatParams = NULL;\r
1474                                 floatParams = new GLfloat[numParams];\r
1475 \r
1476                                 context->getFloatv(target, floatParams);\r
1477 \r
1478                                 for(unsigned int i = 0; i < numParams; ++i)\r
1479                                 {\r
1480                                         if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)\r
1481                                         {\r
1482                                                 data[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) * 0.5f);\r
1483                                         }\r
1484                                         else\r
1485                                         {\r
1486                                                 data[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));\r
1487                                         }\r
1488                                 }\r
1489 \r
1490                                 delete[] floatParams;\r
1491                         }\r
1492                 }\r
1493         }\r
1494 }\r
1495 \r
1496 void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)\r
1497 {\r
1498         TRACE("(GLenum primitiveMode = 0x%X)", primitiveMode);\r
1499 \r
1500         switch(primitiveMode)\r
1501         {\r
1502         case GL_POINTS:\r
1503         case GL_LINES:\r
1504         case GL_TRIANGLES:\r
1505                 break;\r
1506         default:\r
1507                 return error(GL_INVALID_ENUM);\r
1508         }\r
1509 \r
1510         es2::Context *context = es2::getContext();\r
1511 \r
1512         if(context)\r
1513         {\r
1514                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();\r
1515 \r
1516                 if(transformFeedbackObject)\r
1517                 {\r
1518                         if(transformFeedbackObject->isActive())\r
1519                         {\r
1520                                 return error(GL_INVALID_OPERATION);\r
1521                         }\r
1522                         transformFeedbackObject->begin(primitiveMode);\r
1523                 }\r
1524                 else\r
1525                 {\r
1526                         return error(GL_INVALID_OPERATION);\r
1527                 }\r
1528         }\r
1529 }\r
1530 \r
1531 void GL_APIENTRY glEndTransformFeedback(void)\r
1532 {\r
1533         TRACE("()");\r
1534 \r
1535         es2::Context *context = es2::getContext();\r
1536 \r
1537         if(context)\r
1538         {\r
1539                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();\r
1540 \r
1541                 if(transformFeedbackObject)\r
1542                 {\r
1543                         if(!transformFeedbackObject->isActive())\r
1544                         {\r
1545                                 return error(GL_INVALID_OPERATION);\r
1546                         }\r
1547                         transformFeedbackObject->end();\r
1548                 }\r
1549                 else\r
1550                 {\r
1551                         return error(GL_INVALID_OPERATION);\r
1552                 }\r
1553         }\r
1554 }\r
1555 \r
1556 void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)\r
1557 {\r
1558         TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)",\r
1559               target, index, buffer, offset, size);\r
1560 \r
1561         if(buffer != 0 && size <= 0)\r
1562         {\r
1563                 return error(GL_INVALID_VALUE);\r
1564         }\r
1565 \r
1566         es2::Context *context = es2::getContext();\r
1567 \r
1568         if(context)\r
1569         {\r
1570                 switch(target)\r
1571                 {\r
1572                 case GL_TRANSFORM_FEEDBACK_BUFFER:\r
1573                         if(index >= es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)\r
1574                         {\r
1575                                 return error(GL_INVALID_VALUE);\r
1576                         }\r
1577                         if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4\r
1578                         {\r
1579                                 return error(GL_INVALID_VALUE);\r
1580                         }\r
1581                         else\r
1582                         {\r
1583                                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();\r
1584                                 transformFeedback->setBuffer(index, context->getBuffer(buffer), offset, size);\r
1585                         }\r
1586                         break;\r
1587                 case GL_UNIFORM_BUFFER:\r
1588                         if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)\r
1589                         {\r
1590                                 return error(GL_INVALID_VALUE);\r
1591                         }\r
1592                         if(offset % es2::IMPLEMENTATION_UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0)\r
1593                         {\r
1594                                 return error(GL_INVALID_VALUE);\r
1595                         }\r
1596                         UNIMPLEMENTED();\r
1597                         break;\r
1598                 default:\r
1599                         return error(GL_INVALID_ENUM);\r
1600                 }\r
1601         }\r
1602 }\r
1603 \r
1604 void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)\r
1605 {\r
1606         TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)",\r
1607               target, index, buffer);\r
1608 \r
1609         es2::Context *context = es2::getContext();\r
1610 \r
1611         if(context)\r
1612         {\r
1613                 switch(target)\r
1614                 {\r
1615                 case GL_TRANSFORM_FEEDBACK_BUFFER:\r
1616                         if(index >= es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)\r
1617                         {\r
1618                                 return error(GL_INVALID_VALUE);\r
1619                         }\r
1620                         else\r
1621                         {\r
1622                                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();\r
1623                                 transformFeedback->setBuffer(index, context->getBuffer(buffer));\r
1624                         }\r
1625                         break;\r
1626                 case GL_UNIFORM_BUFFER:\r
1627                         if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)\r
1628                         {\r
1629                                 return error(GL_INVALID_VALUE);\r
1630                         }\r
1631                         UNIMPLEMENTED();\r
1632                         break;\r
1633                 default:\r
1634                         return error(GL_INVALID_ENUM);\r
1635                 }\r
1636         }\r
1637 }\r
1638 \r
1639 void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)\r
1640 {\r
1641         TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",\r
1642               program, count, varyings, bufferMode);\r
1643 \r
1644         switch(bufferMode)\r
1645         {\r
1646         case GL_SEPARATE_ATTRIBS:\r
1647                 if(count > es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)\r
1648                 {\r
1649                         return error(GL_INVALID_VALUE);\r
1650                 }\r
1651         case GL_INTERLEAVED_ATTRIBS:\r
1652                 break;\r
1653         default:\r
1654                 return error(GL_INVALID_ENUM);\r
1655         }\r
1656 \r
1657         es2::Context *context = es2::getContext();\r
1658 \r
1659         if(context)\r
1660         {\r
1661                 es2::Program *programObject = context->getProgram(program);\r
1662 \r
1663                 if(!programObject)\r
1664                 {\r
1665                         return error(GL_INVALID_VALUE);\r
1666                 }\r
1667         }\r
1668 \r
1669         UNIMPLEMENTED();\r
1670 }\r
1671 \r
1672 void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)\r
1673 {\r
1674         TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLsizei *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",\r
1675               program, index, bufSize, length, size, type, name);\r
1676 \r
1677         es2::Context *context = es2::getContext();\r
1678 \r
1679         if(context)\r
1680         {\r
1681                 es2::Program *programObject = context->getProgram(program);\r
1682 \r
1683                 if(!programObject)\r
1684                 {\r
1685                         return error(GL_INVALID_VALUE);\r
1686                 }\r
1687         }\r
1688 \r
1689         UNIMPLEMENTED();\r
1690 }\r
1691 \r
1692 void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)\r
1693 {\r
1694         TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLsizei *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",\r
1695               index, size, type, stride, pointer);\r
1696 \r
1697         if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1698         {\r
1699                 return error(GL_INVALID_VALUE);\r
1700         }\r
1701 \r
1702         if(size < 1 || size > 4 || stride < 0)\r
1703         {\r
1704                 return error(GL_INVALID_VALUE);\r
1705         }\r
1706 \r
1707         switch(type)\r
1708         {\r
1709         case GL_BYTE:\r
1710         case GL_UNSIGNED_BYTE:\r
1711         case GL_SHORT:\r
1712         case GL_UNSIGNED_SHORT:\r
1713         case GL_INT:\r
1714         case GL_UNSIGNED_INT:\r
1715                 break;\r
1716         default:\r
1717                 return error(GL_INVALID_ENUM);\r
1718         }\r
1719 \r
1720         es2::Context *context = es2::getContext();\r
1721 \r
1722         if(context)\r
1723         {\r
1724                 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, stride, pointer);\r
1725         }\r
1726 }\r
1727 \r
1728 void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)\r
1729 {\r
1730         TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
1731               index, pname, params);\r
1732 \r
1733         es2::Context *context = es2::getContext();\r
1734 \r
1735         if(context)\r
1736         {\r
1737                 if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1738                 {\r
1739                         return error(GL_INVALID_VALUE);\r
1740                 }\r
1741 \r
1742                 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);\r
1743 \r
1744                 switch(pname)\r
1745                 {\r
1746                 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:\r
1747                         *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);\r
1748                         break;\r
1749                 case GL_VERTEX_ATTRIB_ARRAY_SIZE:\r
1750                         *params = attribState.mSize;\r
1751                         break;\r
1752                 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:\r
1753                         *params = attribState.mStride;\r
1754                         break;\r
1755                 case GL_VERTEX_ATTRIB_ARRAY_TYPE:\r
1756                         *params = attribState.mType;\r
1757                         break;\r
1758                 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:\r
1759                         *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);\r
1760                         break;\r
1761                 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:\r
1762                         *params = attribState.mBoundBuffer.name();\r
1763                         break;\r
1764                 case GL_CURRENT_VERTEX_ATTRIB:\r
1765                         for(int i = 0; i < 4; ++i)\r
1766                         {\r
1767                                 params[i] = attribState.getCurrentValueI(i);\r
1768                         }\r
1769                         break;\r
1770                 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:\r
1771                         switch(attribState.mType)\r
1772                         {\r
1773                         case GL_BYTE:\r
1774                         case GL_UNSIGNED_BYTE:\r
1775                         case GL_SHORT:\r
1776                         case GL_UNSIGNED_SHORT:\r
1777                         case GL_INT:\r
1778                         case GL_INT_2_10_10_10_REV:\r
1779                         case GL_UNSIGNED_INT:\r
1780                         case GL_FIXED:\r
1781                                 *params = GL_TRUE;\r
1782                                 break;\r
1783                         default:\r
1784                                 *params = GL_FALSE;\r
1785                                 break;\r
1786                         }\r
1787                         break;\r
1788                 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:\r
1789                         *params = attribState.mDivisor;\r
1790                         break;\r
1791                 default: return error(GL_INVALID_ENUM);\r
1792                 }\r
1793         }\r
1794 }\r
1795 \r
1796 void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)\r
1797 {\r
1798         TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)",\r
1799                 index, pname, params);\r
1800 \r
1801         es2::Context *context = es2::getContext();\r
1802 \r
1803         if(context)\r
1804         {\r
1805                 if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1806                 {\r
1807                         return error(GL_INVALID_VALUE);\r
1808                 }\r
1809 \r
1810                 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);\r
1811 \r
1812                 switch(pname)\r
1813                 {\r
1814                 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:\r
1815                         *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);\r
1816                         break;\r
1817                 case GL_VERTEX_ATTRIB_ARRAY_SIZE:\r
1818                         *params = attribState.mSize;\r
1819                         break;\r
1820                 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:\r
1821                         *params = attribState.mStride;\r
1822                         break;\r
1823                 case GL_VERTEX_ATTRIB_ARRAY_TYPE:\r
1824                         *params = attribState.mType;\r
1825                         break;\r
1826                 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:\r
1827                         *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);\r
1828                         break;\r
1829                 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:\r
1830                         *params = attribState.mBoundBuffer.name();\r
1831                         break;\r
1832                 case GL_CURRENT_VERTEX_ATTRIB:\r
1833                         for(int i = 0; i < 4; ++i)\r
1834                         {\r
1835                                 params[i] = attribState.getCurrentValueUI(i);\r
1836                         }\r
1837                         break;\r
1838                 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:\r
1839                         switch(attribState.mType)\r
1840                         {\r
1841                         case GL_BYTE:\r
1842                         case GL_UNSIGNED_BYTE:\r
1843                         case GL_SHORT:\r
1844                         case GL_UNSIGNED_SHORT:\r
1845                         case GL_INT:\r
1846                         case GL_INT_2_10_10_10_REV:\r
1847                         case GL_UNSIGNED_INT:\r
1848                         case GL_FIXED:\r
1849                                 *params = GL_TRUE;\r
1850                                 break;\r
1851                         default:\r
1852                                 *params = GL_FALSE;\r
1853                                 break;\r
1854                         }\r
1855                         break;\r
1856                 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:\r
1857                         *params = attribState.mDivisor;\r
1858                         break;\r
1859                 default: return error(GL_INVALID_ENUM);\r
1860                 }\r
1861         }\r
1862 }\r
1863 \r
1864 void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)\r
1865 {\r
1866         TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",\r
1867               index, x, y, z, w);\r
1868 \r
1869         if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1870         {\r
1871                 return error(GL_INVALID_VALUE);\r
1872         }\r
1873 \r
1874         es2::Context *context = es2::getContext();\r
1875 \r
1876         if(context)\r
1877         {\r
1878                 GLint vals[4] = { x, y, z, w };\r
1879                 context->setVertexAttrib(index, vals);\r
1880         }\r
1881 }\r
1882 \r
1883 void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)\r
1884 {\r
1885         TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",\r
1886               index, x, y, z, w);\r
1887 \r
1888         if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1889         {\r
1890                 return error(GL_INVALID_VALUE);\r
1891         }\r
1892 \r
1893         es2::Context *context = es2::getContext();\r
1894 \r
1895         if(context)\r
1896         {\r
1897                 GLuint vals[4] = { x, y, z, w };\r
1898                 context->setVertexAttrib(index, vals);\r
1899         }\r
1900 }\r
1901 \r
1902 void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)\r
1903 {\r
1904         TRACE("(GLuint index = %d, GLint *v = 0x%0.8p)", index, v);\r
1905 \r
1906         if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1907         {\r
1908                 return error(GL_INVALID_VALUE);\r
1909         }\r
1910 \r
1911         es2::Context *context = es2::getContext();\r
1912 \r
1913         if(context)\r
1914         {\r
1915                 context->setVertexAttrib(index, v);\r
1916         }\r
1917 }\r
1918 \r
1919 void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)\r
1920 {\r
1921         TRACE("(GLuint index = %d, GLint *v = 0x%0.8p)", index, v);\r
1922 \r
1923         if(index >= es2::MAX_VERTEX_ATTRIBS)\r
1924         {\r
1925                 return error(GL_INVALID_VALUE);\r
1926         }\r
1927 \r
1928         es2::Context *context = es2::getContext();\r
1929 \r
1930         if(context)\r
1931         {\r
1932                 context->setVertexAttrib(index, v);\r
1933         }\r
1934 }\r
1935 \r
1936 void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)\r
1937 {\r
1938         TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = 0x%0.8p)",\r
1939               program, location, params);\r
1940 \r
1941         es2::Context *context = es2::getContext();\r
1942 \r
1943         if(context)\r
1944         {\r
1945                 if(program == 0)\r
1946                 {\r
1947                         return error(GL_INVALID_VALUE);\r
1948                 }\r
1949 \r
1950                 es2::Program *programObject = context->getProgram(program);\r
1951 \r
1952                 if(!programObject || !programObject->isLinked())\r
1953                 {\r
1954                         return error(GL_INVALID_OPERATION);\r
1955                 }\r
1956 \r
1957                 if(!programObject)\r
1958                 {\r
1959                         return error(GL_INVALID_OPERATION);\r
1960                 }\r
1961 \r
1962                 if(!programObject->getUniformuiv(location, NULL, params))\r
1963                 {\r
1964                         return error(GL_INVALID_OPERATION);\r
1965                 }\r
1966         }\r
1967 }\r
1968 \r
1969 GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)\r
1970 {\r
1971         TRACE("(GLuint program = %d, const GLchar *name = 0x%0.8p)", program, name);\r
1972 \r
1973         es2::Context *context = es2::getContext();\r
1974 \r
1975         if(strstr(name, "gl_") == name)\r
1976         {\r
1977                 return -1;\r
1978         }\r
1979 \r
1980         if(context)\r
1981         {\r
1982                 es2::Program *programObject = context->getProgram(program);\r
1983 \r
1984                 if(!programObject)\r
1985                 {\r
1986                         if(context->getShader(program))\r
1987                         {\r
1988                                 return error(GL_INVALID_OPERATION, -1);\r
1989                         }\r
1990                         else\r
1991                         {\r
1992                                 return error(GL_INVALID_VALUE, -1);\r
1993                         }\r
1994                 }\r
1995 \r
1996                 if(!programObject->isLinked())\r
1997                 {\r
1998                         return error(GL_INVALID_OPERATION, -1);\r
1999                 }\r
2000         }\r
2001 \r
2002         UNIMPLEMENTED();\r
2003         return -1;\r
2004 }\r
2005 \r
2006 void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)\r
2007 {\r
2008         glUniform1uiv(location, 1, &v0);\r
2009 }\r
2010 \r
2011 void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)\r
2012 {\r
2013         GLuint xy[2] = { v0, v1 };\r
2014 \r
2015         glUniform2uiv(location, 1, (GLuint*)&xy);\r
2016 }\r
2017 \r
2018 void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)\r
2019 {\r
2020         GLuint xyz[3] = { v0, v1, v2 };\r
2021 \r
2022         glUniform3uiv(location, 1, (GLuint*)&xyz);\r
2023 }\r
2024 \r
2025 void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)\r
2026 {\r
2027         GLuint xyzw[4] = { v0, v1, v2, v3 };\r
2028 \r
2029         glUniform4uiv(location, 1, (GLuint*)&xyzw);\r
2030 }\r
2031 \r
2032 void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)\r
2033 {\r
2034         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)",\r
2035               location, count, value);\r
2036         \r
2037         if(count < 0)\r
2038         {\r
2039                 return error(GL_INVALID_VALUE);\r
2040         }\r
2041 \r
2042         if(location == -1)\r
2043         {\r
2044                 return;\r
2045         }\r
2046 \r
2047         es2::Context *context = es2::getContext();\r
2048 \r
2049         if(context)\r
2050         {\r
2051                 es2::Program *program = context->getCurrentProgram();\r
2052 \r
2053                 if(!program)\r
2054                 {\r
2055                         return error(GL_INVALID_OPERATION);\r
2056                 }\r
2057 \r
2058                 if(!program->setUniform1uiv(location, count, value))\r
2059                 {\r
2060                         return error(GL_INVALID_OPERATION);\r
2061                 }\r
2062         }\r
2063 }\r
2064 \r
2065 void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)\r
2066 {\r
2067         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)",\r
2068               location, count, value);\r
2069 \r
2070         if(count < 0)\r
2071         {\r
2072                 return error(GL_INVALID_VALUE);\r
2073         }\r
2074 \r
2075         if(location == -1)\r
2076         {\r
2077                 return;\r
2078         }\r
2079 \r
2080         es2::Context *context = es2::getContext();\r
2081 \r
2082         if(context)\r
2083         {\r
2084                 es2::Program *program = context->getCurrentProgram();\r
2085 \r
2086                 if(!program)\r
2087                 {\r
2088                         return error(GL_INVALID_OPERATION);\r
2089                 }\r
2090 \r
2091                 if(!program->setUniform2uiv(location, count, value))\r
2092                 {\r
2093                         return error(GL_INVALID_OPERATION);\r
2094                 }\r
2095         }\r
2096 }\r
2097 \r
2098 void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)\r
2099 {\r
2100         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)",\r
2101               location, count, value);\r
2102 \r
2103         if(count < 0)\r
2104         {\r
2105                 return error(GL_INVALID_VALUE);\r
2106         }\r
2107 \r
2108         if(location == -1)\r
2109         {\r
2110                 return;\r
2111         }\r
2112 \r
2113         es2::Context *context = es2::getContext();\r
2114 \r
2115         if(context)\r
2116         {\r
2117                 es2::Program *program = context->getCurrentProgram();\r
2118 \r
2119                 if(!program)\r
2120                 {\r
2121                         return error(GL_INVALID_OPERATION);\r
2122                 }\r
2123 \r
2124                 if(!program->setUniform3uiv(location, count, value))\r
2125                 {\r
2126                         return error(GL_INVALID_OPERATION);\r
2127                 }\r
2128         }\r
2129 }\r
2130 \r
2131 void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)\r
2132 {\r
2133         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)",\r
2134               location, count, value);\r
2135 \r
2136         if(count < 0)\r
2137         {\r
2138                 return error(GL_INVALID_VALUE);\r
2139         }\r
2140 \r
2141         if(location == -1)\r
2142         {\r
2143                 return;\r
2144         }\r
2145 \r
2146         es2::Context *context = es2::getContext();\r
2147 \r
2148         if(context)\r
2149         {\r
2150                 es2::Program *program = context->getCurrentProgram();\r
2151 \r
2152                 if(!program)\r
2153                 {\r
2154                         return error(GL_INVALID_OPERATION);\r
2155                 }\r
2156 \r
2157                 if(!program->setUniform4uiv(location, count, value))\r
2158                 {\r
2159                         return error(GL_INVALID_OPERATION);\r
2160                 }\r
2161         }\r
2162 }\r
2163 \r
2164 void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)\r
2165 {\r
2166         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = 0x%0.8p)",\r
2167               buffer, drawbuffer, value);\r
2168 \r
2169         switch(buffer)\r
2170         {\r
2171         case GL_COLOR:\r
2172                 if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)\r
2173                 {\r
2174                         return error(GL_INVALID_VALUE);\r
2175                 }\r
2176                 break;\r
2177         case GL_STENCIL:\r
2178                 if(drawbuffer != 0)\r
2179                 {\r
2180                         return error(GL_INVALID_VALUE);\r
2181                 }\r
2182                 break;\r
2183         default:\r
2184                 return error(GL_INVALID_ENUM);\r
2185         }\r
2186 \r
2187         UNIMPLEMENTED();\r
2188 }\r
2189 \r
2190 void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)\r
2191 {\r
2192         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = 0x%0.8p)",\r
2193               buffer, drawbuffer, value);\r
2194 \r
2195         switch(buffer)\r
2196         {\r
2197         case GL_COLOR:\r
2198                 if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)\r
2199                 {\r
2200                         return error(GL_INVALID_VALUE);\r
2201                 }\r
2202                 break;\r
2203         default:\r
2204                 return error(GL_INVALID_ENUM);\r
2205         }\r
2206 \r
2207         UNIMPLEMENTED();\r
2208 }\r
2209 \r
2210 void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)\r
2211 {\r
2212         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = 0x%0.8p)",\r
2213               buffer, drawbuffer, value);\r
2214 \r
2215         switch(buffer)\r
2216         {\r
2217         case GL_COLOR:\r
2218                 if(drawbuffer > es2::IMPLEMENTATION_MAX_DRAW_BUFFERS)\r
2219                 {\r
2220                         return error(GL_INVALID_VALUE);\r
2221                 }\r
2222                 break;\r
2223         case GL_DEPTH:\r
2224                 if(drawbuffer != 0)\r
2225                 {\r
2226                         return error(GL_INVALID_VALUE);\r
2227                 }\r
2228                 break;\r
2229         default:\r
2230                 return error(GL_INVALID_ENUM);\r
2231         }\r
2232 \r
2233         UNIMPLEMENTED();\r
2234 }\r
2235 \r
2236 void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)\r
2237 {\r
2238         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",\r
2239               buffer, drawbuffer, depth, stencil);\r
2240 \r
2241         switch(buffer)\r
2242         {\r
2243         case GL_DEPTH_STENCIL:\r
2244                 if(drawbuffer != 0)\r
2245                 {\r
2246                         return error(GL_INVALID_VALUE);\r
2247                 }\r
2248                 break;\r
2249         default:\r
2250                 return error(GL_INVALID_ENUM);\r
2251         }\r
2252 \r
2253         UNIMPLEMENTED();\r
2254 }\r
2255 \r
2256 const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)\r
2257 {\r
2258         TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index);\r
2259 \r
2260         es2::Context *context = es2::getContext();\r
2261         if(context)\r
2262         {\r
2263                 GLuint numExtensions;\r
2264                 context->getExtensions(0, &numExtensions);\r
2265 \r
2266                 if(index >= numExtensions)\r
2267                 {\r
2268                         return error(GL_INVALID_VALUE, (GLubyte*)NULL);\r
2269                 }\r
2270 \r
2271                 switch(name)\r
2272                 {\r
2273                 case GL_EXTENSIONS:\r
2274                         return context->getExtensions(index);\r
2275                 default:\r
2276                         return error(GL_INVALID_ENUM, (GLubyte*)NULL);\r
2277                 }\r
2278         }\r
2279 \r
2280         return (GLubyte*)NULL;\r
2281 }\r
2282 \r
2283 void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)\r
2284 {\r
2285         TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X,  GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",\r
2286               readTarget, writeTarget, readOffset, writeOffset, size);\r
2287 \r
2288         switch(readTarget)\r
2289         {\r
2290         case GL_ARRAY_BUFFER:\r
2291         case GL_COPY_READ_BUFFER:\r
2292         case GL_COPY_WRITE_BUFFER:\r
2293         case GL_ELEMENT_ARRAY_BUFFER:\r
2294         case GL_PIXEL_PACK_BUFFER:\r
2295         case GL_PIXEL_UNPACK_BUFFER:\r
2296         case GL_TRANSFORM_FEEDBACK_BUFFER:\r
2297         case GL_UNIFORM_BUFFER:\r
2298                 break;\r
2299         default:\r
2300                 return error(GL_INVALID_ENUM);\r
2301         }\r
2302 \r
2303         switch(writeTarget)\r
2304         {\r
2305         case GL_ARRAY_BUFFER:\r
2306         case GL_COPY_READ_BUFFER:\r
2307         case GL_COPY_WRITE_BUFFER:\r
2308         case GL_ELEMENT_ARRAY_BUFFER:\r
2309         case GL_PIXEL_PACK_BUFFER:\r
2310         case GL_PIXEL_UNPACK_BUFFER:\r
2311         case GL_TRANSFORM_FEEDBACK_BUFFER:\r
2312         case GL_UNIFORM_BUFFER:\r
2313                 break;\r
2314         default:\r
2315                 return error(GL_INVALID_ENUM);\r
2316         }\r
2317 \r
2318         if(readOffset < 0 || writeOffset < 0 || size < 0)\r
2319         {\r
2320                 return error(GL_INVALID_VALUE);\r
2321         }\r
2322 \r
2323         UNIMPLEMENTED();\r
2324 }\r
2325 \r
2326 void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)\r
2327 {\r
2328         TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = 0x%0.8p, GLuint *uniformIndices = 0x%0.8p)",\r
2329               program, uniformCount, uniformNames, uniformIndices);\r
2330 \r
2331         es2::Context *context = es2::getContext();\r
2332 \r
2333         if(context)\r
2334         {\r
2335                 es2::Program *programObject = context->getProgram(program);\r
2336 \r
2337                 if(!programObject)\r
2338                 {\r
2339                         return error(GL_INVALID_OPERATION);\r
2340                 }\r
2341         }\r
2342 \r
2343         UNIMPLEMENTED();\r
2344 }\r
2345 \r
2346 void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)\r
2347 {\r
2348         TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = 0x%0.8p, GLenum pname = 0x%X, GLuint *uniformIndices = 0x%0.8p)",\r
2349               program, uniformCount, uniformIndices, pname, uniformIndices);\r
2350 \r
2351         switch(pname)\r
2352         {\r
2353         case GL_UNIFORM_TYPE:\r
2354         case GL_UNIFORM_SIZE:\r
2355         case GL_UNIFORM_NAME_LENGTH:\r
2356         case GL_UNIFORM_BLOCK_INDEX:\r
2357         case GL_UNIFORM_OFFSET:\r
2358         case GL_UNIFORM_ARRAY_STRIDE:\r
2359         case GL_UNIFORM_MATRIX_STRIDE:\r
2360         case GL_UNIFORM_IS_ROW_MAJOR:\r
2361                 break;\r
2362         default:\r
2363                 return error(GL_INVALID_ENUM);\r
2364         }\r
2365 \r
2366         es2::Context *context = es2::getContext();\r
2367 \r
2368         if(context)\r
2369         {\r
2370                 es2::Program *programObject = context->getProgram(program);\r
2371 \r
2372                 if(!programObject)\r
2373                 {\r
2374                         return error(GL_INVALID_OPERATION);\r
2375                 }\r
2376         }\r
2377 \r
2378         UNIMPLEMENTED();\r
2379 }\r
2380 \r
2381 GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)\r
2382 {\r
2383         TRACE("(GLuint program = %d, const GLchar *uniformBlockName = 0x%0.8p)",\r
2384               program, uniformBlockName);\r
2385 \r
2386         es2::Context *context = es2::getContext();\r
2387 \r
2388         if(context)\r
2389         {\r
2390                 es2::Program *programObject = context->getProgram(program);\r
2391 \r
2392                 if(!programObject)\r
2393                 {\r
2394                         return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);\r
2395                 }\r
2396         }\r
2397 \r
2398         UNIMPLEMENTED();\r
2399         return GL_INVALID_INDEX;\r
2400 }\r
2401 \r
2402 void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)\r
2403 {\r
2404         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
2405               program, uniformBlockIndex, pname, params);\r
2406 \r
2407         switch(pname)\r
2408         {\r
2409         case GL_UNIFORM_BLOCK_BINDING:\r
2410         case GL_UNIFORM_BLOCK_DATA_SIZE:\r
2411         case GL_UNIFORM_BLOCK_NAME_LENGTH:\r
2412         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:\r
2413         case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:\r
2414         case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:\r
2415         case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:\r
2416                 break;\r
2417         default:\r
2418                 return error(GL_INVALID_ENUM);\r
2419         }\r
2420 \r
2421         es2::Context *context = es2::getContext();\r
2422 \r
2423         if(context)\r
2424         {\r
2425                 es2::Program *program = context->getCurrentProgram();\r
2426 \r
2427                 if(!program)\r
2428                 {\r
2429                         return error(GL_INVALID_OPERATION);\r
2430                 }\r
2431         }\r
2432 \r
2433         UNIMPLEMENTED();\r
2434 }\r
2435 \r
2436 void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)\r
2437 {\r
2438         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *uniformBlockName = 0x%0.8p)",\r
2439               program, uniformBlockIndex, bufSize, length, uniformBlockName);\r
2440 \r
2441         es2::Context *context = es2::getContext();\r
2442 \r
2443         if(context)\r
2444         {\r
2445                 es2::Program *programObject = context->getProgram(program);\r
2446 \r
2447                 if(!programObject)\r
2448                 {\r
2449                         return error(GL_INVALID_OPERATION);\r
2450                 }\r
2451         }\r
2452 \r
2453         UNIMPLEMENTED();\r
2454 }\r
2455 \r
2456 void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)\r
2457 {\r
2458         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",\r
2459               program, uniformBlockIndex, uniformBlockBinding);\r
2460 \r
2461         es2::Context *context = es2::getContext();\r
2462 \r
2463         if(context)\r
2464         {\r
2465                 es2::Program *programObject = context->getProgram(program);\r
2466 \r
2467                 if(!programObject)\r
2468                 {\r
2469                         return error(GL_INVALID_VALUE);\r
2470                 }\r
2471         }\r
2472 \r
2473         UNIMPLEMENTED();\r
2474 }\r
2475 \r
2476 void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount)\r
2477 {\r
2478         TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instancecount = %d)",\r
2479               mode, first, count, instancecount);\r
2480 \r
2481         switch(mode)\r
2482         {\r
2483         case GL_POINTS:\r
2484         case GL_LINES:\r
2485         case GL_LINE_LOOP:\r
2486         case GL_LINE_STRIP:\r
2487         case GL_TRIANGLES:\r
2488         case GL_TRIANGLE_FAN:\r
2489         case GL_TRIANGLE_STRIP:\r
2490                 break;\r
2491         default:\r
2492                 return error(GL_INVALID_ENUM);\r
2493         }\r
2494 \r
2495         if(count < 0 || instancecount < 0)\r
2496         {\r
2497                 return error(GL_INVALID_VALUE);\r
2498         }\r
2499 \r
2500         es2::Context *context = es2::getContext();\r
2501 \r
2502         if(context)\r
2503         {\r
2504                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();\r
2505                 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))\r
2506                 {\r
2507                         return error(GL_INVALID_OPERATION);\r
2508                 }\r
2509         }\r
2510 \r
2511         UNIMPLEMENTED();\r
2512 }\r
2513 \r
2514 void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount)\r
2515 {\r
2516         TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = 0x%0.8p, GLsizei instancecount = %d)",\r
2517               mode, count, type, indices, instancecount);\r
2518 \r
2519         switch(mode)\r
2520         {\r
2521         case GL_POINTS:\r
2522         case GL_LINES:\r
2523         case GL_LINE_LOOP:\r
2524         case GL_LINE_STRIP:\r
2525         case GL_TRIANGLES:\r
2526         case GL_TRIANGLE_FAN:\r
2527         case GL_TRIANGLE_STRIP:\r
2528                 break;\r
2529         default:\r
2530                 return error(GL_INVALID_ENUM);\r
2531         }\r
2532 \r
2533         switch(type)\r
2534         {\r
2535         case GL_UNSIGNED_BYTE:\r
2536         case GL_UNSIGNED_SHORT:\r
2537         case GL_UNSIGNED_INT:\r
2538                 break;\r
2539         default:\r
2540                 return error(GL_INVALID_ENUM);\r
2541         }\r
2542 \r
2543         if(count < 0 || instancecount < 0)\r
2544         {\r
2545                 return error(GL_INVALID_VALUE);\r
2546         }\r
2547 \r
2548         es2::Context *context = es2::getContext();\r
2549 \r
2550         if(context)\r
2551         {\r
2552                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();\r
2553                 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())\r
2554                 {\r
2555                         return error(GL_INVALID_OPERATION);\r
2556                 }\r
2557         }\r
2558 \r
2559         UNIMPLEMENTED();\r
2560 }\r
2561 \r
2562 GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)\r
2563 {\r
2564         TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags);\r
2565 \r
2566         switch(condition)\r
2567         {\r
2568         case GL_SYNC_GPU_COMMANDS_COMPLETE:\r
2569                 break;\r
2570         default:\r
2571                 return error(GL_INVALID_ENUM, nullptr);\r
2572         }\r
2573 \r
2574         if(flags != 0)\r
2575         {\r
2576                 return error(GL_INVALID_VALUE, nullptr);\r
2577         }\r
2578 \r
2579         UNIMPLEMENTED();\r
2580         return nullptr;\r
2581 }\r
2582 \r
2583 GLboolean GL_APIENTRY glIsSync(GLsync sync)\r
2584 {\r
2585         TRACE("(GLsync sync = 0x%0.8p)", sync);\r
2586 \r
2587         UNIMPLEMENTED();\r
2588         return GL_FALSE;\r
2589 }\r
2590 \r
2591 void GL_APIENTRY glDeleteSync(GLsync sync)\r
2592 {\r
2593         TRACE("(GLsync sync = 0x%0.8p)", sync);\r
2594 \r
2595         UNIMPLEMENTED();\r
2596 }\r
2597 \r
2598 GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)\r
2599 {\r
2600         TRACE("(GLsync sync = 0x%0.8p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);\r
2601 \r
2602         if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)\r
2603         {\r
2604                 error(GL_INVALID_VALUE);\r
2605         }\r
2606 \r
2607         UNIMPLEMENTED();\r
2608         return GL_FALSE;\r
2609 }\r
2610 \r
2611 void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)\r
2612 {\r
2613         TRACE("(GLsync sync = 0x%0.8p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);\r
2614 \r
2615         if(flags != 0)\r
2616         {\r
2617                 return error(GL_INVALID_VALUE);\r
2618         }\r
2619 \r
2620         if(timeout != GL_TIMEOUT_IGNORED)\r
2621         {\r
2622                 return error(GL_INVALID_VALUE);\r
2623         }\r
2624 \r
2625         UNIMPLEMENTED();\r
2626 }\r
2627 \r
2628 void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *data)\r
2629 {\r
2630         TRACE("(GLenum pname = 0x%X, GLint64 *data = 0x%0.8p)", pname, data);\r
2631         UNIMPLEMENTED();\r
2632 }\r
2633 \r
2634 void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)\r
2635 {\r
2636         TRACE("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLint *values = 0x%0.8p)",\r
2637               sync, pname, bufSize, length, values);\r
2638 \r
2639         UNIMPLEMENTED();\r
2640 }\r
2641 \r
2642 void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)\r
2643 {\r
2644         TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint64 *data = 0x%0.8p)", target, index, data);\r
2645         UNIMPLEMENTED();\r
2646 }\r
2647 \r
2648 void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)\r
2649 {\r
2650         TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = 0x%0.8p)", target, pname, params);\r
2651         UNIMPLEMENTED();\r
2652 }\r
2653 \r
2654 void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)\r
2655 {\r
2656         TRACE("(GLsizei count = %d, GLuint *samplers = 0x%0.8p)", count, samplers);\r
2657 \r
2658         if(count < 0)\r
2659         {\r
2660                 return error(GL_INVALID_VALUE);\r
2661         }\r
2662 \r
2663         es2::Context *context = es2::getContext();\r
2664 \r
2665         if(context)\r
2666         {\r
2667                 for(int i = 0; i < count; i++)\r
2668                 {\r
2669                         samplers[i] = context->createSampler();\r
2670                 }\r
2671         }\r
2672 }\r
2673 \r
2674 void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)\r
2675 {\r
2676         TRACE("(GLsizei count = %d, GLuint *samplers = 0x%0.8p)", count, samplers);\r
2677 \r
2678         if(count < 0)\r
2679         {\r
2680                 return error(GL_INVALID_VALUE);\r
2681         }\r
2682 \r
2683         es2::Context *context = es2::getContext();\r
2684 \r
2685         if(context)\r
2686         {\r
2687                 for(int i = 0; i < count; i++)\r
2688                 {\r
2689                         context->deleteSampler(samplers[i]);\r
2690                 }\r
2691         }\r
2692 }\r
2693 \r
2694 GLboolean GL_APIENTRY glIsSampler(GLuint sampler)\r
2695 {\r
2696         TRACE("(GLuint sampler = %d)", sampler);\r
2697 \r
2698         if(sampler == 0)\r
2699         {\r
2700                 return GL_FALSE;\r
2701         }\r
2702 \r
2703         es2::Context *context = es2::getContext();\r
2704 \r
2705         if(context)\r
2706         {\r
2707                 es2::Sampler *samplerObject = context->getSampler(sampler);\r
2708 \r
2709                 if(samplerObject)\r
2710                 {\r
2711                         return GL_TRUE;\r
2712                 }\r
2713         }\r
2714 \r
2715         return GL_FALSE;\r
2716 }\r
2717 \r
2718 void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)\r
2719 {\r
2720         TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler);\r
2721 \r
2722         if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS)\r
2723         {\r
2724                 return error(GL_INVALID_VALUE);\r
2725         }\r
2726 \r
2727         es2::Context *context = es2::getContext();\r
2728 \r
2729         if(context)\r
2730         {\r
2731                 if(sampler != 0)\r
2732                 {\r
2733                         es2::Sampler *samplerObject = context->getSampler(sampler);\r
2734 \r
2735                         if(!samplerObject)\r
2736                         {\r
2737                                 return error(GL_INVALID_OPERATION);\r
2738                         }\r
2739                 }\r
2740 \r
2741                 context->bindSampler(unit, sampler);\r
2742         }\r
2743 }\r
2744 \r
2745 void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)\r
2746 {\r
2747         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint param = %d)",\r
2748               sampler, pname, param);\r
2749 \r
2750         glSamplerParameteriv(sampler, pname, &param);\r
2751 }\r
2752 \r
2753 void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)\r
2754 {\r
2755         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = 0x%0.8p)",\r
2756               sampler, pname, param);\r
2757 \r
2758         es2::Context *context = es2::getContext();\r
2759 \r
2760         if(context)\r
2761         {\r
2762                 es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;\r
2763 \r
2764                 if(!samplerObject)\r
2765                 {\r
2766                         return error(GL_INVALID_VALUE);\r
2767                 }\r
2768 \r
2769                 switch(pname)\r
2770                 {\r
2771                 case GL_TEXTURE_WRAP_S:\r
2772                         switch(*param)\r
2773                         {\r
2774                         case GL_CLAMP_TO_EDGE:\r
2775                         case GL_MIRRORED_REPEAT:\r
2776                         case GL_REPEAT:\r
2777                                 samplerObject->mWrapModeS = *param;\r
2778                                 break;\r
2779                         default:\r
2780                                 return error(GL_INVALID_ENUM);\r
2781                         }\r
2782                         break;\r
2783                 case GL_TEXTURE_WRAP_T:\r
2784                         switch(*param)\r
2785                         {\r
2786                         case GL_CLAMP_TO_EDGE:\r
2787                         case GL_MIRRORED_REPEAT:\r
2788                         case GL_REPEAT:\r
2789                                 samplerObject->mWrapModeT = *param;\r
2790                                 break;\r
2791                         default:\r
2792                                 return error(GL_INVALID_ENUM);\r
2793                         }\r
2794                         break;\r
2795                 case GL_TEXTURE_WRAP_R:\r
2796                         switch(*param)\r
2797                         {\r
2798                         case GL_CLAMP_TO_EDGE:\r
2799                         case GL_MIRRORED_REPEAT:\r
2800                         case GL_REPEAT:\r
2801                                 samplerObject->mWrapModeR = *param;\r
2802                                 break;\r
2803                         default:\r
2804                                 return error(GL_INVALID_ENUM);\r
2805                         }\r
2806                         break;\r
2807                 case GL_TEXTURE_MIN_FILTER:\r
2808                         switch(*param)\r
2809                         {\r
2810                         case GL_NEAREST:\r
2811                         case GL_LINEAR:\r
2812                         case GL_NEAREST_MIPMAP_NEAREST:\r
2813                         case GL_LINEAR_MIPMAP_NEAREST:\r
2814                         case GL_NEAREST_MIPMAP_LINEAR:\r
2815                         case GL_LINEAR_MIPMAP_LINEAR:\r
2816                                 samplerObject->mMinFilter = *param;\r
2817                                 break;\r
2818                         default:\r
2819                                 return error(GL_INVALID_ENUM);\r
2820                         }\r
2821                         break;\r
2822                 case GL_TEXTURE_MAG_FILTER:\r
2823                         switch(*param)\r
2824                         {\r
2825                         case GL_NEAREST:\r
2826                         case GL_LINEAR:\r
2827                                 samplerObject->mMagFilter = *param;\r
2828                                 break;\r
2829                         default:\r
2830                                 return error(GL_INVALID_ENUM);\r
2831                         }\r
2832                         break;\r
2833                 case GL_TEXTURE_MIN_LOD:\r
2834                         samplerObject->mMinLod = (GLfloat)*param;\r
2835                         break;\r
2836                 case GL_TEXTURE_MAX_LOD:\r
2837                         samplerObject->mMaxLod = (GLfloat)*param;\r
2838                         break;\r
2839                 case GL_TEXTURE_COMPARE_MODE:\r
2840                         switch(*param)\r
2841                         {\r
2842                         case GL_COMPARE_REF_TO_TEXTURE:\r
2843                         case GL_NONE:\r
2844                                 samplerObject->mCompareMode = *param;\r
2845                                 break;\r
2846                         default:\r
2847                                 return error(GL_INVALID_ENUM);\r
2848                         }\r
2849                         break;\r
2850                 case GL_TEXTURE_COMPARE_FUNC:\r
2851                         switch(*param)\r
2852                         {\r
2853                         case GL_LEQUAL:\r
2854                         case GL_GEQUAL:\r
2855                         case GL_LESS:\r
2856                         case GL_GREATER:\r
2857                         case GL_EQUAL:\r
2858                         case GL_NOTEQUAL:\r
2859                         case GL_ALWAYS:\r
2860                         case GL_NEVER:\r
2861                                 samplerObject->mCompareFunc = *param;\r
2862                                 break;\r
2863                         default:\r
2864                                 return error(GL_INVALID_ENUM);\r
2865                         }\r
2866                         break;\r
2867                 default:\r
2868                         return error(GL_INVALID_ENUM);\r
2869                 }\r
2870         }\r
2871 }\r
2872 \r
2873 void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)\r
2874 {\r
2875         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat param = %f)",\r
2876               sampler, pname, param);\r
2877 \r
2878         glSamplerParameterfv(sampler, pname, &param);\r
2879 }\r
2880 \r
2881 void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)\r
2882 {\r
2883         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = 0x%0.8p)",\r
2884               sampler, pname, param);\r
2885 \r
2886         es2::Context *context = es2::getContext();\r
2887 \r
2888         if(context)\r
2889         {\r
2890                 es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;\r
2891 \r
2892                 if(!samplerObject)\r
2893                 {\r
2894                         return error(GL_INVALID_VALUE);\r
2895                 }\r
2896 \r
2897                 switch(pname)\r
2898                 {\r
2899                 case GL_TEXTURE_WRAP_S:\r
2900                         switch((GLenum)*param)\r
2901                         {\r
2902                         case GL_CLAMP_TO_EDGE:\r
2903                         case GL_MIRRORED_REPEAT:\r
2904                         case GL_REPEAT:\r
2905                                 samplerObject->mWrapModeS = (GLenum)*param;\r
2906                                 break;\r
2907                         default:\r
2908                                 return error(GL_INVALID_ENUM);\r
2909                         }\r
2910                         break;\r
2911                 case GL_TEXTURE_WRAP_T:\r
2912                         switch((GLenum)*param)\r
2913                         {\r
2914                         case GL_CLAMP_TO_EDGE:\r
2915                         case GL_MIRRORED_REPEAT:\r
2916                         case GL_REPEAT:\r
2917                                 samplerObject->mWrapModeT = (GLenum)*param;\r
2918                                 break;\r
2919                         default:\r
2920                                 return error(GL_INVALID_ENUM);\r
2921                         }\r
2922                         break;\r
2923                 case GL_TEXTURE_WRAP_R:\r
2924                         switch((GLenum)*param)\r
2925                         {\r
2926                         case GL_CLAMP_TO_EDGE:\r
2927                         case GL_MIRRORED_REPEAT:\r
2928                         case GL_REPEAT:\r
2929                                 samplerObject->mWrapModeR = (GLenum)*param;\r
2930                                 break;\r
2931                         default:\r
2932                                 return error(GL_INVALID_ENUM);\r
2933                         }\r
2934                         break;\r
2935                 case GL_TEXTURE_MIN_FILTER:\r
2936                         switch((GLenum)*param)\r
2937                         {\r
2938                         case GL_NEAREST:\r
2939                         case GL_LINEAR:\r
2940                         case GL_NEAREST_MIPMAP_NEAREST:\r
2941                         case GL_LINEAR_MIPMAP_NEAREST:\r
2942                         case GL_NEAREST_MIPMAP_LINEAR:\r
2943                         case GL_LINEAR_MIPMAP_LINEAR:\r
2944                                 samplerObject->mMinFilter = (GLenum)*param;\r
2945                                 break;\r
2946                         default:\r
2947                                 return error(GL_INVALID_ENUM);\r
2948                         }\r
2949                         break;\r
2950                 case GL_TEXTURE_MAG_FILTER:\r
2951                         switch((GLenum)*param)\r
2952                         {\r
2953                         case GL_NEAREST:\r
2954                         case GL_LINEAR:\r
2955                                 samplerObject->mMagFilter = (GLenum)*param;\r
2956                                 break;\r
2957                         default:\r
2958                                 return error(GL_INVALID_ENUM);\r
2959                         }\r
2960                         break;\r
2961                 case GL_TEXTURE_MIN_LOD:\r
2962                         samplerObject->mMinLod = *param;\r
2963                         break;\r
2964                 case GL_TEXTURE_MAX_LOD:\r
2965                         samplerObject->mMaxLod = *param;\r
2966                         break;\r
2967                 case GL_TEXTURE_COMPARE_MODE:\r
2968                         switch((GLenum)*param)\r
2969                         {\r
2970                         case GL_COMPARE_REF_TO_TEXTURE:\r
2971                         case GL_NONE:\r
2972                                 samplerObject->mCompareMode = (GLenum)*param;\r
2973                                 break;\r
2974                         default:\r
2975                                 return error(GL_INVALID_ENUM);\r
2976                         }\r
2977                         break;\r
2978                 case GL_TEXTURE_COMPARE_FUNC:\r
2979                         switch((GLenum)*param)\r
2980                         {\r
2981                         case GL_LEQUAL:\r
2982                         case GL_GEQUAL:\r
2983                         case GL_LESS:\r
2984                         case GL_GREATER:\r
2985                         case GL_EQUAL:\r
2986                         case GL_NOTEQUAL:\r
2987                         case GL_ALWAYS:\r
2988                         case GL_NEVER:\r
2989                                 samplerObject->mCompareFunc = (GLenum)*param;\r
2990                                 break;\r
2991                         default:\r
2992                                 return error(GL_INVALID_ENUM);\r
2993                         }\r
2994                         break;\r
2995                 default:\r
2996                         return error(GL_INVALID_ENUM);\r
2997                 }\r
2998         }\r
2999 }\r
3000 \r
3001 void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)\r
3002 {\r
3003         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",\r
3004               sampler, pname, params);\r
3005 \r
3006         es2::Context *context = es2::getContext();\r
3007 \r
3008         if(context)\r
3009         {\r
3010                 es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;\r
3011 \r
3012                 if(!samplerObject)\r
3013                 {\r
3014                         return error(GL_INVALID_VALUE);\r
3015                 }\r
3016 \r
3017                 switch(pname)\r
3018                 {\r
3019                 case GL_TEXTURE_WRAP_S:\r
3020                         *params = samplerObject->mWrapModeS;\r
3021                         break;\r
3022                 case GL_TEXTURE_WRAP_T:\r
3023                         *params = samplerObject->mWrapModeT;\r
3024                         break;\r
3025                 case GL_TEXTURE_WRAP_R:\r
3026                         *params = samplerObject->mWrapModeR;\r
3027                         break;\r
3028                 case GL_TEXTURE_MIN_FILTER:\r
3029                         *params = samplerObject->mMinFilter;\r
3030                         break;\r
3031                 case GL_TEXTURE_MAG_FILTER:\r
3032                         *params = samplerObject->mMagFilter;\r
3033                         break;\r
3034                 case GL_TEXTURE_MIN_LOD:\r
3035                         *params = (GLint)samplerObject->mMinLod;\r
3036                         break;\r
3037                 case GL_TEXTURE_MAX_LOD:\r
3038                         *params = (GLint)samplerObject->mMaxLod;\r
3039                         break;\r
3040                 case GL_TEXTURE_COMPARE_MODE:\r
3041                         *params = samplerObject->mCompareMode;\r
3042                         break;\r
3043                 case GL_TEXTURE_COMPARE_FUNC:\r
3044                         *params = samplerObject->mCompareFunc;\r
3045                         break;\r
3046                 default:\r
3047                         return error(GL_INVALID_ENUM);\r
3048                 }\r
3049         }\r
3050 }\r
3051 \r
3052 void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)\r
3053 {\r
3054         TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)",\r
3055               sampler, pname, params);\r
3056 \r
3057         es2::Context *context = es2::getContext();\r
3058 \r
3059         if(context)\r
3060         {\r
3061                 es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;\r
3062 \r
3063                 if(!samplerObject)\r
3064                 {\r
3065                         return error(GL_INVALID_VALUE);\r
3066                 }\r
3067 \r
3068                 switch(pname)\r
3069                 {\r
3070                 case GL_TEXTURE_WRAP_S:\r
3071                         *params = (GLfloat)samplerObject->mWrapModeS;\r
3072                         break;\r
3073                 case GL_TEXTURE_WRAP_T:\r
3074                         *params = (GLfloat)samplerObject->mWrapModeT;\r
3075                         break;\r
3076                 case GL_TEXTURE_WRAP_R:\r
3077                         *params = (GLfloat)samplerObject->mWrapModeR;\r
3078                         break;\r
3079                 case GL_TEXTURE_MIN_FILTER:\r
3080                         *params = (GLfloat)samplerObject->mMinFilter;\r
3081                         break;\r
3082                 case GL_TEXTURE_MAG_FILTER:\r
3083                         *params = (GLfloat)samplerObject->mMagFilter;\r
3084                         break;\r
3085                 case GL_TEXTURE_MIN_LOD:\r
3086                         *params = samplerObject->mMinLod;\r
3087                         break;\r
3088                 case GL_TEXTURE_MAX_LOD:\r
3089                         *params = samplerObject->mMaxLod;\r
3090                         break;\r
3091                 case GL_TEXTURE_COMPARE_MODE:\r
3092                         *params = (GLfloat)samplerObject->mCompareMode;\r
3093                         break;\r
3094                 case GL_TEXTURE_COMPARE_FUNC:\r
3095                         *params = (GLfloat)samplerObject->mCompareFunc;\r
3096                         break;\r
3097                 default:\r
3098                         return error(GL_INVALID_ENUM);\r
3099                 }\r
3100         }\r
3101 }\r
3102 \r
3103 void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)\r
3104 {\r
3105         TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);\r
3106 \r
3107         es2::Context *context = es2::getContext();\r
3108 \r
3109         if(context)\r
3110         {\r
3111                 if(index >= es2::MAX_VERTEX_ATTRIBS)\r
3112                 {\r
3113                         return error(GL_INVALID_VALUE);\r
3114                 }\r
3115 \r
3116                 context->setVertexAttribDivisor(index, divisor);\r
3117         }\r
3118 }\r
3119 \r
3120 void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)\r
3121 {\r
3122         TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);\r
3123 \r
3124         if(target != GL_TRANSFORM_FEEDBACK)\r
3125         {\r
3126                 return error(GL_INVALID_ENUM);\r
3127         }\r
3128 \r
3129         es2::Context *context = es2::getContext();\r
3130 \r
3131         if(context)\r
3132         {\r
3133                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();\r
3134 \r
3135                 if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused())\r
3136                 {\r
3137                         return error(GL_INVALID_OPERATION);\r
3138                 }\r
3139 \r
3140                 if(!context->bindTransformFeedback(id))\r
3141                 {\r
3142                         return error(GL_INVALID_OPERATION);\r
3143                 }\r
3144         }\r
3145 }\r
3146 \r
3147 void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)\r
3148 {\r
3149         TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);\r
3150 \r
3151         if(n < 0)\r
3152         {\r
3153                 return error(GL_INVALID_VALUE);\r
3154         }\r
3155 \r
3156         es2::Context *context = es2::getContext();\r
3157 \r
3158         if(context)\r
3159         {\r
3160                 for(int i = 0; i < n; i++)\r
3161                 {\r
3162                         if (ids[i] != 0)\r
3163                         {\r
3164                                 context->deleteTransformFeedback(ids[i]);\r
3165                         }\r
3166                 }\r
3167         }\r
3168 }\r
3169 \r
3170 void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)\r
3171 {\r
3172         TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);\r
3173 \r
3174         if(n < 0)\r
3175         {\r
3176                 return error(GL_INVALID_VALUE);\r
3177         }\r
3178 \r
3179         es2::Context *context = es2::getContext();\r
3180 \r
3181         if(context)\r
3182         {\r
3183                 for(int i = 0; i < n; i++)\r
3184                 {\r
3185                         ids[i] = context->createTransformFeedback();\r
3186                 }\r
3187         }\r
3188 }\r
3189 \r
3190 GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)\r
3191 {\r
3192         TRACE("(GLuint id = %d)", id);\r
3193 \r
3194         if(id == 0)\r
3195         {\r
3196                 return GL_FALSE;\r
3197         }\r
3198 \r
3199         es2::Context *context = es2::getContext();\r
3200 \r
3201         if(context)\r
3202         {\r
3203                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id);\r
3204 \r
3205                 if(transformFeedbackObject)\r
3206                 {\r
3207                         return GL_TRUE;\r
3208                 }\r
3209         }\r
3210 \r
3211         return GL_FALSE;\r
3212 }\r
3213 \r
3214 void GL_APIENTRY glPauseTransformFeedback(void)\r
3215 {\r
3216         TRACE("()");\r
3217 \r
3218         es2::Context *context = es2::getContext();\r
3219 \r
3220         if(context)\r
3221         {\r
3222                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();\r
3223 \r
3224                 if(transformFeedbackObject)\r
3225                 {\r
3226                         if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused())\r
3227                         {\r
3228                                 return error(GL_INVALID_OPERATION);\r
3229                         }\r
3230                         transformFeedbackObject->setPaused(true);\r
3231                 }\r
3232         }\r
3233 }\r
3234 \r
3235 void GL_APIENTRY glResumeTransformFeedback(void)\r
3236 {\r
3237         TRACE("()");\r
3238 \r
3239         es2::Context *context = es2::getContext();\r
3240 \r
3241         if(context)\r
3242         {\r
3243                 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();\r
3244 \r
3245                 if(transformFeedbackObject)\r
3246                 {\r
3247                         if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused())\r
3248                         {\r
3249                                 return error(GL_INVALID_OPERATION);\r
3250                         }\r
3251                         transformFeedbackObject->setPaused(false);\r
3252                 }\r
3253         }\r
3254 }\r
3255 \r
3256 void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)\r
3257 {\r
3258         TRACE("(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLenum *binaryFormat = 0x%0.8p, void *binary = 0x%0.8p)",\r
3259               program, bufSize, length, binaryFormat, binary);\r
3260 \r
3261         UNIMPLEMENTED();\r
3262 }\r
3263 \r
3264 void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)\r
3265 {\r
3266         TRACE("(GLuint program = %d, GLenum binaryFormat = 0x%X, const void *binary = 0x%0.8p, GLsizei length = %d)",\r
3267               program, binaryFormat, binaryFormat, length);\r
3268 \r
3269         UNIMPLEMENTED();\r
3270 }\r
3271 \r
3272 void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)\r
3273 {\r
3274         TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint value = %d)",\r
3275               program, pname, value);\r
3276 \r
3277         UNIMPLEMENTED();\r
3278 }\r
3279 \r
3280 void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)\r
3281 {\r
3282         TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = 0x%0.8p)",\r
3283               target, numAttachments, attachments);\r
3284 \r
3285         UNIMPLEMENTED();\r
3286 }\r
3287 \r
3288 void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)\r
3289 {\r
3290         TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = 0x%0.8p, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",\r
3291               target, numAttachments, attachments, x, y, width, height);\r
3292 \r
3293         UNIMPLEMENTED();\r
3294 }\r
3295 \r
3296 void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)\r
3297 {\r
3298         TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",\r
3299               target, levels, internalformat, width, height);\r
3300 \r
3301         UNIMPLEMENTED();\r
3302 }\r
3303 \r
3304 void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)\r
3305 {\r
3306         TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d)",\r
3307               target, levels, internalformat, width, height, depth);\r
3308 \r
3309         UNIMPLEMENTED();\r
3310 }\r
3311 \r
3312 void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)\r
3313 {\r
3314         TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLint *params = 0x%0.8p)",\r
3315               target, internalformat, pname, bufSize, params);\r
3316 \r
3317         UNIMPLEMENTED();\r
3318 }\r
3319 \r
3320 }\r