OSDN Git Service

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