OSDN Git Service

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