OSDN Git Service

glGetFragDataLocation implementation
[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(context)
2284         {
2285                 es2::Program *programObject = context->getProgram(program);
2286
2287                 if(!programObject)
2288                 {
2289                         if(context->getShader(program))
2290                         {
2291                                 return error(GL_INVALID_OPERATION, -1);
2292                         }
2293                         else
2294                         {
2295                                 return error(GL_INVALID_VALUE, -1);
2296                         }
2297                 }
2298
2299                 if(!programObject->isLinked())
2300                 {
2301                         return error(GL_INVALID_OPERATION, -1);
2302                 }
2303
2304                 return programObject->getFragDataLocation(name);
2305         }
2306
2307         return -1;
2308 }
2309
2310 GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
2311 {
2312         glUniform1uiv(location, 1, &v0);
2313 }
2314
2315 GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
2316 {
2317         GLuint xy[2] = { v0, v1 };
2318
2319         glUniform2uiv(location, 1, (GLuint*)&xy);
2320 }
2321
2322 GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
2323 {
2324         GLuint xyz[3] = { v0, v1, v2 };
2325
2326         glUniform3uiv(location, 1, (GLuint*)&xyz);
2327 }
2328
2329 GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
2330 {
2331         GLuint xyzw[4] = { v0, v1, v2, v3 };
2332
2333         glUniform4uiv(location, 1, (GLuint*)&xyzw);
2334 }
2335
2336 GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
2337 {
2338         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2339               location, count, value);
2340
2341         if(count < 0)
2342         {
2343                 return error(GL_INVALID_VALUE);
2344         }
2345
2346         if(location == -1)
2347         {
2348                 return;
2349         }
2350
2351         es2::Context *context = es2::getContext();
2352
2353         if(context)
2354         {
2355                 es2::Program *program = context->getCurrentProgram();
2356
2357                 if(!program)
2358                 {
2359                         return error(GL_INVALID_OPERATION);
2360                 }
2361
2362                 if(!program->setUniform1uiv(location, count, value))
2363                 {
2364                         return error(GL_INVALID_OPERATION);
2365                 }
2366         }
2367 }
2368
2369 GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
2370 {
2371         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2372               location, count, value);
2373
2374         if(count < 0)
2375         {
2376                 return error(GL_INVALID_VALUE);
2377         }
2378
2379         if(location == -1)
2380         {
2381                 return;
2382         }
2383
2384         es2::Context *context = es2::getContext();
2385
2386         if(context)
2387         {
2388                 es2::Program *program = context->getCurrentProgram();
2389
2390                 if(!program)
2391                 {
2392                         return error(GL_INVALID_OPERATION);
2393                 }
2394
2395                 if(!program->setUniform2uiv(location, count, value))
2396                 {
2397                         return error(GL_INVALID_OPERATION);
2398                 }
2399         }
2400 }
2401
2402 GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
2403 {
2404         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2405               location, count, value);
2406
2407         if(count < 0)
2408         {
2409                 return error(GL_INVALID_VALUE);
2410         }
2411
2412         if(location == -1)
2413         {
2414                 return;
2415         }
2416
2417         es2::Context *context = es2::getContext();
2418
2419         if(context)
2420         {
2421                 es2::Program *program = context->getCurrentProgram();
2422
2423                 if(!program)
2424                 {
2425                         return error(GL_INVALID_OPERATION);
2426                 }
2427
2428                 if(!program->setUniform3uiv(location, count, value))
2429                 {
2430                         return error(GL_INVALID_OPERATION);
2431                 }
2432         }
2433 }
2434
2435 GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
2436 {
2437         TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2438               location, count, value);
2439
2440         if(count < 0)
2441         {
2442                 return error(GL_INVALID_VALUE);
2443         }
2444
2445         if(location == -1)
2446         {
2447                 return;
2448         }
2449
2450         es2::Context *context = es2::getContext();
2451
2452         if(context)
2453         {
2454                 es2::Program *program = context->getCurrentProgram();
2455
2456                 if(!program)
2457                 {
2458                         return error(GL_INVALID_OPERATION);
2459                 }
2460
2461                 if(!program->setUniform4uiv(location, count, value))
2462                 {
2463                         return error(GL_INVALID_OPERATION);
2464                 }
2465         }
2466 }
2467
2468 GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
2469 {
2470         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
2471               buffer, drawbuffer, value);
2472
2473         es2::Context *context = es2::getContext();
2474
2475         if(context)
2476         {
2477                 switch(buffer)
2478                 {
2479                 case GL_COLOR:
2480                         if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2481                         {
2482                                 return error(GL_INVALID_VALUE);
2483                         }
2484                         else
2485                         {
2486                                 context->clearColorBuffer(drawbuffer, value);
2487                         }
2488                         break;
2489                 case GL_STENCIL:
2490                         if(drawbuffer != 0)
2491                         {
2492                                 return error(GL_INVALID_VALUE);
2493                         }
2494                         else
2495                         {
2496                                 context->clearStencilBuffer(value[0]);
2497                         }
2498                         break;
2499                 default:
2500                         return error(GL_INVALID_ENUM);
2501                 }
2502         }
2503 }
2504
2505 GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
2506 {
2507         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
2508               buffer, drawbuffer, value);
2509
2510         es2::Context *context = es2::getContext();
2511
2512         if(context)
2513         {
2514                 switch(buffer)
2515                 {
2516                 case GL_COLOR:
2517                         if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2518                         {
2519                                 return error(GL_INVALID_VALUE);
2520                         }
2521                         else
2522                         {
2523                                 context->clearColorBuffer(drawbuffer, value);
2524                         }
2525                         break;
2526                 default:
2527                         return error(GL_INVALID_ENUM);
2528                 }
2529         }
2530 }
2531
2532 GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
2533 {
2534         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
2535               buffer, drawbuffer, value);
2536
2537         es2::Context *context = es2::getContext();
2538
2539         if(context)
2540         {
2541                 switch(buffer)
2542                 {
2543                 case GL_COLOR:
2544                         if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2545                         {
2546                                 return error(GL_INVALID_VALUE);
2547                         }
2548                         else
2549                         {
2550                                 context->clearColorBuffer(drawbuffer, value);
2551                         }
2552                         break;
2553                 case GL_DEPTH:
2554                         if(drawbuffer != 0)
2555                         {
2556                                 return error(GL_INVALID_VALUE);
2557                         }
2558                         else
2559                         {
2560                                 context->clearDepthBuffer(value[0]);
2561                         }
2562                         break;
2563                 default:
2564                         return error(GL_INVALID_ENUM);
2565                 }
2566         }
2567 }
2568
2569 GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
2570 {
2571         TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
2572               buffer, drawbuffer, depth, stencil);
2573
2574         es2::Context *context = es2::getContext();
2575
2576         if(context)
2577         {
2578                 switch(buffer)
2579                 {
2580                 case GL_DEPTH_STENCIL:
2581                         if(drawbuffer != 0)
2582                         {
2583                                 return error(GL_INVALID_VALUE);
2584                         }
2585                         else
2586                         {
2587                                 context->clearDepthBuffer(depth);
2588                                 context->clearStencilBuffer(stencil);
2589                         }
2590                         break;
2591                 default:
2592                         return error(GL_INVALID_ENUM);
2593                 }
2594         }
2595 }
2596
2597 GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
2598 {
2599         TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index);
2600
2601         es2::Context *context = es2::getContext();
2602         if(context)
2603         {
2604                 GLuint numExtensions;
2605                 context->getExtensions(0, &numExtensions);
2606
2607                 if(index >= numExtensions)
2608                 {
2609                         return error(GL_INVALID_VALUE, (GLubyte*)nullptr);
2610                 }
2611
2612                 switch(name)
2613                 {
2614                 case GL_EXTENSIONS:
2615                         return context->getExtensions(index);
2616                 default:
2617                         return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
2618                 }
2619         }
2620
2621         return (GLubyte*)nullptr;
2622 }
2623
2624 GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
2625 {
2626         TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X,  GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
2627               readTarget, writeTarget, readOffset, writeOffset, size);
2628
2629         if(readOffset < 0 || writeOffset < 0 || size < 0)
2630         {
2631                 return error(GL_INVALID_VALUE);
2632         }
2633
2634         es2::Context *context = es2::getContext();
2635
2636         if(context)
2637         {
2638                 es2::Buffer *readBuffer = nullptr, *writeBuffer = nullptr;
2639                 if(!context->getBuffer(readTarget, &readBuffer) || !context->getBuffer(writeTarget, &writeBuffer))
2640                 {
2641                         return error(GL_INVALID_ENUM);
2642                 }
2643                 if(!readBuffer || readBuffer->isMapped() || !writeBuffer || writeBuffer->isMapped())
2644                 {
2645                         return error(GL_INVALID_OPERATION);
2646                 }
2647                 if(readBuffer == writeBuffer)
2648                 {
2649                         // If same buffer, check for overlap
2650                         if(((readOffset >= writeOffset) && (readOffset < (writeOffset + size))) ||
2651                            ((writeOffset >= readOffset) && (writeOffset < (readOffset + size))))
2652                         {
2653                                 return error(GL_INVALID_VALUE);
2654                         }
2655                 }
2656
2657                 if((static_cast<size_t>(readOffset + size) > readBuffer->size()) ||
2658                    (static_cast<size_t>(writeOffset + size) > writeBuffer->size()))
2659                 {
2660                         return error(GL_INVALID_VALUE);
2661                 }
2662
2663                 writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset);
2664         }
2665 }
2666
2667 GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
2668 {
2669         TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)",
2670               program, uniformCount, uniformNames, uniformIndices);
2671
2672         if(uniformCount < 0)
2673         {
2674                 return error(GL_INVALID_VALUE);
2675         }
2676
2677         es2::Context *context = es2::getContext();
2678
2679         if(context)
2680         {
2681                 es2::Program *programObject = context->getProgram(program);
2682
2683                 if(!programObject)
2684                 {
2685                         return error(GL_INVALID_OPERATION);
2686                 }
2687
2688                 if(!programObject->isLinked())
2689                 {
2690                         for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2691                         {
2692                                 uniformIndices[uniformId] = GL_INVALID_INDEX;
2693                         }
2694                 }
2695                 else
2696                 {
2697                         for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2698                         {
2699                                 uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
2700                         }
2701                 }
2702         }
2703 }
2704
2705 GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
2706 {
2707         TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLenum pname = 0x%X, GLuint *uniformIndices = %p)",
2708               program, uniformCount, uniformIndices, pname, uniformIndices);
2709
2710         switch(pname)
2711         {
2712         case GL_UNIFORM_TYPE:
2713         case GL_UNIFORM_SIZE:
2714         case GL_UNIFORM_NAME_LENGTH:
2715         case GL_UNIFORM_BLOCK_INDEX:
2716         case GL_UNIFORM_OFFSET:
2717         case GL_UNIFORM_ARRAY_STRIDE:
2718         case GL_UNIFORM_MATRIX_STRIDE:
2719         case GL_UNIFORM_IS_ROW_MAJOR:
2720                 break;
2721         default:
2722                 return error(GL_INVALID_ENUM);
2723         }
2724
2725         if(uniformCount < 0)
2726         {
2727                 return error(GL_INVALID_VALUE);
2728         }
2729
2730         es2::Context *context = es2::getContext();
2731
2732         if(context)
2733         {
2734                 es2::Program *programObject = context->getProgram(program);
2735
2736                 if(!programObject)
2737                 {
2738                         return error(GL_INVALID_OPERATION);
2739                 }
2740
2741                 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2742                 {
2743                         const GLuint index = uniformIndices[uniformId];
2744
2745                         if(index >= programObject->getActiveUniformCount())
2746                         {
2747                                 return error(GL_INVALID_VALUE);
2748                         }
2749                 }
2750
2751                 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2752                 {
2753                         const GLuint index = uniformIndices[uniformId];
2754                         params[uniformId] = programObject->getActiveUniformi(index, pname);
2755                 }
2756         }
2757 }
2758
2759 GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
2760 {
2761         TRACE("(GLuint program = %d, const GLchar *uniformBlockName = %p)",
2762               program, uniformBlockName);
2763
2764         es2::Context *context = es2::getContext();
2765
2766         if(context)
2767         {
2768                 es2::Program *programObject = context->getProgram(program);
2769
2770                 if(!programObject)
2771                 {
2772                         return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
2773                 }
2774
2775                 return programObject->getUniformBlockIndex(uniformBlockName);
2776         }
2777
2778         return GL_INVALID_INDEX;
2779 }
2780
2781 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
2782 {
2783         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)",
2784               program, uniformBlockIndex, pname, params);
2785
2786         es2::Context *context = es2::getContext();
2787
2788         if(context)
2789         {
2790                 es2::Program *programObject = context->getProgram(program);
2791
2792                 if(!programObject)
2793                 {
2794                         return error(GL_INVALID_OPERATION);
2795                 }
2796
2797                 switch(pname)
2798                 {
2799                 case GL_UNIFORM_BLOCK_BINDING:
2800                         *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
2801                         break;
2802                 case GL_UNIFORM_BLOCK_DATA_SIZE:
2803                 case GL_UNIFORM_BLOCK_NAME_LENGTH:
2804                 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2805                 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2806                 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2807                 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2808                         programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
2809                         break;
2810                 default:
2811                         return error(GL_INVALID_ENUM);
2812                 }
2813         }
2814 }
2815
2816 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
2817 {
2818         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLchar *uniformBlockName = %p)",
2819               program, uniformBlockIndex, bufSize, length, uniformBlockName);
2820
2821         if(bufSize < 0)
2822         {
2823                 return error(GL_INVALID_VALUE);
2824         }
2825
2826         es2::Context *context = es2::getContext();
2827
2828         if(context)
2829         {
2830                 es2::Program *programObject = context->getProgram(program);
2831
2832                 if(!programObject)
2833                 {
2834                         return error(GL_INVALID_OPERATION);
2835                 }
2836
2837                 programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
2838         }
2839 }
2840
2841 GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2842 {
2843         TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",
2844               program, uniformBlockIndex, uniformBlockBinding);
2845
2846         if(uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS)
2847         {
2848                 return error(GL_INVALID_VALUE);
2849         }
2850
2851         es2::Context *context = es2::getContext();
2852
2853         if(context)
2854         {
2855                 es2::Program *programObject = context->getProgram(program);
2856
2857                 if(!programObject)
2858                 {
2859                         return error(GL_INVALID_VALUE);
2860                 }
2861
2862                 programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
2863         }
2864 }
2865
2866 GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
2867 {
2868         TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
2869               mode, first, count, instanceCount);
2870
2871         switch(mode)
2872         {
2873         case GL_POINTS:
2874         case GL_LINES:
2875         case GL_LINE_LOOP:
2876         case GL_LINE_STRIP:
2877         case GL_TRIANGLES:
2878         case GL_TRIANGLE_FAN:
2879         case GL_TRIANGLE_STRIP:
2880                 break;
2881         default:
2882                 return error(GL_INVALID_ENUM);
2883         }
2884
2885         if(count < 0 || instanceCount < 0)
2886         {
2887                 return error(GL_INVALID_VALUE);
2888         }
2889
2890         es2::Context *context = es2::getContext();
2891
2892         if(context)
2893         {
2894                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
2895                 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
2896                 {
2897                         return error(GL_INVALID_OPERATION);
2898                 }
2899
2900                 context->drawArrays(mode, first, count, instanceCount);
2901         }
2902 }
2903
2904 GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
2905 {
2906         TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
2907               mode, count, type, indices, instanceCount);
2908
2909         switch(mode)
2910         {
2911         case GL_POINTS:
2912         case GL_LINES:
2913         case GL_LINE_LOOP:
2914         case GL_LINE_STRIP:
2915         case GL_TRIANGLES:
2916         case GL_TRIANGLE_FAN:
2917         case GL_TRIANGLE_STRIP:
2918                 break;
2919         default:
2920                 return error(GL_INVALID_ENUM);
2921         }
2922
2923         switch(type)
2924         {
2925         case GL_UNSIGNED_BYTE:
2926         case GL_UNSIGNED_SHORT:
2927         case GL_UNSIGNED_INT:
2928                 break;
2929         default:
2930                 return error(GL_INVALID_ENUM);
2931         }
2932
2933         if(count < 0 || instanceCount < 0)
2934         {
2935                 return error(GL_INVALID_VALUE);
2936         }
2937
2938         es2::Context *context = es2::getContext();
2939
2940         if(context)
2941         {
2942                 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
2943                 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
2944                 {
2945                         return error(GL_INVALID_OPERATION);
2946                 }
2947
2948                 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
2949         }
2950 }
2951
2952 GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
2953 {
2954         TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags);
2955
2956         switch(condition)
2957         {
2958         case GL_SYNC_GPU_COMMANDS_COMPLETE:
2959                 break;
2960         default:
2961                 return error(GL_INVALID_ENUM, nullptr);
2962         }
2963
2964         if(flags != 0)
2965         {
2966                 return error(GL_INVALID_VALUE, nullptr);
2967         }
2968
2969         es2::Context *context = es2::getContext();
2970
2971         if(context)
2972         {
2973                 return context->createFenceSync(condition, flags);
2974         }
2975
2976         return nullptr;
2977 }
2978
2979 GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync)
2980 {
2981         TRACE("(GLsync sync = %p)", sync);
2982
2983         es2::Context *context = es2::getContext();
2984
2985         if(context)
2986         {
2987                 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
2988
2989                 if(fenceSyncObject)
2990                 {
2991                         return GL_TRUE;
2992        &n