OSDN Git Service

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