OSDN Git Service

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