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