• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
InsertFormatMapping(FormatMap & map,GLenum internalformat,GLenum format,GLenum type)40 static void InsertFormatMapping(FormatMap& map, GLenum internalformat, GLenum format, GLenum type)
41 {
42 	map[InternalFormatTypePair(internalformat, type)] = format;
43 }
44 
validImageSize(GLint level,GLsizei width,GLsizei height)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 
validateColorBufferFormat(GLenum textureFormat,GLenum colorbufferFormat)56 static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
57 {
58 	GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
59 	if(validationError != GL_NONE)
60 	{
61 		return error(validationError, false);
62 	}
63 
64 	switch(textureFormat)
65 	{
66 	case GL_ALPHA:
67 		if(colorbufferFormat != GL_ALPHA &&
68 		   colorbufferFormat != GL_RGBA &&
69 		   colorbufferFormat != GL_RGBA4 &&
70 		   colorbufferFormat != GL_RGB5_A1 &&
71 		   colorbufferFormat != GL_RGBA8)
72 		{
73 			return error(GL_INVALID_OPERATION, false);
74 		}
75 		break;
76 	case GL_LUMINANCE:
77 	case GL_RGB:
78 		if(colorbufferFormat != GL_RGB &&
79 		   colorbufferFormat != GL_RGB565 &&
80 		   colorbufferFormat != GL_RGB8 &&
81 		   colorbufferFormat != GL_RGBA &&
82 		   colorbufferFormat != GL_RGBA4 &&
83 		   colorbufferFormat != GL_RGB5_A1 &&
84 		   colorbufferFormat != GL_RGBA8)
85 		{
86 			return error(GL_INVALID_OPERATION, false);
87 		}
88 		break;
89 	case GL_LUMINANCE_ALPHA:
90 	case GL_RGBA:
91 		if(colorbufferFormat != GL_RGBA &&
92 		   colorbufferFormat != GL_RGBA4 &&
93 		   colorbufferFormat != GL_RGB5_A1 &&
94 		   colorbufferFormat != GL_RGBA8)
95 		{
96 			return error(GL_INVALID_OPERATION, false);
97 		}
98 		break;
99 	case GL_DEPTH_COMPONENT:
100 	case GL_DEPTH_STENCIL:
101 		return error(GL_INVALID_OPERATION, false);
102 	default:
103 		return error(GL_INVALID_ENUM, false);
104 	}
105 	return true;
106 }
107 
BuildFormatMap3D()108 static FormatMap BuildFormatMap3D()
109 {
110 	FormatMap map;
111 
112 	//                       Internal format | Format | Type
113 	InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
114 	InsertFormatMapping(map, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
115 	InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
116 	InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
117 	InsertFormatMapping(map, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
118 	InsertFormatMapping(map, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
119 	InsertFormatMapping(map, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
120 	InsertFormatMapping(map, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
121 	InsertFormatMapping(map, GL_R8, GL_RED, GL_UNSIGNED_BYTE);
122 	InsertFormatMapping(map, GL_R8_SNORM, GL_RED, GL_BYTE);
123 	InsertFormatMapping(map, GL_R16F, GL_RED, GL_HALF_FLOAT);
124 	InsertFormatMapping(map, GL_R16F, GL_RED, GL_FLOAT);
125 	InsertFormatMapping(map, GL_R32F, GL_RED, GL_FLOAT);
126 	InsertFormatMapping(map, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE);
127 	InsertFormatMapping(map, GL_R8I, GL_RED_INTEGER, GL_BYTE);
128 	InsertFormatMapping(map, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT);
129 	InsertFormatMapping(map, GL_R16I, GL_RED_INTEGER, GL_SHORT);
130 	InsertFormatMapping(map, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT);
131 	InsertFormatMapping(map, GL_R32I, GL_RED_INTEGER, GL_INT);
132 	InsertFormatMapping(map, GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
133 	InsertFormatMapping(map, GL_RG8_SNORM, GL_RG, GL_BYTE);
134 	InsertFormatMapping(map, GL_RG16F, GL_RG, GL_HALF_FLOAT);
135 	InsertFormatMapping(map, GL_RG16F, GL_RG, GL_FLOAT);
136 	InsertFormatMapping(map, GL_RG32F, GL_RG, GL_FLOAT);
137 	InsertFormatMapping(map, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE);
138 	InsertFormatMapping(map, GL_RG8I, GL_RG_INTEGER, GL_BYTE);
139 	InsertFormatMapping(map, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT);
140 	InsertFormatMapping(map, GL_RG16I, GL_RG_INTEGER, GL_SHORT);
141 	InsertFormatMapping(map, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT);
142 	InsertFormatMapping(map, GL_RG32I, GL_RG_INTEGER, GL_INT);
143 	InsertFormatMapping(map, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE);
144 	InsertFormatMapping(map, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE);
145 	InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE);
146 	InsertFormatMapping(map, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
147 	InsertFormatMapping(map, GL_RGB8_SNORM, GL_RGB, GL_BYTE);
148 	InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV);
149 	InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT);
150 	InsertFormatMapping(map, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT);
151 	InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);
152 	InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT);
153 	InsertFormatMapping(map, GL_RGB9_E5, GL_RGB, GL_FLOAT);
154 	InsertFormatMapping(map, GL_RGB16F, GL_RGB, GL_HALF_FLOAT);
155 	InsertFormatMapping(map, GL_RGB16F, GL_RGB, GL_FLOAT);
156 	InsertFormatMapping(map, GL_RGB32F, GL_RGB, GL_FLOAT);
157 	InsertFormatMapping(map, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE);
158 	InsertFormatMapping(map, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE);
159 	InsertFormatMapping(map, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT);
160 	InsertFormatMapping(map, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT);
161 	InsertFormatMapping(map, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT);
162 	InsertFormatMapping(map, GL_RGB32I, GL_RGB_INTEGER, GL_INT);
163 	InsertFormatMapping(map, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
164 	InsertFormatMapping(map, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE);
165 	InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE);
166 	InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
167 	InsertFormatMapping(map, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
168 	InsertFormatMapping(map, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE);
169 	InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE);
170 	InsertFormatMapping(map, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
171 	InsertFormatMapping(map, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
172 	InsertFormatMapping(map, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT);
173 	InsertFormatMapping(map, GL_RGBA16F, GL_RGBA, GL_FLOAT);
174 	InsertFormatMapping(map, GL_RGBA32F, GL_RGBA, GL_FLOAT);
175 	InsertFormatMapping(map, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE);
176 	InsertFormatMapping(map, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE);
177 	InsertFormatMapping(map, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV);
178 	InsertFormatMapping(map, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT);
179 	InsertFormatMapping(map, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT);
180 	InsertFormatMapping(map, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
181 	InsertFormatMapping(map, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
182 
183 	InsertFormatMapping(map, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
184 	InsertFormatMapping(map, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
185 	InsertFormatMapping(map, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
186 	InsertFormatMapping(map, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
187 	InsertFormatMapping(map, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT);
188 	InsertFormatMapping(map, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
189 	InsertFormatMapping(map, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
190 
191 	return map;
192 }
193 
ValidateType3D(GLenum type)194 static bool ValidateType3D(GLenum type)
195 {
196 	switch(type)
197 	{
198 	case GL_UNSIGNED_BYTE:
199 	case GL_BYTE:
200 	case GL_UNSIGNED_SHORT:
201 	case GL_SHORT:
202 	case GL_UNSIGNED_INT:
203 	case GL_INT:
204 	case GL_HALF_FLOAT:
205 	case GL_FLOAT:
206 	case GL_UNSIGNED_SHORT_5_6_5:
207 	case GL_UNSIGNED_SHORT_4_4_4_4:
208 	case GL_UNSIGNED_SHORT_5_5_5_1:
209 	case GL_UNSIGNED_INT_2_10_10_10_REV:
210 	case GL_UNSIGNED_INT_10F_11F_11F_REV:
211 	case GL_UNSIGNED_INT_5_9_9_9_REV:
212 	case GL_UNSIGNED_INT_24_8:
213 	case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
214 		return true;
215 	default:
216 		break;
217 	}
218 	return false;
219 }
220 
ValidateFormat3D(GLenum format)221 static bool ValidateFormat3D(GLenum format)
222 {
223 	switch(format)
224 	{
225 	case GL_RED:
226 	case GL_RG:
227 	case GL_RGB:
228 	case GL_RGBA:
229 	case GL_DEPTH_COMPONENT:
230 	case GL_DEPTH_STENCIL:
231 	case GL_LUMINANCE_ALPHA:
232 	case GL_LUMINANCE:
233 	case GL_ALPHA:
234 	case GL_RED_INTEGER:
235 	case GL_RG_INTEGER:
236 	case GL_RGB_INTEGER:
237 	case GL_RGBA_INTEGER:
238 		return true;
239 	default:
240 		break;
241 	}
242 	return false;
243 }
244 
ValidateInternalFormat3D(GLenum internalformat,GLenum format,GLenum type)245 static bool ValidateInternalFormat3D(GLenum internalformat, GLenum format, GLenum type)
246 {
247 	static const FormatMap formatMap = BuildFormatMap3D();
248 	FormatMap::const_iterator iter = formatMap.find(InternalFormatTypePair(internalformat, type));
249 	if(iter != formatMap.end())
250 	{
251 		return iter->second == format;
252 	}
253 	return false;
254 }
255 
256 typedef std::map<GLenum, GLenum> FormatMapStorage;
257 
258 // A helper function to insert data into the format map with fewer characters.
InsertFormatStorageMapping(FormatMapStorage & map,GLenum internalformat,GLenum type)259 static void InsertFormatStorageMapping(FormatMapStorage& map, GLenum internalformat, GLenum type)
260 {
261 	map[internalformat] = type;
262 }
263 
BuildFormatMapStorage2D()264 static FormatMapStorage BuildFormatMapStorage2D()
265 {
266 	FormatMapStorage map;
267 
268 	//                              Internal format | Type
269 	InsertFormatStorageMapping(map, GL_R8, GL_UNSIGNED_BYTE);
270 	InsertFormatStorageMapping(map, GL_R8_SNORM, GL_UNSIGNED_BYTE);
271 	InsertFormatStorageMapping(map, GL_R16F, GL_HALF_FLOAT);
272 	InsertFormatStorageMapping(map, GL_R32F, GL_FLOAT);
273 	InsertFormatStorageMapping(map, GL_R8UI, GL_UNSIGNED_BYTE);
274 	InsertFormatStorageMapping(map, GL_R8I, GL_BYTE);
275 	InsertFormatStorageMapping(map, GL_R16UI, GL_UNSIGNED_SHORT);
276 	InsertFormatStorageMapping(map, GL_R16I, GL_SHORT);
277 	InsertFormatStorageMapping(map, GL_R32UI, GL_UNSIGNED_INT);
278 	InsertFormatStorageMapping(map, GL_R32I, GL_INT);
279 	InsertFormatStorageMapping(map, GL_RG8, GL_UNSIGNED_BYTE);
280 	InsertFormatStorageMapping(map, GL_RG8_SNORM, GL_BYTE);
281 	InsertFormatStorageMapping(map, GL_RG16F, GL_HALF_FLOAT);
282 	InsertFormatStorageMapping(map, GL_RG32F, GL_FLOAT);
283 	InsertFormatStorageMapping(map, GL_RG8UI, GL_UNSIGNED_BYTE);
284 	InsertFormatStorageMapping(map, GL_RG8I, GL_BYTE);
285 	InsertFormatStorageMapping(map, GL_RG16UI, GL_UNSIGNED_SHORT);
286 	InsertFormatStorageMapping(map, GL_RG16I, GL_SHORT);
287 	InsertFormatStorageMapping(map, GL_RG32UI, GL_UNSIGNED_INT);
288 	InsertFormatStorageMapping(map, GL_RG32I, GL_INT);
289 	InsertFormatStorageMapping(map, GL_RGB8, GL_UNSIGNED_BYTE);
290 	InsertFormatStorageMapping(map, GL_SRGB8, GL_UNSIGNED_BYTE);
291 	InsertFormatStorageMapping(map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5);
292 	InsertFormatStorageMapping(map, GL_RGB8_SNORM, GL_BYTE);
293 	InsertFormatStorageMapping(map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV);
294 	InsertFormatStorageMapping(map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV);
295 	InsertFormatStorageMapping(map, GL_RGB16F, GL_HALF_FLOAT);
296 	InsertFormatStorageMapping(map, GL_RGB32F, GL_FLOAT);
297 	InsertFormatStorageMapping(map, GL_RGB8UI, GL_UNSIGNED_BYTE);
298 	InsertFormatStorageMapping(map, GL_RGB8I, GL_BYTE);
299 	InsertFormatStorageMapping(map, GL_RGB16UI, GL_UNSIGNED_SHORT);
300 	InsertFormatStorageMapping(map, GL_RGB16I, GL_SHORT);
301 	InsertFormatStorageMapping(map, GL_RGB32UI, GL_UNSIGNED_INT);
302 	InsertFormatStorageMapping(map, GL_RGB32I, GL_INT);
303 	InsertFormatStorageMapping(map, GL_RGBA8, GL_UNSIGNED_BYTE);
304 	InsertFormatStorageMapping(map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE);
305 	InsertFormatStorageMapping(map, GL_RGBA8_SNORM, GL_BYTE);
306 	InsertFormatStorageMapping(map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
307 	InsertFormatStorageMapping(map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
308 	InsertFormatStorageMapping(map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV);
309 	InsertFormatStorageMapping(map, GL_RGBA16F, GL_HALF_FLOAT);
310 	InsertFormatStorageMapping(map, GL_RGBA32F, GL_FLOAT);
311 	InsertFormatStorageMapping(map, GL_RGBA8UI, GL_UNSIGNED_BYTE);
312 	InsertFormatStorageMapping(map, GL_RGBA8I, GL_BYTE);
313 	InsertFormatStorageMapping(map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV);
314 	InsertFormatStorageMapping(map, GL_RGBA16UI, GL_UNSIGNED_SHORT);
315 	InsertFormatStorageMapping(map, GL_RGBA16I, GL_SHORT);
316 	InsertFormatStorageMapping(map, GL_RGBA32UI, GL_UNSIGNED_INT);
317 	InsertFormatStorageMapping(map, GL_RGBA32I, GL_INT);
318 
319 	InsertFormatStorageMapping(map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT);
320 	InsertFormatStorageMapping(map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT);
321 	InsertFormatStorageMapping(map, GL_DEPTH_COMPONENT32F, GL_FLOAT);
322 	InsertFormatStorageMapping(map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);
323 	InsertFormatStorageMapping(map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
324 
325 	return map;
326 }
327 
GetStorageType(GLenum internalformat,GLenum & type)328 static bool GetStorageType(GLenum internalformat, GLenum& type)
329 {
330 	static const FormatMapStorage formatMap = BuildFormatMapStorage2D();
331 	FormatMapStorage::const_iterator iter = formatMap.find(internalformat);
332 	if(iter != formatMap.end())
333 	{
334 		type = iter->second;
335 		return true;
336 	}
337 	return false;
338 }
339 
ValidateQueryTarget(GLenum target)340 static bool ValidateQueryTarget(GLenum target)
341 {
342 	switch(target)
343 	{
344 	case GL_ANY_SAMPLES_PASSED:
345 	case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
346 	case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
347 		break;
348 	default:
349 		return false;
350 	}
351 
352 	return true;
353 }
354 
ValidateTexParamParameters(GLenum pname,GLint param)355 bool ValidateTexParamParameters(GLenum pname, GLint param)
356 {
357 	switch(pname)
358 	{
359 	case GL_TEXTURE_WRAP_S:
360 	case GL_TEXTURE_WRAP_T:
361 	case GL_TEXTURE_WRAP_R:
362 		switch(param)
363 		{
364 		case GL_REPEAT:
365 		case GL_CLAMP_TO_EDGE:
366 		case GL_MIRRORED_REPEAT:
367 			return true;
368 		default:
369 			return error(GL_INVALID_ENUM, false);
370 		}
371 
372 	case GL_TEXTURE_MIN_FILTER:
373 		switch(param)
374 		{
375 		case GL_NEAREST:
376 		case GL_LINEAR:
377 		case GL_NEAREST_MIPMAP_NEAREST:
378 		case GL_LINEAR_MIPMAP_NEAREST:
379 		case GL_NEAREST_MIPMAP_LINEAR:
380 		case GL_LINEAR_MIPMAP_LINEAR:
381 			return true;
382 		default:
383 			return error(GL_INVALID_ENUM, false);
384 		}
385 		break;
386 
387 	case GL_TEXTURE_MAG_FILTER:
388 		switch(param)
389 		{
390 		case GL_NEAREST:
391 		case GL_LINEAR:
392 			return true;
393 		default:
394 			return error(GL_INVALID_ENUM, false);
395 		}
396 		break;
397 
398 	case GL_TEXTURE_USAGE_ANGLE:
399 		switch(param)
400 		{
401 		case GL_NONE:
402 		case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
403 			return true;
404 		default:
405 			return error(GL_INVALID_ENUM, false);
406 		}
407 		break;
408 
409 	case GL_TEXTURE_MAX_ANISOTROPY_EXT:
410 		// we assume the parameter passed to this validation method is truncated, not rounded
411 		if(param < 1)
412 		{
413 			return error(GL_INVALID_VALUE, false);
414 		}
415 		return true;
416 
417 	case GL_TEXTURE_MIN_LOD:
418 	case GL_TEXTURE_MAX_LOD:
419 		// any value is permissible
420 		return true;
421 
422 	case GL_TEXTURE_COMPARE_MODE:
423 		// Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
424 		switch(param)
425 		{
426 		case GL_NONE:
427 		case GL_COMPARE_REF_TO_TEXTURE:
428 			return true;
429 		default:
430 			return error(GL_INVALID_ENUM, false);
431 		}
432 		break;
433 
434 	case GL_TEXTURE_COMPARE_FUNC:
435 		// Acceptable function parameters from GLES 3.0.2 spec, table 3.17
436 		switch(param)
437 		{
438 		case GL_LEQUAL:
439 		case GL_GEQUAL:
440 		case GL_LESS:
441 		case GL_GREATER:
442 		case GL_EQUAL:
443 		case GL_NOTEQUAL:
444 		case GL_ALWAYS:
445 		case GL_NEVER:
446 			return true;
447 		default:
448 			return error(GL_INVALID_ENUM, false);
449 		}
450 		break;
451 
452 	case GL_TEXTURE_SWIZZLE_R:
453 	case GL_TEXTURE_SWIZZLE_G:
454 	case GL_TEXTURE_SWIZZLE_B:
455 	case GL_TEXTURE_SWIZZLE_A:
456 		switch(param)
457 		{
458 		case GL_RED:
459 		case GL_GREEN:
460 		case GL_BLUE:
461 		case GL_ALPHA:
462 		case GL_ZERO:
463 		case GL_ONE:
464 			return true;
465 		default:
466 			return error(GL_INVALID_ENUM, false);
467 		}
468 		break;
469 
470 	case GL_TEXTURE_BASE_LEVEL:
471 	case GL_TEXTURE_MAX_LEVEL:
472 		if(param < 0)
473 		{
474 			return error(GL_INVALID_VALUE, false);
475 		}
476 		return true;
477 
478 	default:
479 		return error(GL_INVALID_ENUM, false);
480 	}
481 }
482 
ValidateSamplerObjectParameter(GLenum pname)483 static bool ValidateSamplerObjectParameter(GLenum pname)
484 {
485 	switch(pname)
486 	{
487 	case GL_TEXTURE_MIN_FILTER:
488 	case GL_TEXTURE_MAG_FILTER:
489 	case GL_TEXTURE_WRAP_S:
490 	case GL_TEXTURE_WRAP_T:
491 	case GL_TEXTURE_WRAP_R:
492 	case GL_TEXTURE_MIN_LOD:
493 	case GL_TEXTURE_MAX_LOD:
494 	case GL_TEXTURE_COMPARE_MODE:
495 	case GL_TEXTURE_COMPARE_FUNC:
496 		return true;
497 	default:
498 		return false;
499 	}
500 }
501 
502 extern "C"
503 {
504 
glReadBuffer(GLenum src)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 
glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const void * indices)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 
glTexImage3D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)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 *pixels)
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* pixels = %p)",
632 	      target, level, internalformat, width, height, depth, border, format, type, pixels);
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(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), pixels);
681 	}
682 }
683 
glTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)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 *pixels)
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* pixels = %p)",
689 		target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
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(level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
727 		}
728 		else
729 		{
730 			return error(validationError);
731 		}
732 	}
733 }
734 
glCopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)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 
glCompressedTexImage3D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)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 
glCompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)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, data);
911 	}
912 }
913 
glGenQueries(GLsizei n,GLuint * ids)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 
glDeleteQueries(GLsizei n,const GLuint * ids)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 
glIsQuery(GLuint id)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 
glBeginQuery(GLenum target,GLuint id)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 
glEndQuery(GLenum target)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 
glGetQueryiv(GLenum target,GLenum pname,GLint * params)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 
glGetQueryObjectuiv(GLuint id,GLenum pname,GLuint * params)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 
glUnmapBuffer(GLenum target)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 
glGetBufferPointerv(GLenum target,GLenum pname,void ** params)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 
glDrawBuffers(GLsizei n,const GLenum * bufs)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 
glUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)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 
glBlitFramebuffer(GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)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);
1451 	}
1452 }
1453 
glRenderbufferStorageMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1454 GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
1455 {
1456 	TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
1457 	      target, samples, internalformat, width, height);
1458 
1459 	switch(target)
1460 	{
1461 	case GL_RENDERBUFFER:
1462 		break;
1463 	default:
1464 		return error(GL_INVALID_ENUM);
1465 	}
1466 
1467 	if(width < 0 || height < 0 || samples < 0)
1468 	{
1469 		return error(GL_INVALID_VALUE);
1470 	}
1471 
1472 	es2::Context *context = es2::getContext();
1473 
1474 	if(context)
1475 	{
1476 		if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
1477 		   height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
1478 		   samples > es2::IMPLEMENTATION_MAX_SAMPLES)
1479 		{
1480 			return error(GL_INVALID_VALUE);
1481 		}
1482 
1483 		GLuint handle = context->getRenderbufferName();
1484 		if(handle == 0)
1485 		{
1486 			return error(GL_INVALID_OPERATION);
1487 		}
1488 
1489 		switch(internalformat)
1490 		{
1491 		case GL_DEPTH_COMPONENT16:
1492 		case GL_DEPTH_COMPONENT24:
1493 		case GL_DEPTH_COMPONENT32_OES:
1494 		case GL_DEPTH_COMPONENT32F:
1495 			context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
1496 			break;
1497 		case GL_R8UI:
1498 		case GL_R8I:
1499 		case GL_R16UI:
1500 		case GL_R16I:
1501 		case GL_R32UI:
1502 		case GL_R32I:
1503 		case GL_RG8UI:
1504 		case GL_RG8I:
1505 		case GL_RG16UI:
1506 		case GL_RG16I:
1507 		case GL_RG32UI:
1508 		case GL_RG32I:
1509 		case GL_RGB8UI:
1510 		case GL_RGB8I:
1511 		case GL_RGB16UI:
1512 		case GL_RGB16I:
1513 		case GL_RGB32UI:
1514 		case GL_RGB32I:
1515 		case GL_RGBA8UI:
1516 		case GL_RGBA8I:
1517 		case GL_RGB10_A2UI:
1518 		case GL_RGBA16UI:
1519 		case GL_RGBA16I:
1520 		case GL_RGBA32UI:
1521 		case GL_RGBA32I:
1522 			if(samples > 0)
1523 			{
1524 				return error(GL_INVALID_OPERATION);
1525 			}
1526 		case GL_RGBA4:
1527 		case GL_RGB5_A1:
1528 		case GL_RGB565:
1529 		case GL_SRGB8_ALPHA8:
1530 		case GL_RGB10_A2:
1531 		case GL_R8:
1532 		case GL_RG8:
1533 		case GL_RGB8:
1534 		case GL_RGBA8:
1535 			context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
1536 			break;
1537 		case GL_STENCIL_INDEX8:
1538 			context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
1539 			break;
1540 		case GL_DEPTH24_STENCIL8:
1541 		case GL_DEPTH32F_STENCIL8:
1542 			context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
1543 			break;
1544 
1545 		default:
1546 			return error(GL_INVALID_ENUM);
1547 		}
1548 	}
1549 }
1550 
glFramebufferTextureLayer(GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)1551 GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
1552 {
1553 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",
1554 	      target, attachment, texture, level, layer);
1555 
1556 	// GLES 3.0.4 spec, p.209, section 4.4.2
1557 	// If texture is zero, any image or array of images attached to the attachment point
1558 	// named by attachment is detached. Any additional parameters(level, textarget,
1559 	// and / or layer) are ignored when texture is zero.
1560 	if(texture != 0 && (layer < 0 || level < 0))
1561 	{
1562 		return error(GL_INVALID_VALUE);
1563 	}
1564 
1565 	es2::Context *context = es2::getContext();
1566 
1567 	if(context)
1568 	{
1569 		Texture* textureObject = context->getTexture(texture);
1570 		GLenum textarget = GL_NONE;
1571 		if(texture != 0)
1572 		{
1573 			if(!textureObject)
1574 			{
1575 				return error(GL_INVALID_VALUE);
1576 			}
1577 
1578 			textarget = textureObject->getTarget();
1579 			switch(textarget)
1580 			{
1581 			case GL_TEXTURE_3D:
1582 			case GL_TEXTURE_2D_ARRAY:
1583 				if(layer >= es2::IMPLEMENTATION_MAX_TEXTURE_SIZE || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1584 				{
1585 					return error(GL_INVALID_VALUE);
1586 				}
1587 				break;
1588 			default:
1589 				return error(GL_INVALID_OPERATION);
1590 			}
1591 
1592 			if(textureObject->isCompressed(textarget, level))
1593 			{
1594 				return error(GL_INVALID_OPERATION);
1595 			}
1596 		}
1597 
1598 		es2::Framebuffer *framebuffer = nullptr;
1599 		switch(target)
1600 		{
1601 		case GL_DRAW_FRAMEBUFFER:
1602 		case GL_FRAMEBUFFER:
1603 			framebuffer = context->getDrawFramebuffer();
1604 			break;
1605 		case GL_READ_FRAMEBUFFER:
1606 			framebuffer = context->getReadFramebuffer();
1607 			break;
1608 		default:
1609 			return error(GL_INVALID_ENUM);
1610 		}
1611 
1612 		if(!framebuffer)
1613 		{
1614 			return error(GL_INVALID_OPERATION);
1615 		}
1616 
1617 		switch(attachment)
1618 		{
1619 		case GL_COLOR_ATTACHMENT0:
1620 		case GL_COLOR_ATTACHMENT1:
1621 		case GL_COLOR_ATTACHMENT2:
1622 		case GL_COLOR_ATTACHMENT3:
1623 		case GL_COLOR_ATTACHMENT4:
1624 		case GL_COLOR_ATTACHMENT5:
1625 		case GL_COLOR_ATTACHMENT6:
1626 		case GL_COLOR_ATTACHMENT7:
1627 		case GL_COLOR_ATTACHMENT8:
1628 		case GL_COLOR_ATTACHMENT9:
1629 		case GL_COLOR_ATTACHMENT10:
1630 		case GL_COLOR_ATTACHMENT11:
1631 		case GL_COLOR_ATTACHMENT12:
1632 		case GL_COLOR_ATTACHMENT13:
1633 		case GL_COLOR_ATTACHMENT14:
1634 		case GL_COLOR_ATTACHMENT15:
1635 		case GL_COLOR_ATTACHMENT16:
1636 		case GL_COLOR_ATTACHMENT17:
1637 		case GL_COLOR_ATTACHMENT18:
1638 		case GL_COLOR_ATTACHMENT19:
1639 		case GL_COLOR_ATTACHMENT20:
1640 		case GL_COLOR_ATTACHMENT21:
1641 		case GL_COLOR_ATTACHMENT22:
1642 		case GL_COLOR_ATTACHMENT23:
1643 		case GL_COLOR_ATTACHMENT24:
1644 		case GL_COLOR_ATTACHMENT25:
1645 		case GL_COLOR_ATTACHMENT26:
1646 		case GL_COLOR_ATTACHMENT27:
1647 		case GL_COLOR_ATTACHMENT28:
1648 		case GL_COLOR_ATTACHMENT29:
1649 		case GL_COLOR_ATTACHMENT30:
1650 		case GL_COLOR_ATTACHMENT31:
1651 			framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level, layer);
1652 			break;
1653 		case GL_DEPTH_ATTACHMENT:
1654 			framebuffer->setDepthbuffer(textarget, texture, level, layer);
1655 			break;
1656 		case GL_STENCIL_ATTACHMENT:
1657 			framebuffer->setStencilbuffer(textarget, texture, level, layer);
1658 			break;
1659 		case GL_DEPTH_STENCIL_ATTACHMENT:
1660 			framebuffer->setDepthbuffer(textarget, texture, level, layer);
1661 			framebuffer->setStencilbuffer(textarget, texture, level, layer);
1662 			break;
1663 		default:
1664 			return error(GL_INVALID_ENUM);
1665 		}
1666 	}
1667 }
1668 
glMapBufferRange(GLenum target,GLintptr offset,GLsizeiptr length,GLbitfield access)1669 GL_APICALL void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
1670 {
1671 	TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",
1672 	      target, offset, length, access);
1673 
1674 	es2::Context *context = es2::getContext();
1675 
1676 	if(context)
1677 	{
1678 		es2::Buffer *buffer = nullptr;
1679 		if(!context->getBuffer(target, &buffer))
1680 		{
1681 			return error(GL_INVALID_ENUM, nullptr);
1682 		}
1683 
1684 		if(!buffer)
1685 		{
1686 			// A null buffer means that "0" is bound to the requested buffer target
1687 			return error(GL_INVALID_OPERATION, nullptr);
1688 		}
1689 
1690 		GLsizeiptr bufferSize = buffer->size();
1691 		if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
1692 		{
1693 			error(GL_INVALID_VALUE);
1694 		}
1695 
1696 		if((access & ~(GL_MAP_READ_BIT |
1697 		               GL_MAP_WRITE_BIT |
1698 		               GL_MAP_INVALIDATE_RANGE_BIT |
1699 		               GL_MAP_INVALIDATE_BUFFER_BIT |
1700 		               GL_MAP_FLUSH_EXPLICIT_BIT |
1701 		               GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
1702 		{
1703 			error(GL_INVALID_VALUE);
1704 		}
1705 
1706 		return buffer->mapRange(offset, length, access);
1707 	}
1708 
1709 	return nullptr;
1710 }
1711 
glFlushMappedBufferRange(GLenum target,GLintptr offset,GLsizeiptr length)1712 GL_APICALL void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
1713 {
1714 	TRACE("(GLenum target = 0x%X,  GLintptr offset = %d, GLsizeiptr length = %d)",
1715 	      target, offset, length);
1716 
1717 	es2::Context *context = es2::getContext();
1718 
1719 	if(context)
1720 	{
1721 		es2::Buffer *buffer = nullptr;
1722 		if(!context->getBuffer(target, &buffer))
1723 		{
1724 			return error(GL_INVALID_ENUM);
1725 		}
1726 
1727 		if(!buffer)
1728 		{
1729 			// A null buffer means that "0" is bound to the requested buffer target
1730 			return error(GL_INVALID_OPERATION);
1731 		}
1732 
1733 		GLsizeiptr bufferSize = buffer->size();
1734 		if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
1735 		{
1736 			error(GL_INVALID_VALUE);
1737 		}
1738 
1739 		buffer->flushMappedRange(offset, length);
1740 	}
1741 }
1742 
glBindVertexArray(GLuint array)1743 GL_APICALL void GL_APIENTRY glBindVertexArray(GLuint array)
1744 {
1745 	TRACE("(GLuint array = %d)", array);
1746 
1747 	if(array == 0)
1748 	{
1749 		return;
1750 	}
1751 
1752 	es2::Context *context = es2::getContext();
1753 
1754 	if(context)
1755 	{
1756 		if(!context->isVertexArray(array))
1757 		{
1758 			return error(GL_INVALID_OPERATION);
1759 		}
1760 
1761 		context->bindVertexArray(array);
1762 	}
1763 }
1764 
glDeleteVertexArrays(GLsizei n,const GLuint * arrays)1765 GL_APICALL void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
1766 {
1767 	TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1768 
1769 	if(n < 0)
1770 	{
1771 		return error(GL_INVALID_VALUE);
1772 	}
1773 
1774 	es2::Context *context = es2::getContext();
1775 
1776 	if(context)
1777 	{
1778 		for(int i = 0; i < n; i++)
1779 		{
1780 			context->deleteVertexArray(arrays[i]);
1781 		}
1782 	}
1783 }
1784 
glGenVertexArrays(GLsizei n,GLuint * arrays)1785 GL_APICALL void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
1786 {
1787 	TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1788 
1789 	if(n < 0)
1790 	{
1791 		return error(GL_INVALID_VALUE);
1792 	}
1793 
1794 	es2::Context *context = es2::getContext();
1795 
1796 	if(context)
1797 	{
1798 		for(int i = 0; i < n; i++)
1799 		{
1800 			arrays[i] = context->createVertexArray();
1801 		}
1802 	}
1803 }
1804 
glIsVertexArray(GLuint array)1805 GL_APICALL GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
1806 {
1807 	TRACE("(GLuint array = %d)", array);
1808 
1809 	if(array == 0)
1810 	{
1811 		return GL_FALSE;
1812 	}
1813 
1814 	es2::Context *context = es2::getContext();
1815 
1816 	if(context)
1817 	{
1818 		es2::VertexArray *arrayObject = context->getVertexArray(array);
1819 
1820 		if(arrayObject)
1821 		{
1822 			return GL_TRUE;
1823 		}
1824 	}
1825 
1826 	return GL_FALSE;
1827 }
1828 
glGetIntegeri_v(GLenum target,GLuint index,GLint * data)1829 GL_APICALL void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)
1830 {
1831 	TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint* data = %p)",
1832 	      target, index, data);
1833 
1834 	es2::Context *context = es2::getContext();
1835 
1836 	if(context)
1837 	{
1838 		if(!context->getTransformFeedbackiv(index, target, data) &&
1839 		   !context->getUniformBufferiv(index, target, data) &&
1840 		   !context->getIntegerv(target, data))
1841 		{
1842 			GLenum nativeType;
1843 			unsigned int numParams = 0;
1844 			if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
1845 				return error(GL_INVALID_ENUM);
1846 
1847 			if(numParams == 0)
1848 				return; // it is known that target is valid, but there are no parameters to return
1849 
1850 			if(nativeType == GL_BOOL)
1851 			{
1852 				GLboolean *boolParams = nullptr;
1853 				boolParams = new GLboolean[numParams];
1854 
1855 				context->getBooleanv(target, boolParams);
1856 
1857 				for(unsigned int i = 0; i < numParams; ++i)
1858 				{
1859 					data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
1860 				}
1861 
1862 				delete[] boolParams;
1863 			}
1864 			else if(nativeType == GL_FLOAT)
1865 			{
1866 				GLfloat *floatParams = nullptr;
1867 				floatParams = new GLfloat[numParams];
1868 
1869 				context->getFloatv(target, floatParams);
1870 
1871 				for(unsigned int i = 0; i < numParams; ++i)
1872 				{
1873 					if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
1874 					{
1875 						data[i] = convert_float_int(floatParams[i]);
1876 					}
1877 					else
1878 					{
1879 						data[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
1880 					}
1881 				}
1882 
1883 				delete[] floatParams;
1884 			}
1885 		}
1886 	}
1887 }
1888 
glBeginTransformFeedback(GLenum primitiveMode)1889 GL_APICALL void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
1890 {
1891 	TRACE("(GLenum primitiveMode = 0x%X)", primitiveMode);
1892 
1893 	switch(primitiveMode)
1894 	{
1895 	case GL_POINTS:
1896 	case GL_LINES:
1897 	case GL_TRIANGLES:
1898 		break;
1899 	default:
1900 		return error(GL_INVALID_ENUM);
1901 	}
1902 
1903 	es2::Context *context = es2::getContext();
1904 
1905 	if(context)
1906 	{
1907 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1908 
1909 		if(transformFeedbackObject)
1910 		{
1911 			if(transformFeedbackObject->isActive())
1912 			{
1913 				return error(GL_INVALID_OPERATION);
1914 			}
1915 			transformFeedbackObject->begin(primitiveMode);
1916 		}
1917 		else
1918 		{
1919 			return error(GL_INVALID_OPERATION);
1920 		}
1921 	}
1922 }
1923 
glEndTransformFeedback(void)1924 GL_APICALL void GL_APIENTRY glEndTransformFeedback(void)
1925 {
1926 	TRACE("()");
1927 
1928 	es2::Context *context = es2::getContext();
1929 
1930 	if(context)
1931 	{
1932 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1933 
1934 		if(transformFeedbackObject)
1935 		{
1936 			if(!transformFeedbackObject->isActive())
1937 			{
1938 				return error(GL_INVALID_OPERATION);
1939 			}
1940 			transformFeedbackObject->end();
1941 		}
1942 		else
1943 		{
1944 			return error(GL_INVALID_OPERATION);
1945 		}
1946 	}
1947 }
1948 
glBindBufferRange(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)1949 GL_APICALL void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
1950 {
1951 	TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)",
1952 	      target, index, buffer, offset, size);
1953 
1954 	if(buffer != 0 && size <= 0)
1955 	{
1956 		return error(GL_INVALID_VALUE);
1957 	}
1958 
1959 	es2::Context *context = es2::getContext();
1960 
1961 	if(context)
1962 	{
1963 		switch(target)
1964 		{
1965 		case GL_TRANSFORM_FEEDBACK_BUFFER:
1966 			if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
1967 			{
1968 				return error(GL_INVALID_VALUE);
1969 			}
1970 			if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4
1971 			{
1972 				return error(GL_INVALID_VALUE);
1973 			}
1974 			context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
1975 			context->bindGenericTransformFeedbackBuffer(buffer);
1976 			break;
1977 		case GL_UNIFORM_BUFFER:
1978 			if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
1979 			{
1980 				return error(GL_INVALID_VALUE);
1981 			}
1982 			if(offset % UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0)
1983 			{
1984 				return error(GL_INVALID_VALUE);
1985 			}
1986 			context->bindIndexedUniformBuffer(buffer, index, offset, size);
1987 			context->bindGenericUniformBuffer(buffer);
1988 			break;
1989 		default:
1990 			return error(GL_INVALID_ENUM);
1991 		}
1992 	}
1993 }
1994 
glBindBufferBase(GLenum target,GLuint index,GLuint buffer)1995 GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
1996 {
1997 	TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)",
1998 	      target, index, buffer);
1999 
2000 	es2::Context *context = es2::getContext();
2001 
2002 	if(context)
2003 	{
2004 		switch(target)
2005 		{
2006 		case GL_TRANSFORM_FEEDBACK_BUFFER:
2007 			if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2008 			{
2009 				return error(GL_INVALID_VALUE);
2010 			}
2011 			context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
2012 			context->bindGenericTransformFeedbackBuffer(buffer);
2013 			break;
2014 		case GL_UNIFORM_BUFFER:
2015 			if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
2016 			{
2017 				return error(GL_INVALID_VALUE);
2018 			}
2019 			context->bindIndexedUniformBuffer(buffer, index, 0, 0);
2020 			context->bindGenericUniformBuffer(buffer);
2021 			break;
2022 		default:
2023 			return error(GL_INVALID_ENUM);
2024 		}
2025 	}
2026 }
2027 
glTransformFeedbackVaryings(GLuint program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2028 GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
2029 {
2030 	TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = %p, GLenum bufferMode = 0x%X)",
2031 	      program, count, varyings, bufferMode);
2032 
2033 	switch(bufferMode)
2034 	{
2035 	case GL_SEPARATE_ATTRIBS:
2036 		if(count > MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2037 		{
2038 			return error(GL_INVALID_VALUE);
2039 		}
2040 	case GL_INTERLEAVED_ATTRIBS:
2041 		break;
2042 	default:
2043 		return error(GL_INVALID_ENUM);
2044 	}
2045 
2046 	es2::Context *context = es2::getContext();
2047 
2048 	if(context)
2049 	{
2050 		es2::Program *programObject = context->getProgram(program);
2051 
2052 		if(!programObject)
2053 		{
2054 			return error(GL_INVALID_VALUE);
2055 		}
2056 
2057 		programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
2058 	}
2059 }
2060 
glGetTransformFeedbackVarying(GLuint program,GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name)2061 GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
2062 {
2063 	TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2064 	      program, index, bufSize, length, size, type, name);
2065 
2066 	if(bufSize < 0)
2067 	{
2068 		return error(GL_INVALID_VALUE);
2069 	}
2070 
2071 	es2::Context *context = es2::getContext();
2072 
2073 	if(context)
2074 	{
2075 		es2::Program *programObject = context->getProgram(program);
2076 
2077 		if(!programObject)
2078 		{
2079 			return error(GL_INVALID_VALUE);
2080 		}
2081 
2082 		if(index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
2083 		{
2084 			return error(GL_INVALID_VALUE);
2085 		}
2086 
2087 		programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
2088 	}
2089 }
2090 
glVertexAttribIPointer(GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer)2091 GL_APICALL void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
2092 {
2093 	TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2094 	      index, size, type, stride, pointer);
2095 
2096 	if(index >= es2::MAX_VERTEX_ATTRIBS)
2097 	{
2098 		return error(GL_INVALID_VALUE);
2099 	}
2100 
2101 	if(size < 1 || size > 4 || stride < 0)
2102 	{
2103 		return error(GL_INVALID_VALUE);
2104 	}
2105 
2106 	switch(type)
2107 	{
2108 	case GL_BYTE:
2109 	case GL_UNSIGNED_BYTE:
2110 	case GL_SHORT:
2111 	case GL_UNSIGNED_SHORT:
2112 	case GL_INT:
2113 	case GL_UNSIGNED_INT:
2114 		break;
2115 	default:
2116 		return error(GL_INVALID_ENUM);
2117 	}
2118 
2119 	es2::Context *context = es2::getContext();
2120 
2121 	if(context)
2122 	{
2123 		context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, stride, pointer);
2124 	}
2125 }
2126 
glGetVertexAttribIiv(GLuint index,GLenum pname,GLint * params)2127 GL_APICALL void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
2128 {
2129 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = %p)",
2130 	      index, pname, params);
2131 
2132 	es2::Context *context = es2::getContext();
2133 
2134 	if(context)
2135 	{
2136 		if(index >= es2::MAX_VERTEX_ATTRIBS)
2137 		{
2138 			return error(GL_INVALID_VALUE);
2139 		}
2140 
2141 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2142 
2143 		switch(pname)
2144 		{
2145 		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2146 			*params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2147 			break;
2148 		case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2149 			*params = attribState.mSize;
2150 			break;
2151 		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2152 			*params = attribState.mStride;
2153 			break;
2154 		case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2155 			*params = attribState.mType;
2156 			break;
2157 		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2158 			*params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2159 			break;
2160 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2161 			*params = attribState.mBoundBuffer.name();
2162 			break;
2163 		case GL_CURRENT_VERTEX_ATTRIB:
2164 			{
2165 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2166 				for(int i = 0; i < 4; ++i)
2167 				{
2168 					params[i] = attrib.getCurrentValueI(i);
2169 				}
2170 			}
2171 			break;
2172 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2173 			switch(attribState.mType)
2174 			{
2175 			case GL_BYTE:
2176 			case GL_UNSIGNED_BYTE:
2177 			case GL_SHORT:
2178 			case GL_UNSIGNED_SHORT:
2179 			case GL_INT:
2180 			case GL_INT_2_10_10_10_REV:
2181 			case GL_UNSIGNED_INT:
2182 			case GL_FIXED:
2183 				*params = GL_TRUE;
2184 				break;
2185 			default:
2186 				*params = GL_FALSE;
2187 				break;
2188 			}
2189 			break;
2190 		case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2191 			*params = attribState.mDivisor;
2192 			break;
2193 		default: return error(GL_INVALID_ENUM);
2194 		}
2195 	}
2196 }
2197 
glGetVertexAttribIuiv(GLuint index,GLenum pname,GLuint * params)2198 GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
2199 {
2200 	TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = %p)",
2201 		index, pname, params);
2202 
2203 	es2::Context *context = es2::getContext();
2204 
2205 	if(context)
2206 	{
2207 		if(index >= es2::MAX_VERTEX_ATTRIBS)
2208 		{
2209 			return error(GL_INVALID_VALUE);
2210 		}
2211 
2212 		const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2213 
2214 		switch(pname)
2215 		{
2216 		case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2217 			*params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2218 			break;
2219 		case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2220 			*params = attribState.mSize;
2221 			break;
2222 		case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2223 			*params = attribState.mStride;
2224 			break;
2225 		case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2226 			*params = attribState.mType;
2227 			break;
2228 		case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2229 			*params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2230 			break;
2231 		case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2232 			*params = attribState.mBoundBuffer.name();
2233 			break;
2234 		case GL_CURRENT_VERTEX_ATTRIB:
2235 			{
2236 				const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2237 				for(int i = 0; i < 4; ++i)
2238 				{
2239 					params[i] = attrib.getCurrentValueUI(i);
2240 				}
2241 			}
2242 			break;
2243 		case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2244 			switch(attribState.mType)
2245 			{
2246 			case GL_BYTE:
2247 			case GL_UNSIGNED_BYTE:
2248 			case GL_SHORT:
2249 			case GL_UNSIGNED_SHORT:
2250 			case GL_INT:
2251 			case GL_INT_2_10_10_10_REV:
2252 			case GL_UNSIGNED_INT:
2253 			case GL_FIXED:
2254 				*params = GL_TRUE;
2255 				break;
2256 			default:
2257 				*params = GL_FALSE;
2258 				break;
2259 			}
2260 			break;
2261 		case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2262 			*params = attribState.mDivisor;
2263 			break;
2264 		default: return error(GL_INVALID_ENUM);
2265 		}
2266 	}
2267 }
2268 
glVertexAttribI4i(GLuint index,GLint x,GLint y,GLint z,GLint w)2269 GL_APICALL void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
2270 {
2271 	TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2272 	      index, x, y, z, w);
2273 
2274 	if(index >= es2::MAX_VERTEX_ATTRIBS)
2275 	{
2276 		return error(GL_INVALID_VALUE);
2277 	}
2278 
2279 	es2::Context *context = es2::getContext();
2280 
2281 	if(context)
2282 	{
2283 		GLint vals[4] = { x, y, z, w };
2284 		context->setVertexAttrib(index, vals);
2285 	}
2286 }
2287 
glVertexAttribI4ui(GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)2288 GL_APICALL void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
2289 {
2290 	TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2291 	      index, x, y, z, w);
2292 
2293 	if(index >= es2::MAX_VERTEX_ATTRIBS)
2294 	{
2295 		return error(GL_INVALID_VALUE);
2296 	}
2297 
2298 	es2::Context *context = es2::getContext();
2299 
2300 	if(context)
2301 	{
2302 		GLuint vals[4] = { x, y, z, w };
2303 		context->setVertexAttrib(index, vals);
2304 	}
2305 }
2306 
glVertexAttribI4iv(GLuint index,const GLint * v)2307 GL_APICALL void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)
2308 {
2309 	TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2310 
2311 	if(index >= es2::MAX_VERTEX_ATTRIBS)
2312 	{
2313 		return error(GL_INVALID_VALUE);
2314 	}
2315 
2316 	es2::Context *context = es2::getContext();
2317 
2318 	if(context)
2319 	{
2320 		context->setVertexAttrib(index, v);
2321 	}
2322 }
2323 
glVertexAttribI4uiv(GLuint index,const GLuint * v)2324 GL_APICALL void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)
2325 {
2326 	TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2327 
2328 	if(index >= es2::MAX_VERTEX_ATTRIBS)
2329 	{
2330 		return error(GL_INVALID_VALUE);
2331 	}
2332 
2333 	es2::Context *context = es2::getContext();
2334 
2335 	if(context)
2336 	{
2337 		context->setVertexAttrib(index, v);
2338 	}
2339 }
2340 
glGetUniformuiv(GLuint program,GLint location,GLuint * params)2341 GL_APICALL void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)
2342 {
2343 	TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = %p)",
2344 	      program, location, params);
2345 
2346 	es2::Context *context = es2::getContext();
2347 
2348 	if(context)
2349 	{
2350 		if(program == 0)
2351 		{
2352 			return error(GL_INVALID_VALUE);
2353 		}
2354 
2355 		es2::Program *programObject = context->getProgram(program);
2356 
2357 		if(!programObject || !programObject->isLinked())
2358 		{
2359 			return error(GL_INVALID_OPERATION);
2360 		}
2361 
2362 		if(!programObject)
2363 		{
2364 			return error(GL_INVALID_OPERATION);
2365 		}
2366 
2367 		if(!programObject->getUniformuiv(location, nullptr, params))
2368 		{
2369 			return error(GL_INVALID_OPERATION);
2370 		}
2371 	}
2372 }
2373 
glGetFragDataLocation(GLuint program,const GLchar * name)2374 GL_APICALL GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
2375 {
2376 	TRACE("(GLuint program = %d, const GLchar *name = %p)", program, name);
2377 
2378 	es2::Context *context = es2::getContext();
2379 
2380 	if(strstr(name, "gl_") == name)
2381 	{
2382 		return -1;
2383 	}
2384 
2385 	if(context)
2386 	{
2387 		es2::Program *programObject = context->getProgram(program);
2388 
2389 		if(!programObject)
2390 		{
2391 			if(context->getShader(program))
2392 			{
2393 				return error(GL_INVALID_OPERATION, -1);
2394 			}
2395 			else
2396 			{
2397 				return error(GL_INVALID_VALUE, -1);
2398 			}
2399 		}
2400 
2401 		if(!programObject->isLinked())
2402 		{
2403 			return error(GL_INVALID_OPERATION, -1);
2404 		}
2405 	}
2406 
2407 	UNIMPLEMENTED();
2408 	return -1;
2409 }
2410 
glUniform1ui(GLint location,GLuint v0)2411 GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
2412 {
2413 	glUniform1uiv(location, 1, &v0);
2414 }
2415 
glUniform2ui(GLint location,GLuint v0,GLuint v1)2416 GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
2417 {
2418 	GLuint xy[2] = { v0, v1 };
2419 
2420 	glUniform2uiv(location, 1, (GLuint*)&xy);
2421 }
2422 
glUniform3ui(GLint location,GLuint v0,GLuint v1,GLuint v2)2423 GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
2424 {
2425 	GLuint xyz[3] = { v0, v1, v2 };
2426 
2427 	glUniform3uiv(location, 1, (GLuint*)&xyz);
2428 }
2429 
glUniform4ui(GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)2430 GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
2431 {
2432 	GLuint xyzw[4] = { v0, v1, v2, v3 };
2433 
2434 	glUniform4uiv(location, 1, (GLuint*)&xyzw);
2435 }
2436 
glUniform1uiv(GLint location,GLsizei count,const GLuint * value)2437 GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
2438 {
2439 	TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2440 	      location, count, value);
2441 
2442 	if(count < 0)
2443 	{
2444 		return error(GL_INVALID_VALUE);
2445 	}
2446 
2447 	if(location == -1)
2448 	{
2449 		return;
2450 	}
2451 
2452 	es2::Context *context = es2::getContext();
2453 
2454 	if(context)
2455 	{
2456 		es2::Program *program = context->getCurrentProgram();
2457 
2458 		if(!program)
2459 		{
2460 			return error(GL_INVALID_OPERATION);
2461 		}
2462 
2463 		if(!program->setUniform1uiv(location, count, value))
2464 		{
2465 			return error(GL_INVALID_OPERATION);
2466 		}
2467 	}
2468 }
2469 
glUniform2uiv(GLint location,GLsizei count,const GLuint * value)2470 GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
2471 {
2472 	TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2473 	      location, count, value);
2474 
2475 	if(count < 0)
2476 	{
2477 		return error(GL_INVALID_VALUE);
2478 	}
2479 
2480 	if(location == -1)
2481 	{
2482 		return;
2483 	}
2484 
2485 	es2::Context *context = es2::getContext();
2486 
2487 	if(context)
2488 	{
2489 		es2::Program *program = context->getCurrentProgram();
2490 
2491 		if(!program)
2492 		{
2493 			return error(GL_INVALID_OPERATION);
2494 		}
2495 
2496 		if(!program->setUniform2uiv(location, count, value))
2497 		{
2498 			return error(GL_INVALID_OPERATION);
2499 		}
2500 	}
2501 }
2502 
glUniform3uiv(GLint location,GLsizei count,const GLuint * value)2503 GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
2504 {
2505 	TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2506 	      location, count, value);
2507 
2508 	if(count < 0)
2509 	{
2510 		return error(GL_INVALID_VALUE);
2511 	}
2512 
2513 	if(location == -1)
2514 	{
2515 		return;
2516 	}
2517 
2518 	es2::Context *context = es2::getContext();
2519 
2520 	if(context)
2521 	{
2522 		es2::Program *program = context->getCurrentProgram();
2523 
2524 		if(!program)
2525 		{
2526 			return error(GL_INVALID_OPERATION);
2527 		}
2528 
2529 		if(!program->setUniform3uiv(location, count, value))
2530 		{
2531 			return error(GL_INVALID_OPERATION);
2532 		}
2533 	}
2534 }
2535 
glUniform4uiv(GLint location,GLsizei count,const GLuint * value)2536 GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
2537 {
2538 	TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2539 	      location, count, value);
2540 
2541 	if(count < 0)
2542 	{
2543 		return error(GL_INVALID_VALUE);
2544 	}
2545 
2546 	if(location == -1)
2547 	{
2548 		return;
2549 	}
2550 
2551 	es2::Context *context = es2::getContext();
2552 
2553 	if(context)
2554 	{
2555 		es2::Program *program = context->getCurrentProgram();
2556 
2557 		if(!program)
2558 		{
2559 			return error(GL_INVALID_OPERATION);
2560 		}
2561 
2562 		if(!program->setUniform4uiv(location, count, value))
2563 		{
2564 			return error(GL_INVALID_OPERATION);
2565 		}
2566 	}
2567 }
2568 
glClearBufferiv(GLenum buffer,GLint drawbuffer,const GLint * value)2569 GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
2570 {
2571 	TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
2572 	      buffer, drawbuffer, value);
2573 
2574 	es2::Context *context = es2::getContext();
2575 
2576 	if(context)
2577 	{
2578 		switch(buffer)
2579 		{
2580 		case GL_COLOR:
2581 			if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2582 			{
2583 				return error(GL_INVALID_VALUE);
2584 			}
2585 			else
2586 			{
2587 				context->clearColorBuffer(drawbuffer, value);
2588 			}
2589 			break;
2590 		case GL_STENCIL:
2591 			if(drawbuffer != 0)
2592 			{
2593 				return error(GL_INVALID_VALUE);
2594 			}
2595 			else
2596 			{
2597 				context->clearStencilBuffer(value[0]);
2598 			}
2599 			break;
2600 		default:
2601 			return error(GL_INVALID_ENUM);
2602 		}
2603 	}
2604 }
2605 
glClearBufferuiv(GLenum buffer,GLint drawbuffer,const GLuint * value)2606 GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
2607 {
2608 	TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
2609 	      buffer, drawbuffer, value);
2610 
2611 	es2::Context *context = es2::getContext();
2612 
2613 	if(context)
2614 	{
2615 		switch(buffer)
2616 		{
2617 		case GL_COLOR:
2618 			if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2619 			{
2620 				return error(GL_INVALID_VALUE);
2621 			}
2622 			else
2623 			{
2624 				context->clearColorBuffer(drawbuffer, value);
2625 			}
2626 			break;
2627 		default:
2628 			return error(GL_INVALID_ENUM);
2629 		}
2630 	}
2631 }
2632 
glClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat * value)2633 GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
2634 {
2635 	TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
2636 	      buffer, drawbuffer, value);
2637 
2638 	es2::Context *context = es2::getContext();
2639 
2640 	if(context)
2641 	{
2642 		switch(buffer)
2643 		{
2644 		case GL_COLOR:
2645 			if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2646 			{
2647 				return error(GL_INVALID_VALUE);
2648 			}
2649 			else
2650 			{
2651 				context->clearColorBuffer(drawbuffer, value);
2652 			}
2653 			break;
2654 		case GL_DEPTH:
2655 			if(drawbuffer != 0)
2656 			{
2657 				return error(GL_INVALID_VALUE);
2658 			}
2659 			else
2660 			{
2661 				context->clearDepthBuffer(value[0]);
2662 			}
2663 			break;
2664 		default:
2665 			return error(GL_INVALID_ENUM);
2666 		}
2667 	}
2668 }
2669 
glClearBufferfi(GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)2670 GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
2671 {
2672 	TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
2673 	      buffer, drawbuffer, depth, stencil);
2674 
2675 	es2::Context *context = es2::getContext();
2676 
2677 	if(context)
2678 	{
2679 		switch(buffer)
2680 		{
2681 		case GL_DEPTH_STENCIL:
2682 			if(drawbuffer != 0)
2683 			{
2684 				return error(GL_INVALID_VALUE);
2685 			}
2686 			else
2687 			{
2688 				context->clearDepthBuffer(depth);
2689 				context->clearStencilBuffer(stencil);
2690 			}
2691 			break;
2692 		default:
2693 			return error(GL_INVALID_ENUM);
2694 		}
2695 	}
2696 }
2697 
glGetStringi(GLenum name,GLuint index)2698 GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
2699 {
2700 	TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index);
2701 
2702 	es2::Context *context = es2::getContext();
2703 	if(context)
2704 	{
2705 		GLuint numExtensions;
2706 		context->getExtensions(0, &numExtensions);
2707 
2708 		if(index >= numExtensions)
2709 		{
2710 			return error(GL_INVALID_VALUE, (GLubyte*)nullptr);
2711 		}
2712 
2713 		switch(name)
2714 		{
2715 		case GL_EXTENSIONS:
2716 			return context->getExtensions(index);
2717 		default:
2718 			return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
2719 		}
2720 	}
2721 
2722 	return (GLubyte*)nullptr;
2723 }
2724 
glCopyBufferSubData(GLenum readTarget,GLenum writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)2725 GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
2726 {
2727 	TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X,  GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
2728 	      readTarget, writeTarget, readOffset, writeOffset, size);
2729 
2730 	if(readOffset < 0 || writeOffset < 0 || size < 0)
2731 	{
2732 		return error(GL_INVALID_VALUE);
2733 	}
2734 
2735 	es2::Context *context = es2::getContext();
2736 
2737 	if(context)
2738 	{
2739 		es2::Buffer *readBuffer = nullptr, *writeBuffer = nullptr;
2740 		if(!context->getBuffer(readTarget, &readBuffer) || !context->getBuffer(writeTarget, &writeBuffer))
2741 		{
2742 			return error(GL_INVALID_ENUM);
2743 		}
2744 		if(!readBuffer || readBuffer->isMapped() || !writeBuffer || writeBuffer->isMapped())
2745 		{
2746 			return error(GL_INVALID_OPERATION);
2747 		}
2748 		if(readBuffer == writeBuffer)
2749 		{
2750 			// If same buffer, check for overlap
2751 			if(((readOffset >= writeOffset) && (readOffset < (writeOffset + size))) ||
2752 			   ((writeOffset >= readOffset) && (writeOffset < (readOffset + size))))
2753 			{
2754 				return error(GL_INVALID_VALUE);
2755 			}
2756 		}
2757 
2758 		if((static_cast<size_t>(readOffset + size) > readBuffer->size()) ||
2759 		   (static_cast<size_t>(writeOffset + size) > writeBuffer->size()))
2760 		{
2761 			return error(GL_INVALID_VALUE);
2762 		}
2763 
2764 		writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset);
2765 	}
2766 }
2767 
glGetUniformIndices(GLuint program,GLsizei uniformCount,const GLchar * const * uniformNames,GLuint * uniformIndices)2768 GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
2769 {
2770 	TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)",
2771 	      program, uniformCount, uniformNames, uniformIndices);
2772 
2773 	if(uniformCount < 0)
2774 	{
2775 		return error(GL_INVALID_VALUE);
2776 	}
2777 
2778 	es2::Context *context = es2::getContext();
2779 
2780 	if(context)
2781 	{
2782 		es2::Program *programObject = context->getProgram(program);
2783 
2784 		if(!programObject)
2785 		{
2786 			return error(GL_INVALID_OPERATION);
2787 		}
2788 
2789 		if(!programObject->isLinked())
2790 		{
2791 			for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2792 			{
2793 				uniformIndices[uniformId] = GL_INVALID_INDEX;
2794 			}
2795 		}
2796 		else
2797 		{
2798 			for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2799 			{
2800 				uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
2801 			}
2802 		}
2803 	}
2804 }
2805 
glGetActiveUniformsiv(GLuint program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,GLint * params)2806 GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
2807 {
2808 	TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLenum pname = 0x%X, GLuint *uniformIndices = %p)",
2809 	      program, uniformCount, uniformIndices, pname, uniformIndices);
2810 
2811 	switch(pname)
2812 	{
2813 	case GL_UNIFORM_TYPE:
2814 	case GL_UNIFORM_SIZE:
2815 	case GL_UNIFORM_NAME_LENGTH:
2816 	case GL_UNIFORM_BLOCK_INDEX:
2817 	case GL_UNIFORM_OFFSET:
2818 	case GL_UNIFORM_ARRAY_STRIDE:
2819 	case GL_UNIFORM_MATRIX_STRIDE:
2820 	case GL_UNIFORM_IS_ROW_MAJOR:
2821 		break;
2822 	default:
2823 		return error(GL_INVALID_ENUM);
2824 	}
2825 
2826 	if(uniformCount < 0)
2827 	{
2828 		return error(GL_INVALID_VALUE);
2829 	}
2830 
2831 	es2::Context *context = es2::getContext();
2832 
2833 	if(context)
2834 	{
2835 		es2::Program *programObject = context->getProgram(program);
2836 
2837 		if(!programObject)
2838 		{
2839 			return error(GL_INVALID_OPERATION);
2840 		}
2841 
2842 		for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2843 		{
2844 			const GLuint index = uniformIndices[uniformId];
2845 
2846 			if(index >= programObject->getActiveUniformCount())
2847 			{
2848 				return error(GL_INVALID_VALUE);
2849 			}
2850 		}
2851 
2852 		for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2853 		{
2854 			const GLuint index = uniformIndices[uniformId];
2855 			params[uniformId] = programObject->getActiveUniformi(index, pname);
2856 		}
2857 	}
2858 }
2859 
glGetUniformBlockIndex(GLuint program,const GLchar * uniformBlockName)2860 GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
2861 {
2862 	TRACE("(GLuint program = %d, const GLchar *uniformBlockName = %p)",
2863 	      program, uniformBlockName);
2864 
2865 	es2::Context *context = es2::getContext();
2866 
2867 	if(context)
2868 	{
2869 		es2::Program *programObject = context->getProgram(program);
2870 
2871 		if(!programObject)
2872 		{
2873 			return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
2874 		}
2875 
2876 		return programObject->getUniformBlockIndex(uniformBlockName);
2877 	}
2878 
2879 	return GL_INVALID_INDEX;
2880 }
2881 
glGetActiveUniformBlockiv(GLuint program,GLuint uniformBlockIndex,GLenum pname,GLint * params)2882 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
2883 {
2884 	TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)",
2885 	      program, uniformBlockIndex, pname, params);
2886 
2887 	es2::Context *context = es2::getContext();
2888 
2889 	if(context)
2890 	{
2891 		es2::Program *programObject = context->getProgram(program);
2892 
2893 		if(!programObject)
2894 		{
2895 			return error(GL_INVALID_OPERATION);
2896 		}
2897 
2898 		switch(pname)
2899 		{
2900 		case GL_UNIFORM_BLOCK_BINDING:
2901 			*params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
2902 			break;
2903 		case GL_UNIFORM_BLOCK_DATA_SIZE:
2904 		case GL_UNIFORM_BLOCK_NAME_LENGTH:
2905 		case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2906 		case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2907 		case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2908 		case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2909 			programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
2910 			break;
2911 		default:
2912 			return error(GL_INVALID_ENUM);
2913 		}
2914 	}
2915 }
2916 
glGetActiveUniformBlockName(GLuint program,GLuint uniformBlockIndex,GLsizei bufSize,GLsizei * length,GLchar * uniformBlockName)2917 GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
2918 {
2919 	TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLchar *uniformBlockName = %p)",
2920 	      program, uniformBlockIndex, bufSize, length, uniformBlockName);
2921 
2922 	if(bufSize < 0)
2923 	{
2924 		return error(GL_INVALID_VALUE);
2925 	}
2926 
2927 	es2::Context *context = es2::getContext();
2928 
2929 	if(context)
2930 	{
2931 		es2::Program *programObject = context->getProgram(program);
2932 
2933 		if(!programObject)
2934 		{
2935 			return error(GL_INVALID_OPERATION);
2936 		}
2937 
2938 		programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
2939 	}
2940 }
2941 
glUniformBlockBinding(GLuint program,GLuint uniformBlockIndex,GLuint uniformBlockBinding)2942 GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2943 {
2944 	TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",
2945 	      program, uniformBlockIndex, uniformBlockBinding);
2946 
2947 	if(uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS)
2948 	{
2949 		return error(GL_INVALID_VALUE);
2950 	}
2951 
2952 	es2::Context *context = es2::getContext();
2953 
2954 	if(context)
2955 	{
2956 		es2::Program *programObject = context->getProgram(program);
2957 
2958 		if(!programObject)
2959 		{
2960 			return error(GL_INVALID_VALUE);
2961 		}
2962 
2963 		programObject->bindUniformBlock(uniformBlockIndex, uniformBlockIndex);
2964 	}
2965 }
2966 
glDrawArraysInstanced(GLenum mode,GLint first,GLsizei count,GLsizei instanceCount)2967 GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
2968 {
2969 	TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
2970 	      mode, first, count, instanceCount);
2971 
2972 	switch(mode)
2973 	{
2974 	case GL_POINTS:
2975 	case GL_LINES:
2976 	case GL_LINE_LOOP:
2977 	case GL_LINE_STRIP:
2978 	case GL_TRIANGLES:
2979 	case GL_TRIANGLE_FAN:
2980 	case GL_TRIANGLE_STRIP:
2981 		break;
2982 	default:
2983 		return error(GL_INVALID_ENUM);
2984 	}
2985 
2986 	if(count < 0 || instanceCount < 0)
2987 	{
2988 		return error(GL_INVALID_VALUE);
2989 	}
2990 
2991 	es2::Context *context = es2::getContext();
2992 
2993 	if(context)
2994 	{
2995 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
2996 		if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
2997 		{
2998 			return error(GL_INVALID_OPERATION);
2999 		}
3000 
3001 		context->drawArrays(mode, first, count, instanceCount);
3002 	}
3003 }
3004 
glDrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei instanceCount)3005 GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
3006 {
3007 	TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
3008 	      mode, count, type, indices, instanceCount);
3009 
3010 	switch(mode)
3011 	{
3012 	case GL_POINTS:
3013 	case GL_LINES:
3014 	case GL_LINE_LOOP:
3015 	case GL_LINE_STRIP:
3016 	case GL_TRIANGLES:
3017 	case GL_TRIANGLE_FAN:
3018 	case GL_TRIANGLE_STRIP:
3019 		break;
3020 	default:
3021 		return error(GL_INVALID_ENUM);
3022 	}
3023 
3024 	switch(type)
3025 	{
3026 	case GL_UNSIGNED_BYTE:
3027 	case GL_UNSIGNED_SHORT:
3028 	case GL_UNSIGNED_INT:
3029 		break;
3030 	default:
3031 		return error(GL_INVALID_ENUM);
3032 	}
3033 
3034 	if(count < 0 || instanceCount < 0)
3035 	{
3036 		return error(GL_INVALID_VALUE);
3037 	}
3038 
3039 	es2::Context *context = es2::getContext();
3040 
3041 	if(context)
3042 	{
3043 		es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
3044 		if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
3045 		{
3046 			return error(GL_INVALID_OPERATION);
3047 		}
3048 
3049 		context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
3050 	}
3051 }
3052 
glFenceSync(GLenum condition,GLbitfield flags)3053 GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
3054 {
3055 	TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags);
3056 
3057 	switch(condition)
3058 	{
3059 	case GL_SYNC_GPU_COMMANDS_COMPLETE:
3060 		break;
3061 	default:
3062 		return error(GL_INVALID_ENUM, nullptr);
3063 	}
3064 
3065 	if(flags != 0)
3066 	{
3067 		return error(GL_INVALID_VALUE, nullptr);
3068 	}
3069 
3070 	es2::Context *context = es2::getContext();
3071 
3072 	if(context)
3073 	{
3074 		return context->createFenceSync(condition, flags);
3075 	}
3076 
3077 	return nullptr;
3078 }
3079 
glIsSync(GLsync sync)3080 GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync)
3081 {
3082 	TRACE("(GLsync sync = %p)", sync);
3083 
3084 	es2::Context *context = es2::getContext();
3085 
3086 	if(context)
3087 	{
3088 		es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3089 
3090 		if(fenceSyncObject)
3091 		{
3092 			return GL_TRUE;
3093 		}
3094 	}
3095 
3096 	return GL_FALSE;
3097 }
3098 
glDeleteSync(GLsync sync)3099 GL_APICALL void GL_APIENTRY glDeleteSync(GLsync sync)
3100 {
3101 	TRACE("(GLsync sync = %p)", sync);
3102 
3103 	es2::Context *context = es2::getContext();
3104 
3105 	if(context)
3106 	{
3107 		context->deleteFenceSync(sync);
3108 	}
3109 }
3110 
glClientWaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)3111 GL_APICALL GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3112 {
3113 	TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3114 
3115 	if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3116 	{
3117 		error(GL_INVALID_VALUE);
3118 	}
3119 
3120 	es2::Context *context = es2::getContext();
3121 
3122 	if(context)
3123 	{
3124 		es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3125 
3126 		if(fenceSyncObject)
3127 		{
3128 			return fenceSyncObject->clientWait(flags, timeout);
3129 		}
3130 		else
3131 		{
3132 			return error(GL_INVALID_VALUE, GL_FALSE);
3133 		}
3134 	}
3135 
3136 	return GL_FALSE;
3137 }
3138 
glWaitSync(GLsync sync,GLbitfield flags,GLuint64 timeout)3139 GL_APICALL void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3140 {
3141 	TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3142 
3143 	if(flags != 0)
3144 	{
3145 		return error(GL_INVALID_VALUE);
3146 	}
3147 
3148 	if(timeout != GL_TIMEOUT_IGNORED)
3149 	{
3150 		return error(GL_INVALID_VALUE);
3151 	}
3152 
3153 	es2::Context *context = es2::getContext();
3154 
3155 	if(context)
3156 	{
3157 		es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3158 
3159 		if(fenceSyncObject)
3160 		{
3161 			fenceSyncObject->serverWait(flags, timeout);
3162 		}
3163 		else
3164 		{
3165 			return error(GL_INVALID_VALUE);
3166 		}
3167 	}
3168 }
3169 
glGetInteger64v(GLenum pname,GLint64 * data)3170 GL_APICALL void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *data)
3171 {
3172 	TRACE("(GLenum pname = 0x%X, GLint64 *data = %p)", pname, data);
3173 
3174 	es2::Context *context = es2::getContext();
3175 
3176 	if(context)
3177 	{
3178 		if(!(context->getIntegerv(pname, data)))
3179 		{
3180 			GLenum nativeType;
3181 			unsigned int numParams = 0;
3182 			if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3183 				return error(GL_INVALID_ENUM);
3184 
3185 			if(numParams == 0)
3186 				return; // it is known that pname is valid, but there are no parameters to return
3187 
3188 			if(nativeType == GL_BOOL)
3189 			{
3190 				GLboolean *boolParams = nullptr;
3191 				boolParams = new GLboolean[numParams];
3192 
3193 				context->getBooleanv(pname, boolParams);
3194 
3195 				for(unsigned int i = 0; i < numParams; ++i)
3196 				{
3197 					data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3198 				}
3199 
3200 				delete[] boolParams;
3201 			}
3202 			else if(nativeType == GL_FLOAT)
3203 			{
3204 				GLfloat *floatParams = nullptr;
3205 				floatParams = new GLfloat[numParams];
3206 
3207 				context->getFloatv(pname, floatParams);
3208 
3209 				for(unsigned int i = 0; i < numParams; ++i)
3210 				{
3211 					if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3212 					{
3213 						data[i] = (GLint64)(convert_float_int(floatParams[i]));
3214 					}
3215 					else
3216 					{
3217 						data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3218 					}
3219 				}
3220 
3221 				delete[] floatParams;
3222 			}
3223 		}
3224 	}
3225 }
3226 
glGetSynciv(GLsync sync,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)3227 GL_APICALL void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
3228 {
3229 	TRACE("(GLsync sync = %p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = %p, GLint *values = %p)",
3230 	      sync, pname, bufSize, length, values);
3231 
3232 	if(bufSize < 0)
3233 	{
3234 		return error(GL_INVALID_VALUE);
3235 	}
3236 
3237 	UNIMPLEMENTED();
3238 }
3239 
glGetInteger64i_v(GLenum target,GLuint index,GLint64 * data)3240 GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
3241 {
3242 	TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint64 *data = %p)", target, index, data);
3243 
3244 	es2::Context *context = es2::getContext();
3245 
3246 	if(context)
3247 	{
3248 		if(!context->getTransformFeedbackiv(index, target, data) &&
3249 		   !context->getUniformBufferiv(index, target, data) &&
3250 		   !context->getIntegerv(target, data))
3251 		{
3252 			GLenum nativeType;
3253 			unsigned int numParams = 0;
3254 			if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
3255 				return error(GL_INVALID_ENUM);
3256 
3257 			if(numParams == 0)
3258 				return; // it is known that target is valid, but there are no parameters to return
3259 
3260 			if(nativeType == GL_BOOL)
3261 			{
3262 				GLboolean *boolParams = nullptr;
3263 				boolParams = new GLboolean[numParams];
3264 
3265 				context->getBooleanv(target, boolParams);
3266 
3267 				for(unsigned int i = 0; i < numParams; ++i)
3268 				{
3269 					data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3270 				}
3271 
3272 				delete[] boolParams;
3273 			}
3274 			else if(nativeType == GL_FLOAT)
3275 			{
3276 				GLfloat *floatParams = nullptr;
3277 				floatParams = new GLfloat[numParams];
3278 
3279 				context->getFloatv(target, floatParams);
3280 
3281 				for(unsigned int i = 0; i < numParams; ++i)
3282 				{
3283 					if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
3284 					{
3285 						data[i] = (GLint64)(convert_float_int(floatParams[i]));
3286 					}
3287 					else
3288 					{
3289 						data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3290 					}
3291 				}
3292 
3293 				delete[] floatParams;
3294 			}
3295 		}
3296 	}
3297 }
3298 
glGetBufferParameteri64v(GLenum target,GLenum pname,GLint64 * params)3299 GL_APICALL void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
3300 {
3301 	TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = %p)", target, pname, params);
3302 
3303 	es2::Context *context = es2::getContext();
3304 
3305 	if(context)
3306 	{
3307 		es2::Buffer *buffer = nullptr;
3308 
3309 		if(!context->getBuffer(target, &buffer))
3310 		{
3311 			return error(GL_INVALID_ENUM);
3312 		}
3313 
3314 		if(!buffer)
3315 		{
3316 			// A null buffer means that "0" is bound to the requested buffer target
3317 			return error(GL_INVALID_OPERATION);
3318 		}
3319 
3320 		switch(pname)
3321 		{
3322 		case GL_BUFFER_USAGE:
3323 			*params = buffer->usage();
3324 			break;
3325 		case GL_BUFFER_SIZE:
3326 			*params = buffer->size();
3327 			break;
3328 		case GL_BUFFER_ACCESS_FLAGS:
3329 			*params = buffer->access();
3330 			break;
3331 		case GL_BUFFER_MAPPED:
3332 			*params = buffer->isMapped();
3333 			break;
3334 		case GL_BUFFER_MAP_LENGTH:
3335 			*params = buffer->length();
3336 			break;
3337 		case GL_BUFFER_MAP_OFFSET:
3338 			*params = buffer->offset();
3339 			break;
3340 		default:
3341 			return error(GL_INVALID_ENUM);
3342 		}
3343 	}
3344 }
3345 
glGenSamplers(GLsizei count,GLuint * samplers)3346 GL_APICALL void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)
3347 {
3348 	TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3349 
3350 	if(count < 0)
3351 	{
3352 		return error(GL_INVALID_VALUE);
3353 	}
3354 
3355 	es2::Context *context = es2::getContext();
3356 
3357 	if(context)
3358 	{
3359 		for(int i = 0; i < count; i++)
3360 		{
3361 			samplers[i] = context->createSampler();
3362 		}
3363 	}
3364 }
3365 
glDeleteSamplers(GLsizei count,const GLuint * samplers)3366 GL_APICALL void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
3367 {
3368 	TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3369 
3370 	if(count < 0)
3371 	{
3372 		return error(GL_INVALID_VALUE);
3373 	}
3374 
3375 	es2::Context *context = es2::getContext();
3376 
3377 	if(context)
3378 	{
3379 		for(int i = 0; i < count; i++)
3380 		{
3381 			context->deleteSampler(samplers[i]);
3382 		}
3383 	}
3384 }
3385 
glIsSampler(GLuint sampler)3386 GL_APICALL GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
3387 {
3388 	TRACE("(GLuint sampler = %d)", sampler);
3389 
3390 	if(sampler == 0)
3391 	{
3392 		return GL_FALSE;
3393 	}
3394 
3395 	es2::Context *context = es2::getContext();
3396 
3397 	if(context)
3398 	{
3399 		if(context->isSampler(sampler))
3400 		{
3401 			return GL_TRUE;
3402 		}
3403 	}
3404 
3405 	return GL_FALSE;
3406 }
3407 
glBindSampler(GLuint unit,GLuint sampler)3408 GL_APICALL void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
3409 {
3410 	TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler);
3411 
3412 	if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3413 	{
3414 		return error(GL_INVALID_VALUE);
3415 	}
3416 
3417 	es2::Context *context = es2::getContext();
3418 
3419 	if(context)
3420 	{
3421 		if(sampler != 0 && !context->isSampler(sampler))
3422 		{
3423 			return error(GL_INVALID_OPERATION);
3424 		}
3425 
3426 		context->bindSampler(unit, sampler);
3427 	}
3428 }
3429 
glSamplerParameteri(GLuint sampler,GLenum pname,GLint param)3430 GL_APICALL void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
3431 {
3432 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint param = %d)",
3433 	      sampler, pname, param);
3434 
3435 	glSamplerParameteriv(sampler, pname, &param);
3436 }
3437 
glSamplerParameteriv(GLuint sampler,GLenum pname,const GLint * param)3438 GL_APICALL void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
3439 {
3440 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = %p)",
3441 	      sampler, pname, param);
3442 
3443 	if(!ValidateSamplerObjectParameter(pname))
3444 	{
3445 		return error(GL_INVALID_ENUM);
3446 	}
3447 
3448 	if(!ValidateTexParamParameters(pname, *param))
3449 	{
3450 		return;
3451 	}
3452 
3453 	es2::Context *context = es2::getContext();
3454 
3455 	if(context)
3456 	{
3457 		if(!context->isSampler(sampler))
3458 		{
3459 			return error(GL_INVALID_OPERATION);
3460 		}
3461 
3462 		context->samplerParameteri(sampler, pname, *param);
3463 	}
3464 }
3465 
glSamplerParameterf(GLuint sampler,GLenum pname,GLfloat param)3466 GL_APICALL void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
3467 {
3468 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat param = %f)",
3469 	      sampler, pname, param);
3470 
3471 	glSamplerParameterfv(sampler, pname, &param);
3472 }
3473 
glSamplerParameterfv(GLuint sampler,GLenum pname,const GLfloat * param)3474 GL_APICALL void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
3475 {
3476 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = %p)",
3477 	      sampler, pname, param);
3478 
3479 	if(!ValidateSamplerObjectParameter(pname))
3480 	{
3481 		return error(GL_INVALID_ENUM);
3482 	}
3483 
3484 	if(!ValidateTexParamParameters(pname, *param))
3485 	{
3486 		return;
3487 	}
3488 
3489 	es2::Context *context = es2::getContext();
3490 
3491 	if(context)
3492 	{
3493 		if(!context->isSampler(sampler))
3494 		{
3495 			return error(GL_INVALID_OPERATION);
3496 		}
3497 
3498 		context->samplerParameterf(sampler, pname, *param);
3499 	}
3500 }
3501 
glGetSamplerParameteriv(GLuint sampler,GLenum pname,GLint * params)3502 GL_APICALL void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
3503 {
3504 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = %p)",
3505 	      sampler, pname, params);
3506 
3507 	if(!ValidateSamplerObjectParameter(pname))
3508 	{
3509 		return error(GL_INVALID_ENUM);
3510 	}
3511 
3512 	es2::Context *context = es2::getContext();
3513 
3514 	if(context)
3515 	{
3516 		if(!context->isSampler(sampler))
3517 		{
3518 			return error(GL_INVALID_VALUE);
3519 		}
3520 
3521 		*params = context->getSamplerParameteri(sampler, pname);
3522 	}
3523 }
3524 
glGetSamplerParameterfv(GLuint sampler,GLenum pname,GLfloat * params)3525 GL_APICALL void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
3526 {
3527 	TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = %p)",
3528 	      sampler, pname, params);
3529 
3530 	if(!ValidateSamplerObjectParameter(pname))
3531 	{
3532 		return error(GL_INVALID_ENUM);
3533 	}
3534 
3535 	es2::Context *context = es2::getContext();
3536 
3537 	if(context)
3538 	{
3539 		if(!context->isSampler(sampler))
3540 		{
3541 			return error(GL_INVALID_VALUE);
3542 		}
3543 
3544 		*params = context->getSamplerParameterf(sampler, pname);
3545 	}
3546 }
3547 
glVertexAttribDivisor(GLuint index,GLuint divisor)3548 GL_APICALL void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
3549 {
3550 	TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
3551 
3552 	es2::Context *context = es2::getContext();
3553 
3554 	if(context)
3555 	{
3556 		if(index >= es2::MAX_VERTEX_ATTRIBS)
3557 		{
3558 			return error(GL_INVALID_VALUE);
3559 		}
3560 
3561 		context->setVertexAttribDivisor(index, divisor);
3562 	}
3563 }
3564 
glBindTransformFeedback(GLenum target,GLuint id)3565 GL_APICALL void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
3566 {
3567 	TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);
3568 
3569 	if(target != GL_TRANSFORM_FEEDBACK)
3570 	{
3571 		return error(GL_INVALID_ENUM);
3572 	}
3573 
3574 	es2::Context *context = es2::getContext();
3575 
3576 	if(context)
3577 	{
3578 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3579 
3580 		if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused())
3581 		{
3582 			return error(GL_INVALID_OPERATION);
3583 		}
3584 
3585 		context->bindTransformFeedback(id);
3586 	}
3587 }
3588 
glDeleteTransformFeedbacks(GLsizei n,const GLuint * ids)3589 GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
3590 {
3591 	TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3592 
3593 	if(n < 0)
3594 	{
3595 		return error(GL_INVALID_VALUE);
3596 	}
3597 
3598 	es2::Context *context = es2::getContext();
3599 
3600 	if(context)
3601 	{
3602 		for(int i = 0; i < n; i++)
3603 		{
3604 			if(ids[i] != 0)
3605 			{
3606 				context->deleteTransformFeedback(ids[i]);
3607 			}
3608 		}
3609 	}
3610 }
3611 
glGenTransformFeedbacks(GLsizei n,GLuint * ids)3612 GL_APICALL void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
3613 {
3614 	TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3615 
3616 	if(n < 0)
3617 	{
3618 		return error(GL_INVALID_VALUE);
3619 	}
3620 
3621 	es2::Context *context = es2::getContext();
3622 
3623 	if(context)
3624 	{
3625 		for(int i = 0; i < n; i++)
3626 		{
3627 			ids[i] = context->createTransformFeedback();
3628 		}
3629 	}
3630 }
3631 
glIsTransformFeedback(GLuint id)3632 GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
3633 {
3634 	TRACE("(GLuint id = %d)", id);
3635 
3636 	if(id == 0)
3637 	{
3638 		return GL_FALSE;
3639 	}
3640 
3641 	es2::Context *context = es2::getContext();
3642 
3643 	if(context)
3644 	{
3645 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id);
3646 
3647 		if(transformFeedbackObject)
3648 		{
3649 			return GL_TRUE;
3650 		}
3651 	}
3652 
3653 	return GL_FALSE;
3654 }
3655 
glPauseTransformFeedback(void)3656 GL_APICALL void GL_APIENTRY glPauseTransformFeedback(void)
3657 {
3658 	TRACE("()");
3659 
3660 	es2::Context *context = es2::getContext();
3661 
3662 	if(context)
3663 	{
3664 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3665 
3666 		if(transformFeedbackObject)
3667 		{
3668 			if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused())
3669 			{
3670 				return error(GL_INVALID_OPERATION);
3671 			}
3672 			transformFeedbackObject->setPaused(true);
3673 		}
3674 	}
3675 }
3676 
glResumeTransformFeedback(void)3677 GL_APICALL void GL_APIENTRY glResumeTransformFeedback(void)
3678 {
3679 	TRACE("()");
3680 
3681 	es2::Context *context = es2::getContext();
3682 
3683 	if(context)
3684 	{
3685 		es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3686 
3687 		if(transformFeedbackObject)
3688 		{
3689 			if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused())
3690 			{
3691 				return error(GL_INVALID_OPERATION);
3692 			}
3693 			transformFeedbackObject->setPaused(false);
3694 		}
3695 	}
3696 }
3697 
glGetProgramBinary(GLuint program,GLsizei bufSize,GLsizei * length,GLenum * binaryFormat,void * binary)3698 GL_APICALL void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
3699 {
3700 	TRACE("(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLenum *binaryFormat = %p, void *binary = %p)",
3701 	      program, bufSize, length, binaryFormat, binary);
3702 
3703 	if(bufSize < 0)
3704 	{
3705 		return error(GL_INVALID_VALUE);
3706 	}
3707 
3708 	UNIMPLEMENTED();
3709 }
3710 
glProgramBinary(GLuint program,GLenum binaryFormat,const void * binary,GLsizei length)3711 GL_APICALL void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
3712 {
3713 	TRACE("(GLuint program = %d, GLenum binaryFormat = 0x%X, const void *binary = %p, GLsizei length = %d)",
3714 	      program, binaryFormat, binaryFormat, length);
3715 
3716 	if(length < 0)
3717 	{
3718 		return error(GL_INVALID_VALUE);
3719 	}
3720 
3721 	UNIMPLEMENTED();
3722 }
3723 
glProgramParameteri(GLuint program,GLenum pname,GLint value)3724 GL_APICALL void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
3725 {
3726 	TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint value = %d)",
3727 	      program, pname, value);
3728 
3729 	es2::Context *context = es2::getContext();
3730 
3731 	if(context)
3732 	{
3733 		es2::Program *programObject = context->getProgram(program);
3734 
3735 		if(!programObject)
3736 		{
3737 			return error(GL_INVALID_OPERATION);
3738 		}
3739 
3740 		switch(pname)
3741 		{
3742 		case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3743 			programObject->setBinaryRetrievable(value != GL_FALSE);
3744 			break;
3745 		default:
3746 			return error(GL_INVALID_ENUM);
3747 		}
3748 	}
3749 }
3750 
glInvalidateFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments)3751 GL_APICALL void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
3752 {
3753 	TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p)",
3754 	      target, numAttachments, attachments);
3755 
3756 	glInvalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, std::numeric_limits<GLsizei>::max(), std::numeric_limits<GLsizei>::max());
3757 }
3758 
glInvalidateSubFramebuffer(GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)3759 GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
3760 {
3761 	TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
3762 	      target, numAttachments, attachments, x, y, width, height);
3763 
3764 	es2::Context *context = es2::getContext();
3765 
3766 	if(context)
3767 	{
3768 		if(numAttachments < 0 || width < 0 || height < 0)
3769 		{
3770 			return error(GL_INVALID_VALUE);
3771 		}
3772 
3773 		es2::Framebuffer *framebuffer = nullptr;
3774 		switch(target)
3775 		{
3776 		case GL_DRAW_FRAMEBUFFER:
3777 		case GL_FRAMEBUFFER:
3778 			framebuffer = context->getDrawFramebuffer();
3779 		case GL_READ_FRAMEBUFFER:
3780 			framebuffer = context->getReadFramebuffer();
3781 			break;
3782 		default:
3783 			return error(GL_INVALID_ENUM);
3784 		}
3785 
3786 		if(framebuffer)
3787 		{
3788 			for(int i = 0; i < numAttachments; i++)
3789 			{
3790 				switch(attachments[i])
3791 				{
3792 				case GL_COLOR:
3793 				case GL_DEPTH:
3794 				case GL_STENCIL:
3795 					if(!framebuffer->isDefaultFramebuffer())
3796 					{
3797 						return error(GL_INVALID_ENUM);
3798 					}
3799 					break;
3800 				case GL_DEPTH_ATTACHMENT:
3801 				case GL_STENCIL_ATTACHMENT:
3802 				case GL_DEPTH_STENCIL_ATTACHMENT:
3803 					break;
3804 				default:
3805 					if(attachments[i] >= GL_COLOR_ATTACHMENT0 &&
3806 					   attachments[i] <= GL_COLOR_ATTACHMENT31)
3807 					{
3808 						if(attachments[i] - GL_COLOR_ATTACHMENT0 >= MAX_DRAW_BUFFERS)
3809 						{
3810 							return error(GL_INVALID_OPERATION);
3811 						}
3812 					}
3813 					else
3814 					{
3815 						return error(GL_INVALID_ENUM);
3816 					}
3817 					break;
3818 				}
3819 			}
3820 		}
3821 
3822 		// UNIMPLEMENTED();   // It is valid for this function to be treated as a no-op
3823 	}
3824 }
3825 
glTexStorage2D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)3826 GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
3827 {
3828 	TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
3829 	      target, levels, internalformat, width, height);
3830 
3831 	if(width < 1 || height < 1 || levels < 1)
3832 	{
3833 		return error(GL_INVALID_VALUE);
3834 	}
3835 
3836 	if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
3837 	{
3838 		return error(GL_INVALID_OPERATION);
3839 	}
3840 
3841 	GLenum type;
3842 	if(!GetStorageType(internalformat, type))
3843 	{
3844 		return error(GL_INVALID_ENUM);
3845 	}
3846 
3847 	es2::Context *context = es2::getContext();
3848 
3849 	if(context)
3850 	{
3851 		switch(target)
3852 		{
3853 		case GL_TEXTURE_2D:
3854 		{
3855 			es2::Texture2D *texture = context->getTexture2D();
3856 			if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3857 			{
3858 				return error(GL_INVALID_OPERATION);
3859 			}
3860 
3861 			for(int level = 0; level < levels; ++level)
3862 			{
3863 				texture->setImage(level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
3864 				width = std::max(1, (width / 2));
3865 				height = std::max(1, (height / 2));
3866 			}
3867 			texture->makeImmutable(levels);
3868 		}
3869 			break;
3870 		case GL_TEXTURE_CUBE_MAP:
3871 		{
3872 			es2::TextureCubeMap *texture = context->getTextureCubeMap();
3873 			if(!texture || texture->name == 0 || texture->getImmutableFormat())
3874 			{
3875 				return error(GL_INVALID_OPERATION);
3876 			}
3877 
3878 			for(int level = 0; level < levels; ++level)
3879 			{
3880 				for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
3881 				{
3882 					texture->setImage(face, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
3883 				}
3884 				width = std::max(1, (width / 2));
3885 				height = std::max(1, (height / 2));
3886 			}
3887 			texture->makeImmutable(levels);
3888 		}
3889 			break;
3890 		default:
3891 			return error(GL_INVALID_ENUM);
3892 		}
3893 	}
3894 }
3895 
glTexStorage3D(GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)3896 GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
3897 {
3898 	TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d)",
3899 	      target, levels, internalformat, width, height, depth);
3900 
3901 	if(width < 1 || height < 1 || depth < 1 || levels < 1)
3902 	{
3903 		return error(GL_INVALID_VALUE);
3904 	}
3905 
3906 	GLenum type;
3907 	if(!GetStorageType(internalformat, type))
3908 	{
3909 		return error(GL_INVALID_ENUM);
3910 	}
3911 
3912 	es2::Context *context = es2::getContext();
3913 
3914 	if(context)
3915 	{
3916 		switch(target)
3917 		{
3918 		case GL_TEXTURE_3D:
3919 		{
3920 			if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1))
3921 			{
3922 				return error(GL_INVALID_OPERATION);
3923 			}
3924 
3925 			es2::Texture3D *texture = context->getTexture3D();
3926 			if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3927 			{
3928 				return error(GL_INVALID_OPERATION);
3929 			}
3930 
3931 			for(int level = 0; level < levels; ++level)
3932 			{
3933 				texture->setImage(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
3934 				width = std::max(1, (width / 2));
3935 				height = std::max(1, (height / 2));
3936 				depth = std::max(1, (depth / 2));
3937 			}
3938 			texture->makeImmutable(levels);
3939 		}
3940 			break;
3941 		case GL_TEXTURE_2D_ARRAY:
3942 		{
3943 			if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
3944 			{
3945 				return error(GL_INVALID_OPERATION);
3946 			}
3947 
3948 			es2::Texture3D *texture = context->getTexture2DArray();
3949 			if(!texture || texture->name == 0 || texture->getImmutableFormat())
3950 			{
3951 				return error(GL_INVALID_OPERATION);
3952 			}
3953 
3954 			for(int level = 0; level < levels; ++level)
3955 			{
3956 				for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
3957 				{
3958 					texture->setImage(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
3959 				}
3960 				width = std::max(1, (width / 2));
3961 				height = std::max(1, (height / 2));
3962 			}
3963 			texture->makeImmutable(levels);
3964 		}
3965 			break;
3966 		default:
3967 			return error(GL_INVALID_ENUM);
3968 		}
3969 	}
3970 }
3971 
glGetInternalformativ(GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLint * params)3972 GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)
3973 {
3974 	TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLint *params = %p)",
3975 	      target, internalformat, pname, bufSize, params);
3976 
3977 	if(bufSize < 0)
3978 	{
3979 		return error(GL_INVALID_VALUE);
3980 	}
3981 
3982 	if(bufSize == 0)
3983 	{
3984 		return;
3985 	}
3986 
3987 	if(!IsColorRenderable(internalformat, egl::getClientVersion()) && !IsDepthRenderable(internalformat) && !IsStencilRenderable(internalformat))
3988 	{
3989 		return error(GL_INVALID_ENUM);
3990 	}
3991 
3992 	switch(target)
3993 	{
3994 	case GL_RENDERBUFFER:
3995 		break;
3996 	default:
3997 		return error(GL_INVALID_ENUM);
3998 	}
3999 
4000 	// Integer types have no multisampling
4001 	GLint numMultisampleCounts = NUM_MULTISAMPLE_COUNTS;
4002 	switch(internalformat)
4003 	{
4004 	case GL_R8UI:
4005 	case GL_R8I:
4006 	case GL_R16UI:
4007 	case GL_R16I:
4008 	case GL_R32UI:
4009 	case GL_R32I:
4010 	case GL_RG8UI:
4011 	case GL_RG8I:
4012 	case GL_RG16UI:
4013 	case GL_RG16I:
4014 	case GL_RG32UI:
4015 	case GL_RG32I:
4016 	case GL_RGB8UI:
4017 	case GL_RGB8I:
4018 	case GL_RGB16UI:
4019 	case GL_RGB16I:
4020 	case GL_RGB32UI:
4021 	case GL_RGB32I:
4022 	case GL_RGBA8UI:
4023 	case GL_RGBA8I:
4024 	case GL_RGB10_A2UI:
4025 	case GL_RGBA16UI:
4026 	case GL_RGBA16I:
4027 	case GL_RGBA32UI:
4028 	case GL_RGBA32I:
4029 		numMultisampleCounts = 0;
4030 		break;
4031 	default:
4032 		break;
4033 	}
4034 
4035 	switch(pname)
4036 	{
4037 	case GL_NUM_SAMPLE_COUNTS:
4038 		*params = numMultisampleCounts;
4039 		break;
4040 	case GL_SAMPLES:
4041 		for(int i = 0; i < numMultisampleCounts && i < bufSize; i++)
4042 		{
4043 			params[i] = multisampleCount[i];
4044 		}
4045 		break;
4046 	default:
4047 		return error(GL_INVALID_ENUM);
4048 	}
4049 }
4050 
4051 }
4052