blob: 541b116a32cf9322c62370ea5adcb8709ee1ecb3 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
15
16#include "main.h"
17#include "mathutil.h"
18#include "utilities.h"
19#include "Buffer.h"
20#include "Context.h"
21#include "Fence.h"
22#include "Framebuffer.h"
23#include "Program.h"
24#include "Renderbuffer.h"
25#include "Shader.h"
26#include "Texture.h"
27#include "Query.h"
28#include "TransformFeedback.h"
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -050029#include "VertexArray.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040030#include "common/debug.h"
31#include "Common/Version.h"
32
33#include <GLES2/gl2.h>
34#include <GLES2/gl2ext.h>
35#include <GLES3/gl3.h>
36
Krzysztof Kosińskif919b862018-01-03 23:17:52 +010037#include <algorithm>
Nicolas Capens0bac2852016-05-07 06:09:58 -040038#include <limits>
39
Nicolas Capens0bac2852016-05-07 06:09:58 -040040namespace es2
41{
42
43static bool validImageSize(GLint level, GLsizei width, GLsizei height)
44{
45 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
46 {
47 return false;
48 }
49
50 return true;
51}
52
Nicolas Capens0bac2852016-05-07 06:09:58 -040053void ActiveTexture(GLenum texture)
54{
55 TRACE("(GLenum texture = 0x%X)", texture);
56
Chris Forbes108f3e12018-08-30 19:41:59 -070057 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040058
59 if(context)
60 {
61 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
62 {
63 return error(GL_INVALID_ENUM);
64 }
65
66 context->setActiveSampler(texture - GL_TEXTURE0);
67 }
68}
69
70void AttachShader(GLuint program, GLuint shader)
71{
72 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
73
Chris Forbes108f3e12018-08-30 19:41:59 -070074 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040075
76 if(context)
77 {
78 es2::Program *programObject = context->getProgram(program);
79 es2::Shader *shaderObject = context->getShader(shader);
80
81 if(!programObject)
82 {
83 if(context->getShader(program))
84 {
85 return error(GL_INVALID_OPERATION);
86 }
87 else
88 {
89 return error(GL_INVALID_VALUE);
90 }
91 }
92
93 if(!shaderObject)
94 {
95 if(context->getProgram(shader))
96 {
97 return error(GL_INVALID_OPERATION);
98 }
99 else
100 {
101 return error(GL_INVALID_VALUE);
102 }
103 }
104
105 if(!programObject->attachShader(shaderObject))
106 {
107 return error(GL_INVALID_OPERATION);
108 }
109 }
110}
111
112void BeginQueryEXT(GLenum target, GLuint name)
113{
114 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
115
116 switch(target)
117 {
118 case GL_ANY_SAMPLES_PASSED_EXT:
119 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
120 break;
121 default:
122 return error(GL_INVALID_ENUM);
123 }
124
125 if(name == 0)
126 {
127 return error(GL_INVALID_OPERATION);
128 }
129
Chris Forbes108f3e12018-08-30 19:41:59 -0700130 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400131
132 if(context)
133 {
134 context->beginQuery(target, name);
135 }
136}
137
138void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
139{
140 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
141
142 if(index >= es2::MAX_VERTEX_ATTRIBS)
143 {
144 return error(GL_INVALID_VALUE);
145 }
146
Chris Forbes108f3e12018-08-30 19:41:59 -0700147 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400148
149 if(context)
150 {
151 es2::Program *programObject = context->getProgram(program);
152
153 if(!programObject)
154 {
155 if(context->getShader(program))
156 {
157 return error(GL_INVALID_OPERATION);
158 }
159 else
160 {
161 return error(GL_INVALID_VALUE);
162 }
163 }
164
165 if(strncmp(name, "gl_", 3) == 0)
166 {
167 return error(GL_INVALID_OPERATION);
168 }
169
170 programObject->bindAttributeLocation(index, name);
171 }
172}
173
174void BindBuffer(GLenum target, GLuint buffer)
175{
176 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
177
Chris Forbes108f3e12018-08-30 19:41:59 -0700178 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400179
180 if(context)
181 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400182 switch(target)
183 {
184 case GL_ARRAY_BUFFER:
185 context->bindArrayBuffer(buffer);
186 return;
187 case GL_ELEMENT_ARRAY_BUFFER:
188 context->bindElementArrayBuffer(buffer);
189 return;
190 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400191 context->bindCopyReadBuffer(buffer);
192 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400193 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400194 context->bindCopyWriteBuffer(buffer);
195 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400196 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400197 context->bindPixelPackBuffer(buffer);
198 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400199 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400200 context->bindPixelUnpackBuffer(buffer);
201 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400202 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400203 context->bindTransformFeedbackBuffer(buffer);
204 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400205 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400206 context->bindGenericUniformBuffer(buffer);
207 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400208 default:
209 return error(GL_INVALID_ENUM);
210 }
211 }
212}
213
214void BindFramebuffer(GLenum target, GLuint framebuffer)
215{
216 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
217
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000218 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400219 {
220 return error(GL_INVALID_ENUM);
221 }
222
Chris Forbes108f3e12018-08-30 19:41:59 -0700223 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400224
225 if(context)
226 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000227 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400228 {
229 context->bindReadFramebuffer(framebuffer);
230 }
231
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000232 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400233 {
234 context->bindDrawFramebuffer(framebuffer);
235 }
236 }
237}
238
239void BindRenderbuffer(GLenum target, GLuint renderbuffer)
240{
241 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
242
243 if(target != GL_RENDERBUFFER)
244 {
245 return error(GL_INVALID_ENUM);
246 }
247
Chris Forbes108f3e12018-08-30 19:41:59 -0700248 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400249
250 if(context)
251 {
252 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
253 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
254 // If renderbuffer is not zero, then the resulting renderbuffer object
255 // is a new state vector, initialized with a zero-sized memory buffer.
256 context->bindRenderbuffer(renderbuffer);
257 }
258}
259
260void BindTexture(GLenum target, GLuint texture)
261{
262 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
263
Chris Forbes108f3e12018-08-30 19:41:59 -0700264 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400265
266 if(context)
267 {
268 es2::Texture *textureObject = context->getTexture(texture);
269
270 if(textureObject && textureObject->getTarget() != target && texture != 0)
271 {
272 return error(GL_INVALID_OPERATION);
273 }
274
Nicolas Capens0bac2852016-05-07 06:09:58 -0400275 switch(target)
276 {
277 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500278 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400279 break;
280 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500281 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400282 break;
283 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500284 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400285 break;
286 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500287 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400288 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500289 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500290 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400291 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500292 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500293 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500294 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 default:
296 return error(GL_INVALID_ENUM);
297 }
298 }
299}
300
301void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
302{
303 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
304 red, green, blue, alpha);
305
Chris Forbes108f3e12018-08-30 19:41:59 -0700306 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400307
308 if(context)
309 {
310 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
311 }
312}
313
314void BlendEquation(GLenum mode)
315{
316 glBlendEquationSeparate(mode, mode);
317}
318
319void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
320{
321 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
322
323 switch(modeRGB)
324 {
325 case GL_FUNC_ADD:
326 case GL_FUNC_SUBTRACT:
327 case GL_FUNC_REVERSE_SUBTRACT:
328 case GL_MIN_EXT:
329 case GL_MAX_EXT:
330 break;
331 default:
332 return error(GL_INVALID_ENUM);
333 }
334
335 switch(modeAlpha)
336 {
337 case GL_FUNC_ADD:
338 case GL_FUNC_SUBTRACT:
339 case GL_FUNC_REVERSE_SUBTRACT:
340 case GL_MIN_EXT:
341 case GL_MAX_EXT:
342 break;
343 default:
344 return error(GL_INVALID_ENUM);
345 }
346
Chris Forbes108f3e12018-08-30 19:41:59 -0700347 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400348
349 if(context)
350 {
351 context->setBlendEquation(modeRGB, modeAlpha);
352 }
353}
354
355void BlendFunc(GLenum sfactor, GLenum dfactor)
356{
357 glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
358}
359
360void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
361{
362 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
363 srcRGB, dstRGB, srcAlpha, dstAlpha);
364
Nicolas Capens0bac2852016-05-07 06:09:58 -0400365 switch(srcRGB)
366 {
367 case GL_ZERO:
368 case GL_ONE:
369 case GL_SRC_COLOR:
370 case GL_ONE_MINUS_SRC_COLOR:
371 case GL_DST_COLOR:
372 case GL_ONE_MINUS_DST_COLOR:
373 case GL_SRC_ALPHA:
374 case GL_ONE_MINUS_SRC_ALPHA:
375 case GL_DST_ALPHA:
376 case GL_ONE_MINUS_DST_ALPHA:
377 case GL_CONSTANT_COLOR:
378 case GL_ONE_MINUS_CONSTANT_COLOR:
379 case GL_CONSTANT_ALPHA:
380 case GL_ONE_MINUS_CONSTANT_ALPHA:
381 case GL_SRC_ALPHA_SATURATE:
382 break;
383 default:
384 return error(GL_INVALID_ENUM);
385 }
386
387 switch(dstRGB)
388 {
389 case GL_ZERO:
390 case GL_ONE:
391 case GL_SRC_COLOR:
392 case GL_ONE_MINUS_SRC_COLOR:
393 case GL_DST_COLOR:
394 case GL_ONE_MINUS_DST_COLOR:
395 case GL_SRC_ALPHA:
396 case GL_ONE_MINUS_SRC_ALPHA:
397 case GL_DST_ALPHA:
398 case GL_ONE_MINUS_DST_ALPHA:
399 case GL_CONSTANT_COLOR:
400 case GL_ONE_MINUS_CONSTANT_COLOR:
401 case GL_CONSTANT_ALPHA:
402 case GL_ONE_MINUS_CONSTANT_ALPHA:
403 break;
404 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400405 break;
406 default:
407 return error(GL_INVALID_ENUM);
408 }
409
410 switch(srcAlpha)
411 {
412 case GL_ZERO:
413 case GL_ONE:
414 case GL_SRC_COLOR:
415 case GL_ONE_MINUS_SRC_COLOR:
416 case GL_DST_COLOR:
417 case GL_ONE_MINUS_DST_COLOR:
418 case GL_SRC_ALPHA:
419 case GL_ONE_MINUS_SRC_ALPHA:
420 case GL_DST_ALPHA:
421 case GL_ONE_MINUS_DST_ALPHA:
422 case GL_CONSTANT_COLOR:
423 case GL_ONE_MINUS_CONSTANT_COLOR:
424 case GL_CONSTANT_ALPHA:
425 case GL_ONE_MINUS_CONSTANT_ALPHA:
426 case GL_SRC_ALPHA_SATURATE:
427 break;
428 default:
429 return error(GL_INVALID_ENUM);
430 }
431
432 switch(dstAlpha)
433 {
434 case GL_ZERO:
435 case GL_ONE:
436 case GL_SRC_COLOR:
437 case GL_ONE_MINUS_SRC_COLOR:
438 case GL_DST_COLOR:
439 case GL_ONE_MINUS_DST_COLOR:
440 case GL_SRC_ALPHA:
441 case GL_ONE_MINUS_SRC_ALPHA:
442 case GL_DST_ALPHA:
443 case GL_ONE_MINUS_DST_ALPHA:
444 case GL_CONSTANT_COLOR:
445 case GL_ONE_MINUS_CONSTANT_COLOR:
446 case GL_CONSTANT_ALPHA:
447 case GL_ONE_MINUS_CONSTANT_ALPHA:
448 break;
449 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400450 break;
451 default:
452 return error(GL_INVALID_ENUM);
453 }
454
Chris Forbes108f3e12018-08-30 19:41:59 -0700455 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400456
457 if(context)
458 {
459 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
460 }
461}
462
463void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
464{
465 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
466
467 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
468 target, size, data, usage);
469
470 if(size < 0)
471 {
472 return error(GL_INVALID_VALUE);
473 }
474
Nicolas Capens0bac2852016-05-07 06:09:58 -0400475 switch(usage)
476 {
477 case GL_STREAM_DRAW:
478 case GL_STATIC_DRAW:
479 case GL_DYNAMIC_DRAW:
480 break;
481 case GL_STREAM_READ:
482 case GL_STREAM_COPY:
483 case GL_STATIC_READ:
484 case GL_STATIC_COPY:
485 case GL_DYNAMIC_READ:
486 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400487 break;
488 default:
489 return error(GL_INVALID_ENUM);
490 }
491
Chris Forbes108f3e12018-08-30 19:41:59 -0700492 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400493
494 if(context)
495 {
496 es2::Buffer *buffer = nullptr;
497 if(!context->getBuffer(target, &buffer))
498 {
499 return error(GL_INVALID_ENUM);
500 }
501
502 if(!buffer)
503 {
504 // A null buffer means that "0" is bound to the requested buffer target
505 return error(GL_INVALID_OPERATION);
506 }
507
508 buffer->bufferData(data, size, usage);
509 }
510}
511
512void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
513{
514 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
515 offset = static_cast<GLint>(offset);
516
517 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
518 target, offset, size, data);
519
520 if(size < 0 || offset < 0)
521 {
522 return error(GL_INVALID_VALUE);
523 }
524
Chris Forbes108f3e12018-08-30 19:41:59 -0700525 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400526
527 if(context)
528 {
529 es2::Buffer *buffer = nullptr;
530 if(!context->getBuffer(target, &buffer))
531 {
532 return error(GL_INVALID_ENUM);
533 }
534
535 if(!buffer)
536 {
537 // A null buffer means that "0" is bound to the requested buffer target
538 return error(GL_INVALID_OPERATION);
539 }
540
Alexis Hetu6e864492017-11-14 15:27:00 -0500541 if(buffer->isMapped())
542 {
543 // It is an invalid operation to update an already mapped buffer
544 return error(GL_INVALID_OPERATION);
545 }
546
Nicolas Capens0bac2852016-05-07 06:09:58 -0400547 if((size_t)size + offset > buffer->size())
548 {
549 return error(GL_INVALID_VALUE);
550 }
551
552 buffer->bufferSubData(data, size, offset);
553 }
554}
555
556GLenum CheckFramebufferStatus(GLenum target)
557{
558 TRACE("(GLenum target = 0x%X)", target);
559
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000560 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400561 {
562 return error(GL_INVALID_ENUM, 0);
563 }
564
Chris Forbes108f3e12018-08-30 19:41:59 -0700565 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400566
567 if(context)
568 {
569 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000570 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400571 {
572 framebuffer = context->getReadFramebuffer();
573 }
574 else
575 {
576 framebuffer = context->getDrawFramebuffer();
577 }
578
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400579 if(!framebuffer)
580 {
581 return GL_FRAMEBUFFER_UNDEFINED_OES;
582 }
583
Nicolas Capens0bac2852016-05-07 06:09:58 -0400584 return framebuffer->completeness();
585 }
586
587 return 0;
588}
589
590void Clear(GLbitfield mask)
591{
592 TRACE("(GLbitfield mask = %X)", mask);
593
594 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
595 {
596 return error(GL_INVALID_VALUE);
597 }
598
Chris Forbes108f3e12018-08-30 19:41:59 -0700599 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400600
601 if(context)
602 {
603 context->clear(mask);
604 }
605}
606
607void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
608{
609 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
610 red, green, blue, alpha);
611
Chris Forbes108f3e12018-08-30 19:41:59 -0700612 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400613
614 if(context)
615 {
616 context->setClearColor(red, green, blue, alpha);
617 }
618}
619
620void ClearDepthf(GLclampf depth)
621{
622 TRACE("(GLclampf depth = %f)", depth);
623
Chris Forbes108f3e12018-08-30 19:41:59 -0700624 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400625
626 if(context)
627 {
628 context->setClearDepth(depth);
629 }
630}
631
632void ClearStencil(GLint s)
633{
634 TRACE("(GLint s = %d)", s);
635
Chris Forbes108f3e12018-08-30 19:41:59 -0700636 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400637
638 if(context)
639 {
640 context->setClearStencil(s);
641 }
642}
643
644void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
645{
646 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
647 red, green, blue, alpha);
648
Chris Forbes108f3e12018-08-30 19:41:59 -0700649 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400650
651 if(context)
652 {
653 context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
654 }
655}
656
657void CompileShader(GLuint shader)
658{
659 TRACE("(GLuint shader = %d)", shader);
660
Chris Forbes108f3e12018-08-30 19:41:59 -0700661 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400662
663 if(context)
664 {
665 es2::Shader *shaderObject = context->getShader(shader);
666
667 if(!shaderObject)
668 {
669 if(context->getProgram(shader))
670 {
671 return error(GL_INVALID_OPERATION);
672 }
673 else
674 {
675 return error(GL_INVALID_VALUE);
676 }
677 }
678
679 shaderObject->compile();
680 }
681}
682
683void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
684 GLint border, GLsizei imageSize, const GLvoid* data)
685{
686 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
687 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
688 target, level, internalformat, width, height, border, imageSize, data);
689
690 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
691 {
692 return error(GL_INVALID_VALUE);
693 }
694
Nicolas Capens83463112018-06-12 23:55:16 -0400695 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400696 {
Nicolas Capens03589982018-02-01 17:28:32 -0500697 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400698 }
699
700 if(border != 0)
701 {
702 return error(GL_INVALID_VALUE);
703 }
704
Chris Forbes108f3e12018-08-30 19:41:59 -0700705 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400706
707 if(context)
708 {
709 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
710 {
711 return error(GL_INVALID_VALUE);
712 }
713
714 switch(target)
715 {
716 case GL_TEXTURE_2D:
717 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
718 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
719 {
720 return error(GL_INVALID_VALUE);
721 }
722 break;
723 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
725 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
726 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
729 if(width != height)
730 {
731 return error(GL_INVALID_VALUE);
732 }
733
734 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
735 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
736 {
737 return error(GL_INVALID_VALUE);
738 }
739 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500740 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400741 default:
742 return error(GL_INVALID_ENUM);
743 }
744
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500745 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400746 {
747 return error(GL_INVALID_VALUE);
748 }
749
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500750 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500751 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500752 {
753 return error(validationError);
754 }
755
Alexis Hetu46768622018-01-16 22:09:28 -0500756 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400757 {
Alexis Hetu46768622018-01-16 22:09:28 -0500758 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400759
760 if(!texture)
761 {
762 return error(GL_INVALID_OPERATION);
763 }
764
765 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
766 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500767 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400768 {
769 es2::TextureCubeMap *texture = context->getTextureCubeMap();
770
771 if(!texture)
772 {
773 return error(GL_INVALID_OPERATION);
774 }
775
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500776 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400777 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500778 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400779 }
780}
781
782void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
783 GLenum format, GLsizei imageSize, const GLvoid* data)
784{
785 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
786 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
787 "GLsizei imageSize = %d, const GLvoid* data = %p)",
788 target, level, xoffset, yoffset, width, height, format, imageSize, data);
789
790 if(!es2::IsTextureTarget(target))
791 {
792 return error(GL_INVALID_ENUM);
793 }
794
795 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
796 {
797 return error(GL_INVALID_VALUE);
798 }
799
800 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
801 {
802 return error(GL_INVALID_VALUE);
803 }
804
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500805 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400806 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500807 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400808 }
809
Chris Forbes108f3e12018-08-30 19:41:59 -0700810 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400811
812 if(context)
813 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400814 if(xoffset % 4 != 0 || yoffset % 4 != 0)
815 {
816 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
817 return error(GL_INVALID_OPERATION);
818 }
819
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500820 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500821 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500822 {
823 return error(validationError);
824 }
825
Alexis Hetu46768622018-01-16 22:09:28 -0500826 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400827 {
Alexis Hetu46768622018-01-16 22:09:28 -0500828 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400829
Nicolas Capens83463112018-06-12 23:55:16 -0400830 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500831 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400832 {
833 return error(validationError);
834 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500835
Nicolas Capenseab70762018-02-06 16:49:36 -0500836 texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400837 }
838 else if(es2::IsCubemapTextureTarget(target))
839 {
840 es2::TextureCubeMap *texture = context->getTextureCubeMap();
841
Nicolas Capens83463112018-06-12 23:55:16 -0400842 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500843 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400844 {
845 return error(validationError);
846 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500847
Nicolas Capenseab70762018-02-06 16:49:36 -0500848 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400849 }
850 else UNREACHABLE(target);
851 }
852}
853
854void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
855{
856 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
857 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
858 target, level, internalformat, x, y, width, height, border);
859
860 if(!validImageSize(level, width, height))
861 {
862 return error(GL_INVALID_VALUE);
863 }
864
865 if(border != 0)
866 {
867 return error(GL_INVALID_VALUE);
868 }
869
Chris Forbes108f3e12018-08-30 19:41:59 -0700870 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400871
872 if(context)
873 {
874 switch(target)
875 {
Alexis Hetu46768622018-01-16 22:09:28 -0500876 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500877 if(level != 0)
878 {
879 return error(GL_INVALID_VALUE);
880 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400881 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500882 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400883 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
884 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
885 {
886 return error(GL_INVALID_VALUE);
887 }
888 break;
889 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
890 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
891 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
892 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
893 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
894 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
895 if(width != height)
896 {
897 return error(GL_INVALID_VALUE);
898 }
899
900 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
901 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
902 {
903 return error(GL_INVALID_VALUE);
904 }
905 break;
906 default:
907 return error(GL_INVALID_ENUM);
908 }
909
910 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
911
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400912 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400913 {
914 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
915 }
916
917 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
918
919 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
920 {
921 return error(GL_INVALID_OPERATION);
922 }
923
924 GLenum colorbufferFormat = source->getFormat();
925
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500926 // Determine the sized internal format.
927 if(gl::IsUnsizedInternalFormat(internalformat))
928 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400929 if(colorbufferFormat == GL_RGB10_A2)
930 {
931 // Not supported with unsized internalformat.
932 // https://www.khronos.org/members/login/bugzilla/show_bug.cgi?id=9807#c56
933 return error(GL_INVALID_OPERATION);
934 }
935
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500936 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
937 {
938 internalformat = colorbufferFormat;
939 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400940 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500941 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400942 // TODO: Convert to the smallest format that fits all components.
943 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
944
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500945 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
946 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400947 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
948 {
949 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
950 }
951 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
952 {
953 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
954 }
955 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
956 {
957 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
958 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400959 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
960 {
961 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
962 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500963 else
964 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400965 printf("internalformat = %x, colorbufferFormat = %X\n", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500966 UNIMPLEMENTED();
967
968 return error(GL_INVALID_OPERATION);
969 }
970 }
971
Nicolas Capens8f215a42018-02-02 13:25:53 -0500972 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400973 {
974 return;
975 }
976
Alexis Hetu46768622018-01-16 22:09:28 -0500977 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400978 {
Alexis Hetu46768622018-01-16 22:09:28 -0500979 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400980
981 if(!texture)
982 {
983 return error(GL_INVALID_OPERATION);
984 }
985
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500986 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400987 }
988 else if(es2::IsCubemapTextureTarget(target))
989 {
990 es2::TextureCubeMap *texture = context->getTextureCubeMap();
991
992 if(!texture)
993 {
994 return error(GL_INVALID_OPERATION);
995 }
996
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500997 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400998 }
999 else UNREACHABLE(target);
1000 }
1001}
1002
1003void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1004{
1005 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1006 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1007 target, level, xoffset, yoffset, x, y, width, height);
1008
1009 if(!es2::IsTextureTarget(target))
1010 {
1011 return error(GL_INVALID_ENUM);
1012 }
1013
1014 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1015 {
1016 return error(GL_INVALID_VALUE);
1017 }
1018
1019 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1020 {
1021 return error(GL_INVALID_VALUE);
1022 }
1023
1024 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1025 {
1026 return error(GL_INVALID_VALUE);
1027 }
1028
Chris Forbes108f3e12018-08-30 19:41:59 -07001029 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001030
1031 if(context)
1032 {
1033 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1034
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001035 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001036 {
1037 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1038 }
1039
1040 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1041
1042 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1043 {
1044 return error(GL_INVALID_OPERATION);
1045 }
1046
1047 es2::Texture *texture = nullptr;
1048
Alexis Hetu46768622018-01-16 22:09:28 -05001049 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001050 {
Alexis Hetu46768622018-01-16 22:09:28 -05001051 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001052 }
1053 else if(es2::IsCubemapTextureTarget(target))
1054 {
1055 texture = context->getTextureCubeMap();
1056 }
1057 else UNREACHABLE(target);
1058
Nicolas Capens83463112018-06-12 23:55:16 -04001059 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001060 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001061 {
1062 return error(validationError);
1063 }
1064
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001065 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001066 }
1067}
1068
1069GLuint CreateProgram(void)
1070{
1071 TRACE("()");
1072
Chris Forbes108f3e12018-08-30 19:41:59 -07001073 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001074
1075 if(context)
1076 {
1077 return context->createProgram();
1078 }
1079
1080 return 0;
1081}
1082
1083GLuint CreateShader(GLenum type)
1084{
1085 TRACE("(GLenum type = 0x%X)", type);
1086
Chris Forbes108f3e12018-08-30 19:41:59 -07001087 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001088
1089 if(context)
1090 {
1091 switch(type)
1092 {
1093 case GL_FRAGMENT_SHADER:
1094 case GL_VERTEX_SHADER:
1095 return context->createShader(type);
1096 default:
1097 return error(GL_INVALID_ENUM, 0);
1098 }
1099 }
1100
1101 return 0;
1102}
1103
1104void CullFace(GLenum mode)
1105{
1106 TRACE("(GLenum mode = 0x%X)", mode);
1107
1108 switch(mode)
1109 {
1110 case GL_FRONT:
1111 case GL_BACK:
1112 case GL_FRONT_AND_BACK:
1113 {
Chris Forbes108f3e12018-08-30 19:41:59 -07001114 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001115
1116 if(context)
1117 {
1118 context->setCullMode(mode);
1119 }
1120 }
1121 break;
1122 default:
1123 return error(GL_INVALID_ENUM);
1124 }
1125}
1126
1127void DeleteBuffers(GLsizei n, const GLuint* buffers)
1128{
1129 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1130
1131 if(n < 0)
1132 {
1133 return error(GL_INVALID_VALUE);
1134 }
1135
Chris Forbes108f3e12018-08-30 19:41:59 -07001136 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001137
1138 if(context)
1139 {
1140 for(int i = 0; i < n; i++)
1141 {
1142 context->deleteBuffer(buffers[i]);
1143 }
1144 }
1145}
1146
1147void DeleteFencesNV(GLsizei n, const GLuint* fences)
1148{
1149 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1150
1151 if(n < 0)
1152 {
1153 return error(GL_INVALID_VALUE);
1154 }
1155
Chris Forbes108f3e12018-08-30 19:41:59 -07001156 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001157
1158 if(context)
1159 {
1160 for(int i = 0; i < n; i++)
1161 {
1162 context->deleteFence(fences[i]);
1163 }
1164 }
1165}
1166
1167void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1168{
1169 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1170
1171 if(n < 0)
1172 {
1173 return error(GL_INVALID_VALUE);
1174 }
1175
Chris Forbes108f3e12018-08-30 19:41:59 -07001176 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001177
1178 if(context)
1179 {
1180 for(int i = 0; i < n; i++)
1181 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001182 if(framebuffers[i] != 0) // Attempts to delete default framebuffer silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001183 {
1184 context->deleteFramebuffer(framebuffers[i]);
1185 }
1186 }
1187 }
1188}
1189
1190void DeleteProgram(GLuint program)
1191{
1192 TRACE("(GLuint program = %d)", program);
1193
1194 if(program == 0)
1195 {
1196 return;
1197 }
1198
Chris Forbes108f3e12018-08-30 19:41:59 -07001199 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001200
1201 if(context)
1202 {
1203 if(!context->getProgram(program))
1204 {
1205 if(context->getShader(program))
1206 {
1207 return error(GL_INVALID_OPERATION);
1208 }
1209 else
1210 {
1211 return error(GL_INVALID_VALUE);
1212 }
1213 }
1214
1215 context->deleteProgram(program);
1216 }
1217}
1218
1219void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1220{
1221 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1222
1223 if(n < 0)
1224 {
1225 return error(GL_INVALID_VALUE);
1226 }
1227
Chris Forbes108f3e12018-08-30 19:41:59 -07001228 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001229
1230 if(context)
1231 {
1232 for(int i = 0; i < n; i++)
1233 {
1234 context->deleteQuery(ids[i]);
1235 }
1236 }
1237}
1238
1239void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1240{
1241 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1242
1243 if(n < 0)
1244 {
1245 return error(GL_INVALID_VALUE);
1246 }
1247
Chris Forbes108f3e12018-08-30 19:41:59 -07001248 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001249
1250 if(context)
1251 {
1252 for(int i = 0; i < n; i++)
1253 {
1254 context->deleteRenderbuffer(renderbuffers[i]);
1255 }
1256 }
1257}
1258
1259void DeleteShader(GLuint shader)
1260{
1261 TRACE("(GLuint shader = %d)", shader);
1262
1263 if(shader == 0)
1264 {
1265 return;
1266 }
1267
Chris Forbes108f3e12018-08-30 19:41:59 -07001268 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001269
1270 if(context)
1271 {
1272 if(!context->getShader(shader))
1273 {
1274 if(context->getProgram(shader))
1275 {
1276 return error(GL_INVALID_OPERATION);
1277 }
1278 else
1279 {
1280 return error(GL_INVALID_VALUE);
1281 }
1282 }
1283
1284 context->deleteShader(shader);
1285 }
1286}
1287
1288void DeleteTextures(GLsizei n, const GLuint* textures)
1289{
1290 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1291
1292 if(n < 0)
1293 {
1294 return error(GL_INVALID_VALUE);
1295 }
1296
Chris Forbes108f3e12018-08-30 19:41:59 -07001297 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001298
1299 if(context)
1300 {
1301 for(int i = 0; i < n; i++)
1302 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001303 if(textures[i] != 0) // Attempts to delete default texture silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001304 {
1305 context->deleteTexture(textures[i]);
1306 }
1307 }
1308 }
1309}
1310
1311void DepthFunc(GLenum func)
1312{
1313 TRACE("(GLenum func = 0x%X)", func);
1314
1315 switch(func)
1316 {
1317 case GL_NEVER:
1318 case GL_ALWAYS:
1319 case GL_LESS:
1320 case GL_LEQUAL:
1321 case GL_EQUAL:
1322 case GL_GREATER:
1323 case GL_GEQUAL:
1324 case GL_NOTEQUAL:
1325 break;
1326 default:
1327 return error(GL_INVALID_ENUM);
1328 }
1329
Chris Forbes108f3e12018-08-30 19:41:59 -07001330 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001331
1332 if(context)
1333 {
1334 context->setDepthFunc(func);
1335 }
1336}
1337
1338void DepthMask(GLboolean flag)
1339{
1340 TRACE("(GLboolean flag = %d)", flag);
1341
Chris Forbes108f3e12018-08-30 19:41:59 -07001342 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001343
1344 if(context)
1345 {
1346 context->setDepthMask(flag != GL_FALSE);
1347 }
1348}
1349
1350void DepthRangef(GLclampf zNear, GLclampf zFar)
1351{
1352 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1353
Chris Forbes108f3e12018-08-30 19:41:59 -07001354 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001355
1356 if(context)
1357 {
1358 context->setDepthRange(zNear, zFar);
1359 }
1360}
1361
1362void DetachShader(GLuint program, GLuint shader)
1363{
1364 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1365
Chris Forbes108f3e12018-08-30 19:41:59 -07001366 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001367
1368 if(context)
1369 {
1370
1371 es2::Program *programObject = context->getProgram(program);
1372 es2::Shader *shaderObject = context->getShader(shader);
1373
1374 if(!programObject)
1375 {
1376 es2::Shader *shaderByProgramHandle;
1377 shaderByProgramHandle = context->getShader(program);
1378 if(!shaderByProgramHandle)
1379 {
1380 return error(GL_INVALID_VALUE);
1381 }
1382 else
1383 {
1384 return error(GL_INVALID_OPERATION);
1385 }
1386 }
1387
1388 if(!shaderObject)
1389 {
1390 es2::Program *programByShaderHandle = context->getProgram(shader);
1391 if(!programByShaderHandle)
1392 {
1393 return error(GL_INVALID_VALUE);
1394 }
1395 else
1396 {
1397 return error(GL_INVALID_OPERATION);
1398 }
1399 }
1400
1401 if(!programObject->detachShader(shaderObject))
1402 {
1403 return error(GL_INVALID_OPERATION);
1404 }
1405 }
1406}
1407
1408void Disable(GLenum cap)
1409{
1410 TRACE("(GLenum cap = 0x%X)", cap);
1411
Chris Forbes108f3e12018-08-30 19:41:59 -07001412 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001413
1414 if(context)
1415 {
1416 switch(cap)
1417 {
1418 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1419 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1420 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1421 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1422 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1423 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1424 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1425 case GL_BLEND: context->setBlendEnabled(false); break;
1426 case GL_DITHER: context->setDitherEnabled(false); break;
1427 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1428 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1429 default:
1430 return error(GL_INVALID_ENUM);
1431 }
1432 }
1433}
1434
1435void DisableVertexAttribArray(GLuint index)
1436{
1437 TRACE("(GLuint index = %d)", index);
1438
1439 if(index >= es2::MAX_VERTEX_ATTRIBS)
1440 {
1441 return error(GL_INVALID_VALUE);
1442 }
1443
Chris Forbes108f3e12018-08-30 19:41:59 -07001444 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001445
1446 if(context)
1447 {
1448 context->setVertexAttribArrayEnabled(index, false);
1449 }
1450}
1451
1452void DrawArrays(GLenum mode, GLint first, GLsizei count)
1453{
1454 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1455
1456 switch(mode)
1457 {
1458 case GL_POINTS:
1459 case GL_LINES:
1460 case GL_LINE_LOOP:
1461 case GL_LINE_STRIP:
1462 case GL_TRIANGLES:
1463 case GL_TRIANGLE_FAN:
1464 case GL_TRIANGLE_STRIP:
1465 break;
1466 default:
1467 return error(GL_INVALID_ENUM);
1468 }
1469
1470 if(count < 0 || first < 0)
1471 {
1472 return error(GL_INVALID_VALUE);
1473 }
1474
Chris Forbes108f3e12018-08-30 19:41:59 -07001475 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001476
1477 if(context)
1478 {
1479 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1480 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1481 {
1482 return error(GL_INVALID_OPERATION);
1483 }
1484
1485 context->drawArrays(mode, first, count);
1486 }
1487}
1488
1489void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1490{
1491 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1492 mode, count, type, indices);
1493
1494 switch(mode)
1495 {
1496 case GL_POINTS:
1497 case GL_LINES:
1498 case GL_LINE_LOOP:
1499 case GL_LINE_STRIP:
1500 case GL_TRIANGLES:
1501 case GL_TRIANGLE_FAN:
1502 case GL_TRIANGLE_STRIP:
1503 break;
1504 default:
1505 return error(GL_INVALID_ENUM);
1506 }
1507
1508 if(count < 0)
1509 {
1510 return error(GL_INVALID_VALUE);
1511 }
1512
Chris Forbes108f3e12018-08-30 19:41:59 -07001513 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001514
1515 if(context)
1516 {
1517 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1518 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1519 {
1520 return error(GL_INVALID_OPERATION);
1521 }
1522
1523 switch(type)
1524 {
1525 case GL_UNSIGNED_BYTE:
1526 case GL_UNSIGNED_SHORT:
1527 case GL_UNSIGNED_INT:
1528 break;
1529 default:
1530 return error(GL_INVALID_ENUM);
1531 }
1532
1533 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1534 }
1535}
1536
1537void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1538{
1539 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1540 mode, first, count, instanceCount);
1541
1542 switch(mode)
1543 {
1544 case GL_POINTS:
1545 case GL_LINES:
1546 case GL_LINE_LOOP:
1547 case GL_LINE_STRIP:
1548 case GL_TRIANGLES:
1549 case GL_TRIANGLE_FAN:
1550 case GL_TRIANGLE_STRIP:
1551 break;
1552 default:
1553 return error(GL_INVALID_ENUM);
1554 }
1555
1556 if(count < 0 || instanceCount < 0)
1557 {
1558 return error(GL_INVALID_VALUE);
1559 }
1560
Chris Forbes108f3e12018-08-30 19:41:59 -07001561 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001562
1563 if(context)
1564 {
1565 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1566 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1567 {
1568 return error(GL_INVALID_OPERATION);
1569 }
1570
1571 context->drawArrays(mode, first, count, instanceCount);
1572 }
1573}
1574
1575void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1576{
1577 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1578 mode, count, type, indices, instanceCount);
1579
1580 switch(mode)
1581 {
1582 case GL_POINTS:
1583 case GL_LINES:
1584 case GL_LINE_LOOP:
1585 case GL_LINE_STRIP:
1586 case GL_TRIANGLES:
1587 case GL_TRIANGLE_FAN:
1588 case GL_TRIANGLE_STRIP:
1589 break;
1590 default:
1591 return error(GL_INVALID_ENUM);
1592 }
1593
1594 switch(type)
1595 {
1596 case GL_UNSIGNED_BYTE:
1597 case GL_UNSIGNED_SHORT:
1598 case GL_UNSIGNED_INT:
1599 break;
1600 default:
1601 return error(GL_INVALID_ENUM);
1602 }
1603
1604 if(count < 0 || instanceCount < 0)
1605 {
1606 return error(GL_INVALID_VALUE);
1607 }
1608
Chris Forbes108f3e12018-08-30 19:41:59 -07001609 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001610
1611 if(context)
1612 {
1613 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1614 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1615 {
1616 return error(GL_INVALID_OPERATION);
1617 }
1618
1619 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1620 }
1621}
1622
1623void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1624{
1625 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1626
Chris Forbes108f3e12018-08-30 19:41:59 -07001627 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001628
1629 if(context)
1630 {
1631 if(index >= es2::MAX_VERTEX_ATTRIBS)
1632 {
1633 return error(GL_INVALID_VALUE);
1634 }
1635
1636 context->setVertexAttribDivisor(index, divisor);
1637 }
1638}
1639
1640void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1641{
1642 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1643 mode, first, count, instanceCount);
1644
1645 switch(mode)
1646 {
1647 case GL_POINTS:
1648 case GL_LINES:
1649 case GL_LINE_LOOP:
1650 case GL_LINE_STRIP:
1651 case GL_TRIANGLES:
1652 case GL_TRIANGLE_FAN:
1653 case GL_TRIANGLE_STRIP:
1654 break;
1655 default:
1656 return error(GL_INVALID_ENUM);
1657 }
1658
1659 if(count < 0 || instanceCount < 0)
1660 {
1661 return error(GL_INVALID_VALUE);
1662 }
1663
Chris Forbes108f3e12018-08-30 19:41:59 -07001664 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001665
1666 if(context)
1667 {
1668 if(!context->hasZeroDivisor())
1669 {
1670 return error(GL_INVALID_OPERATION);
1671 }
1672
1673 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1674 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1675 {
1676 return error(GL_INVALID_OPERATION);
1677 }
1678
1679 context->drawArrays(mode, first, count, instanceCount);
1680 }
1681}
1682
1683void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1684{
1685 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1686 mode, count, type, indices, instanceCount);
1687
1688 switch(mode)
1689 {
1690 case GL_POINTS:
1691 case GL_LINES:
1692 case GL_LINE_LOOP:
1693 case GL_LINE_STRIP:
1694 case GL_TRIANGLES:
1695 case GL_TRIANGLE_FAN:
1696 case GL_TRIANGLE_STRIP:
1697 break;
1698 default:
1699 return error(GL_INVALID_ENUM);
1700 }
1701
1702 switch(type)
1703 {
1704 case GL_UNSIGNED_BYTE:
1705 case GL_UNSIGNED_SHORT:
1706 case GL_UNSIGNED_INT:
1707 break;
1708 default:
1709 return error(GL_INVALID_ENUM);
1710 }
1711
1712 if(count < 0 || instanceCount < 0)
1713 {
1714 return error(GL_INVALID_VALUE);
1715 }
1716
Chris Forbes108f3e12018-08-30 19:41:59 -07001717 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001718
1719 if(context)
1720 {
1721 if(!context->hasZeroDivisor())
1722 {
1723 return error(GL_INVALID_OPERATION);
1724 }
1725
1726 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1727 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1728 {
1729 return error(GL_INVALID_OPERATION);
1730 }
1731
1732 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1733 }
1734}
1735
1736void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1737{
1738 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1739
Chris Forbes108f3e12018-08-30 19:41:59 -07001740 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001741
1742 if(context)
1743 {
1744 if(index >= MAX_VERTEX_ATTRIBS)
1745 {
1746 return error(GL_INVALID_VALUE);
1747 }
1748
1749 context->setVertexAttribDivisor(index, divisor);
1750 }
1751}
1752
1753void Enable(GLenum cap)
1754{
1755 TRACE("(GLenum cap = 0x%X)", cap);
1756
Chris Forbes108f3e12018-08-30 19:41:59 -07001757 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001758
1759 if(context)
1760 {
1761 switch(cap)
1762 {
1763 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1764 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1765 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1766 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1767 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1768 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1769 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1770 case GL_BLEND: context->setBlendEnabled(true); break;
1771 case GL_DITHER: context->setDitherEnabled(true); break;
1772 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1773 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1774 default:
1775 return error(GL_INVALID_ENUM);
1776 }
1777 }
1778}
1779
1780void EnableVertexAttribArray(GLuint index)
1781{
1782 TRACE("(GLuint index = %d)", index);
1783
1784 if(index >= es2::MAX_VERTEX_ATTRIBS)
1785 {
1786 return error(GL_INVALID_VALUE);
1787 }
1788
Chris Forbes108f3e12018-08-30 19:41:59 -07001789 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001790
1791 if(context)
1792 {
1793 context->setVertexAttribArrayEnabled(index, true);
1794 }
1795}
1796
1797void EndQueryEXT(GLenum target)
1798{
1799 TRACE("GLenum target = 0x%X)", target);
1800
1801 switch(target)
1802 {
1803 case GL_ANY_SAMPLES_PASSED_EXT:
1804 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1805 break;
1806 default:
1807 return error(GL_INVALID_ENUM);
1808 }
1809
Chris Forbes108f3e12018-08-30 19:41:59 -07001810 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001811
1812 if(context)
1813 {
1814 context->endQuery(target);
1815 }
1816}
1817
1818void FinishFenceNV(GLuint fence)
1819{
1820 TRACE("(GLuint fence = %d)", fence);
1821
Chris Forbes108f3e12018-08-30 19:41:59 -07001822 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001823
1824 if(context)
1825 {
1826 es2::Fence *fenceObject = context->getFence(fence);
1827
1828 if(!fenceObject)
1829 {
1830 return error(GL_INVALID_OPERATION);
1831 }
1832
1833 fenceObject->finishFence();
1834 }
1835}
1836
1837void Finish(void)
1838{
1839 TRACE("()");
1840
Chris Forbes108f3e12018-08-30 19:41:59 -07001841 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001842
1843 if(context)
1844 {
1845 context->finish();
1846 }
1847}
1848
1849void Flush(void)
1850{
1851 TRACE("()");
1852
Chris Forbes108f3e12018-08-30 19:41:59 -07001853 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001854
1855 if(context)
1856 {
1857 context->flush();
1858 }
1859}
1860
1861void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1862{
1863 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1864 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1865
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001866 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001867 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1868 {
1869 return error(GL_INVALID_ENUM);
1870 }
1871
Chris Forbes108f3e12018-08-30 19:41:59 -07001872 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001873
1874 if(context)
1875 {
1876 es2::Framebuffer *framebuffer = nullptr;
1877 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001878 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001879 {
1880 framebuffer = context->getReadFramebuffer();
1881 framebufferName = context->getReadFramebufferName();
1882 }
1883 else
1884 {
1885 framebuffer = context->getDrawFramebuffer();
1886 framebufferName = context->getDrawFramebufferName();
1887 }
1888
1889 if(!framebuffer || framebufferName == 0)
1890 {
1891 return error(GL_INVALID_OPERATION);
1892 }
1893
1894 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1895 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1896 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1897 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1898 if(renderbuffer != 0)
1899 {
1900 if(!context->getRenderbuffer(renderbuffer))
1901 {
1902 return error(GL_INVALID_OPERATION);
1903 }
1904 }
1905
Nicolas Capens0bac2852016-05-07 06:09:58 -04001906 switch(attachment)
1907 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001908 case GL_DEPTH_ATTACHMENT:
1909 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1910 break;
1911 case GL_STENCIL_ATTACHMENT:
1912 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1913 break;
1914 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001915 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1916 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1917 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001918 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001919 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1920 {
1921 return error(GL_INVALID_ENUM);
1922 }
1923 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1924 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001925 }
1926 }
1927}
1928
1929void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1930{
1931 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1932 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1933
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001934 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001935 {
1936 return error(GL_INVALID_ENUM);
1937 }
1938
Chris Forbes108f3e12018-08-30 19:41:59 -07001939 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001940
1941 if(context)
1942 {
1943 if(texture == 0)
1944 {
1945 textarget = GL_NONE;
1946 }
1947 else
1948 {
1949 es2::Texture *tex = context->getTexture(texture);
1950
1951 if(!tex)
1952 {
1953 return error(GL_INVALID_OPERATION);
1954 }
1955
1956 switch(textarget)
1957 {
1958 case GL_TEXTURE_2D:
1959 if(tex->getTarget() != GL_TEXTURE_2D)
1960 {
1961 return error(GL_INVALID_OPERATION);
1962 }
1963 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001964 case GL_TEXTURE_RECTANGLE_ARB:
1965 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1966 {
1967 return error(GL_INVALID_OPERATION);
1968 }
1969 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001970 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1971 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1972 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1973 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1974 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1975 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1976 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1977 {
1978 return error(GL_INVALID_OPERATION);
1979 }
1980 break;
1981 default:
1982 return error(GL_INVALID_ENUM);
1983 }
1984
Nicolas Capens83463112018-06-12 23:55:16 -04001985 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001986 {
1987 return error(GL_INVALID_VALUE);
1988 }
1989
1990 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1991 {
1992 return error(GL_INVALID_VALUE);
1993 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001994
1995 if(tex->isCompressed(textarget, level))
1996 {
1997 return error(GL_INVALID_OPERATION);
1998 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001999 }
2000
2001 es2::Framebuffer *framebuffer = nullptr;
2002 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002003 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002004 {
2005 framebuffer = context->getReadFramebuffer();
2006 framebufferName = context->getReadFramebufferName();
2007 }
2008 else
2009 {
2010 framebuffer = context->getDrawFramebuffer();
2011 framebufferName = context->getDrawFramebufferName();
2012 }
2013
2014 if(framebufferName == 0 || !framebuffer)
2015 {
2016 return error(GL_INVALID_OPERATION);
2017 }
2018
2019 switch(attachment)
2020 {
Nicolas Capens83463112018-06-12 23:55:16 -04002021 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2022 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2023 case GL_DEPTH_STENCIL_ATTACHMENT:
2024 framebuffer->setDepthbuffer(textarget, texture, level);
2025 framebuffer->setStencilbuffer(textarget, texture, level);
2026 break;
2027 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002028 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2029 {
2030 return error(GL_INVALID_ENUM);
2031 }
2032 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2033 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002034 }
2035 }
2036}
2037
2038void FrontFace(GLenum mode)
2039{
2040 TRACE("(GLenum mode = 0x%X)", mode);
2041
2042 switch(mode)
2043 {
2044 case GL_CW:
2045 case GL_CCW:
2046 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002047 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002048
2049 if(context)
2050 {
2051 context->setFrontFace(mode);
2052 }
2053 }
2054 break;
2055 default:
2056 return error(GL_INVALID_ENUM);
2057 }
2058}
2059
2060void GenBuffers(GLsizei n, GLuint* buffers)
2061{
2062 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2063
2064 if(n < 0)
2065 {
2066 return error(GL_INVALID_VALUE);
2067 }
2068
Chris Forbes108f3e12018-08-30 19:41:59 -07002069 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002070
2071 if(context)
2072 {
2073 for(int i = 0; i < n; i++)
2074 {
2075 buffers[i] = context->createBuffer();
2076 }
2077 }
2078}
2079
2080void GenerateMipmap(GLenum target)
2081{
2082 TRACE("(GLenum target = 0x%X)", target);
2083
Chris Forbes108f3e12018-08-30 19:41:59 -07002084 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002085
2086 if(context)
2087 {
2088 es2::Texture *texture = nullptr;
2089
Nicolas Capens0bac2852016-05-07 06:09:58 -04002090 switch(target)
2091 {
2092 case GL_TEXTURE_2D:
2093 texture = context->getTexture2D();
2094 break;
2095 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002096 {
2097 TextureCubeMap *cube = context->getTextureCubeMap();
2098 texture = cube;
2099
2100 if(!cube->isCubeComplete())
2101 {
2102 return error(GL_INVALID_OPERATION);
2103 }
2104 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002105 break;
2106 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002107 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002108 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002109 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002110 texture = context->getTexture3D();
2111 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002112 case GL_TEXTURE_RECTANGLE_ARB:
2113 texture = context->getTexture2DRect();
2114 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002115 default:
2116 return error(GL_INVALID_ENUM);
2117 }
2118
Nicolas Capens83463112018-06-12 23:55:16 -04002119 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002120 {
2121 return error(GL_INVALID_OPERATION);
2122 }
2123
Nicolas Capens0bac2852016-05-07 06:09:58 -04002124 texture->generateMipmaps();
2125 }
2126}
2127
2128void GenFencesNV(GLsizei n, GLuint* fences)
2129{
2130 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2131
2132 if(n < 0)
2133 {
2134 return error(GL_INVALID_VALUE);
2135 }
2136
Chris Forbes108f3e12018-08-30 19:41:59 -07002137 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002138
2139 if(context)
2140 {
2141 for(int i = 0; i < n; i++)
2142 {
2143 fences[i] = context->createFence();
2144 }
2145 }
2146}
2147
2148void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2149{
2150 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2151
2152 if(n < 0)
2153 {
2154 return error(GL_INVALID_VALUE);
2155 }
2156
Chris Forbes108f3e12018-08-30 19:41:59 -07002157 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002158
2159 if(context)
2160 {
2161 for(int i = 0; i < n; i++)
2162 {
2163 framebuffers[i] = context->createFramebuffer();
2164 }
2165 }
2166}
2167
2168void GenQueriesEXT(GLsizei n, GLuint* ids)
2169{
2170 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2171
2172 if(n < 0)
2173 {
2174 return error(GL_INVALID_VALUE);
2175 }
2176
Chris Forbes108f3e12018-08-30 19:41:59 -07002177 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002178
2179 if(context)
2180 {
2181 for(int i = 0; i < n; i++)
2182 {
2183 ids[i] = context->createQuery();
2184 }
2185 }
2186}
2187
2188void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2189{
2190 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2191
2192 if(n < 0)
2193 {
2194 return error(GL_INVALID_VALUE);
2195 }
2196
Chris Forbes108f3e12018-08-30 19:41:59 -07002197 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002198
2199 if(context)
2200 {
2201 for(int i = 0; i < n; i++)
2202 {
2203 renderbuffers[i] = context->createRenderbuffer();
2204 }
2205 }
2206}
2207
2208void GenTextures(GLsizei n, GLuint* textures)
2209{
2210 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2211
2212 if(n < 0)
2213 {
2214 return error(GL_INVALID_VALUE);
2215 }
2216
Chris Forbes108f3e12018-08-30 19:41:59 -07002217 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002218
2219 if(context)
2220 {
2221 for(int i = 0; i < n; i++)
2222 {
2223 textures[i] = context->createTexture();
2224 }
2225 }
2226}
2227
2228void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2229{
2230 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2231 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2232 program, index, bufsize, length, size, type, name);
2233
2234 if(bufsize < 0)
2235 {
2236 return error(GL_INVALID_VALUE);
2237 }
2238
Chris Forbes108f3e12018-08-30 19:41:59 -07002239 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002240
2241 if(context)
2242 {
2243 es2::Program *programObject = context->getProgram(program);
2244
2245 if(!programObject)
2246 {
2247 if(context->getShader(program))
2248 {
2249 return error(GL_INVALID_OPERATION);
2250 }
2251 else
2252 {
2253 return error(GL_INVALID_VALUE);
2254 }
2255 }
2256
2257 if(index >= programObject->getActiveAttributeCount())
2258 {
2259 return error(GL_INVALID_VALUE);
2260 }
2261
2262 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2263 }
2264}
2265
2266void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2267{
2268 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2269 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2270 program, index, bufsize, length, size, type, name);
2271
2272 if(bufsize < 0)
2273 {
2274 return error(GL_INVALID_VALUE);
2275 }
2276
Chris Forbes108f3e12018-08-30 19:41:59 -07002277 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002278
2279 if(context)
2280 {
2281 es2::Program *programObject = context->getProgram(program);
2282
2283 if(!programObject)
2284 {
2285 if(context->getShader(program))
2286 {
2287 return error(GL_INVALID_OPERATION);
2288 }
2289 else
2290 {
2291 return error(GL_INVALID_VALUE);
2292 }
2293 }
2294
2295 if(index >= programObject->getActiveUniformCount())
2296 {
2297 return error(GL_INVALID_VALUE);
2298 }
2299
2300 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2301 }
2302}
2303
2304void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2305{
2306 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2307 program, maxcount, count, shaders);
2308
2309 if(maxcount < 0)
2310 {
2311 return error(GL_INVALID_VALUE);
2312 }
2313
Chris Forbes108f3e12018-08-30 19:41:59 -07002314 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002315
2316 if(context)
2317 {
2318 es2::Program *programObject = context->getProgram(program);
2319
2320 if(!programObject)
2321 {
2322 if(context->getShader(program))
2323 {
2324 return error(GL_INVALID_OPERATION);
2325 }
2326 else
2327 {
2328 return error(GL_INVALID_VALUE);
2329 }
2330 }
2331
2332 return programObject->getAttachedShaders(maxcount, count, shaders);
2333 }
2334}
2335
2336int GetAttribLocation(GLuint program, const GLchar* name)
2337{
2338 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2339
Chris Forbes108f3e12018-08-30 19:41:59 -07002340 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002341
2342 if(context)
2343 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002344 es2::Program *programObject = context->getProgram(program);
2345
2346 if(!programObject)
2347 {
2348 if(context->getShader(program))
2349 {
2350 return error(GL_INVALID_OPERATION, -1);
2351 }
2352 else
2353 {
2354 return error(GL_INVALID_VALUE, -1);
2355 }
2356 }
2357
2358 if(!programObject->isLinked())
2359 {
2360 return error(GL_INVALID_OPERATION, -1);
2361 }
2362
2363 return programObject->getAttributeLocation(name);
2364 }
2365
2366 return -1;
2367}
2368
2369void GetBooleanv(GLenum pname, GLboolean* params)
2370{
2371 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2372
Chris Forbes108f3e12018-08-30 19:41:59 -07002373 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002374
2375 if(context)
2376 {
2377 if(!(context->getBooleanv(pname, params)))
2378 {
2379 GLenum nativeType;
2380 unsigned int numParams = 0;
2381 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2382 return error(GL_INVALID_ENUM);
2383
2384 if(numParams == 0)
2385 return; // it is known that the pname is valid, but there are no parameters to return
2386
2387 if(nativeType == GL_FLOAT)
2388 {
2389 GLfloat *floatParams = nullptr;
2390 floatParams = new GLfloat[numParams];
2391
2392 context->getFloatv(pname, floatParams);
2393
2394 for(unsigned int i = 0; i < numParams; ++i)
2395 {
2396 if(floatParams[i] == 0.0f)
2397 params[i] = GL_FALSE;
2398 else
2399 params[i] = GL_TRUE;
2400 }
2401
2402 delete [] floatParams;
2403 }
2404 else if(nativeType == GL_INT)
2405 {
2406 GLint *intParams = nullptr;
2407 intParams = new GLint[numParams];
2408
2409 context->getIntegerv(pname, intParams);
2410
2411 for(unsigned int i = 0; i < numParams; ++i)
2412 {
2413 if(intParams[i] == 0)
2414 params[i] = GL_FALSE;
2415 else
2416 params[i] = GL_TRUE;
2417 }
2418
2419 delete [] intParams;
2420 }
2421 }
2422 }
2423}
2424
2425void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2426{
2427 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2428
Chris Forbes108f3e12018-08-30 19:41:59 -07002429 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002430
2431 if(context)
2432 {
2433 es2::Buffer *buffer;
2434 if(!context->getBuffer(target, &buffer))
2435 {
2436 return error(GL_INVALID_ENUM);
2437 }
2438
2439 if(!buffer)
2440 {
2441 // A null buffer means that "0" is bound to the requested buffer target
2442 return error(GL_INVALID_OPERATION);
2443 }
2444
Nicolas Capens0bac2852016-05-07 06:09:58 -04002445 switch(pname)
2446 {
2447 case GL_BUFFER_USAGE:
2448 *params = buffer->usage();
2449 break;
2450 case GL_BUFFER_SIZE:
2451 *params = (GLint)buffer->size();
2452 break;
2453 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002454 *params = buffer->access();
2455 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002456 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002457 *params = buffer->isMapped();
2458 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002459 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002460 *params = (GLint)buffer->length();
2461 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002462 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002463 *params = (GLint)buffer->offset();
2464 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002465 default:
2466 return error(GL_INVALID_ENUM);
2467 }
2468 }
2469}
2470
2471GLenum GetError(void)
2472{
2473 TRACE("()");
2474
Chris Forbes108f3e12018-08-30 19:41:59 -07002475 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002476
2477 if(context)
2478 {
2479 return context->getError();
2480 }
2481
2482 return GL_NO_ERROR;
2483}
2484
2485void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2486{
2487 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2488
Chris Forbes108f3e12018-08-30 19:41:59 -07002489 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002490
2491 if(context)
2492 {
2493 es2::Fence *fenceObject = context->getFence(fence);
2494
2495 if(!fenceObject)
2496 {
2497 return error(GL_INVALID_OPERATION);
2498 }
2499
2500 fenceObject->getFenceiv(pname, params);
2501 }
2502}
2503
2504void GetFloatv(GLenum pname, GLfloat* params)
2505{
2506 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2507
Chris Forbes108f3e12018-08-30 19:41:59 -07002508 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002509
2510 if(context)
2511 {
2512 if(!(context->getFloatv(pname, params)))
2513 {
2514 GLenum nativeType;
2515 unsigned int numParams = 0;
2516 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2517 return error(GL_INVALID_ENUM);
2518
2519 if(numParams == 0)
2520 return; // it is known that the pname is valid, but that there are no parameters to return.
2521
2522 if(nativeType == GL_BOOL)
2523 {
2524 GLboolean *boolParams = nullptr;
2525 boolParams = new GLboolean[numParams];
2526
2527 context->getBooleanv(pname, boolParams);
2528
2529 for(unsigned int i = 0; i < numParams; ++i)
2530 {
2531 if(boolParams[i] == GL_FALSE)
2532 params[i] = 0.0f;
2533 else
2534 params[i] = 1.0f;
2535 }
2536
2537 delete [] boolParams;
2538 }
2539 else if(nativeType == GL_INT)
2540 {
2541 GLint *intParams = nullptr;
2542 intParams = new GLint[numParams];
2543
2544 context->getIntegerv(pname, intParams);
2545
2546 for(unsigned int i = 0; i < numParams; ++i)
2547 {
2548 params[i] = (GLfloat)intParams[i];
2549 }
2550
2551 delete [] intParams;
2552 }
2553 }
2554 }
2555}
2556
2557void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2558{
2559 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2560 target, attachment, pname, params);
2561
Chris Forbes108f3e12018-08-30 19:41:59 -07002562 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002563
2564 if(context)
2565 {
2566 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2567 {
2568 return error(GL_INVALID_ENUM);
2569 }
2570
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002571 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002572
Nicolas Capens0bac2852016-05-07 06:09:58 -04002573 if(target == GL_READ_FRAMEBUFFER)
2574 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002575 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002576 }
2577 else
2578 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002579 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002580 }
2581
Nicolas Capens0bac2852016-05-07 06:09:58 -04002582 switch(attachment)
2583 {
2584 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002585 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002586 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002587 if(framebufferName != 0)
2588 {
2589 return error(GL_INVALID_OPERATION);
2590 }
2591 break;
2592 case GL_DEPTH_ATTACHMENT:
2593 case GL_STENCIL_ATTACHMENT:
2594 if(framebufferName == 0)
2595 {
2596 return error(GL_INVALID_OPERATION);
2597 }
2598 break;
2599 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002600 if(framebufferName == 0)
2601 {
2602 return error(GL_INVALID_OPERATION);
2603 }
2604 break;
2605 default:
2606 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2607 {
2608 if(framebufferName == 0)
2609 {
2610 return error(GL_INVALID_OPERATION);
2611 }
2612 }
2613 else return error(GL_INVALID_ENUM);
2614 }
2615
2616 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2617
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002618 if(!framebuffer)
2619 {
2620 return error(GL_INVALID_OPERATION);
2621 }
2622
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002623 GLenum attachmentType;
2624 GLuint attachmentHandle;
2625 GLint attachmentLayer;
2626 Renderbuffer *renderbuffer = nullptr;
2627 switch(attachment)
2628 {
2629 case GL_BACK:
2630 attachmentType = framebuffer->getColorbufferType(0);
2631 attachmentHandle = framebuffer->getColorbufferName(0);
2632 attachmentLayer = framebuffer->getColorbufferLayer(0);
2633 renderbuffer = framebuffer->getColorbuffer(0);
2634 break;
2635 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002636 case GL_DEPTH_ATTACHMENT:
2637 attachmentType = framebuffer->getDepthbufferType();
2638 attachmentHandle = framebuffer->getDepthbufferName();
2639 attachmentLayer = framebuffer->getDepthbufferLayer();
2640 renderbuffer = framebuffer->getDepthbuffer();
2641 break;
2642 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002643 case GL_STENCIL_ATTACHMENT:
2644 attachmentType = framebuffer->getStencilbufferType();
2645 attachmentHandle = framebuffer->getStencilbufferName();
2646 attachmentLayer = framebuffer->getStencilbufferLayer();
2647 renderbuffer = framebuffer->getStencilbuffer();
2648 break;
2649 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002650 attachmentType = framebuffer->getDepthbufferType();
2651 attachmentHandle = framebuffer->getDepthbufferName();
2652 attachmentLayer = framebuffer->getDepthbufferLayer();
2653 renderbuffer = framebuffer->getDepthbuffer();
2654
2655 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002656 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002657 // Different attachments to DEPTH and STENCIL, query fails
2658 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002659 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002660 break;
2661 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002662 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2663 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2664 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2665 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2666 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2667 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002668 }
2669
2670 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002671 if(framebufferName == 0)
2672 {
2673 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2674 }
2675 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002676 {
2677 attachmentObjectType = attachmentType;
2678 }
2679 else if(es2::IsTextureTarget(attachmentType))
2680 {
2681 attachmentObjectType = GL_TEXTURE;
2682 }
2683 else UNREACHABLE(attachmentType);
2684
2685 if(attachmentObjectType != GL_NONE)
2686 {
2687 switch(pname)
2688 {
2689 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2690 *params = attachmentObjectType;
2691 break;
2692 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002693 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002694 {
2695 *params = attachmentHandle;
2696 }
2697 else
2698 {
2699 return error(GL_INVALID_ENUM);
2700 }
2701 break;
2702 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2703 if(attachmentObjectType == GL_TEXTURE)
2704 {
Nicolas Capens83463112018-06-12 23:55:16 -04002705 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002706 }
2707 else
2708 {
2709 return error(GL_INVALID_ENUM);
2710 }
2711 break;
2712 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2713 if(attachmentObjectType == GL_TEXTURE)
2714 {
2715 if(es2::IsCubemapTextureTarget(attachmentType))
2716 {
2717 *params = attachmentType;
2718 }
2719 else
2720 {
2721 *params = 0;
2722 }
2723 }
2724 else
2725 {
2726 return error(GL_INVALID_ENUM);
2727 }
2728 break;
2729 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002730 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002731 break;
2732 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002733 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002734 break;
2735 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002736 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002737 break;
2738 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002739 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002740 break;
2741 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002742 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002743 break;
2744 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002745 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002746 break;
2747 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002748 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002749 break;
2750 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002751 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2752 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002753 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002754 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002755 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002756
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002757 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002758 break;
2759 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002760 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002761 break;
2762 default:
2763 return error(GL_INVALID_ENUM);
2764 }
2765 }
2766 else
2767 {
2768 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2769 // is NONE, then querying any other pname will generate INVALID_ENUM.
2770
2771 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2772 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2773 // INVALID_OPERATION for all other pnames
2774
2775 switch(pname)
2776 {
2777 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2778 *params = GL_NONE;
2779 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002780 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002781 *params = 0;
2782 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002783 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002784 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002785 }
2786 }
2787 }
2788}
2789
2790GLenum GetGraphicsResetStatusEXT(void)
2791{
2792 TRACE("()");
2793
2794 return GL_NO_ERROR;
2795}
2796
2797void GetIntegerv(GLenum pname, GLint* params)
2798{
2799 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2800
Chris Forbes108f3e12018-08-30 19:41:59 -07002801 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002802
2803 if(!context)
2804 {
2805 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002806 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002807
2808 // This is not spec compliant! When there is no current GL context, functions should
2809 // have no side effects. Google Maps queries these values before creating a context,
2810 // so we need this as a bug-compatible workaround.
2811 switch(pname)
2812 {
2813 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2814 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2815 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2816 case GL_STENCIL_BITS: *params = 8; return;
2817 case GL_ALIASED_LINE_WIDTH_RANGE:
2818 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2819 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2820 return;
2821 }
2822 }
2823
2824 if(context)
2825 {
2826 if(!(context->getIntegerv(pname, params)))
2827 {
2828 GLenum nativeType;
2829 unsigned int numParams = 0;
2830 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2831 return error(GL_INVALID_ENUM);
2832
2833 if(numParams == 0)
2834 return; // it is known that pname is valid, but there are no parameters to return
2835
2836 if(nativeType == GL_BOOL)
2837 {
2838 GLboolean *boolParams = nullptr;
2839 boolParams = new GLboolean[numParams];
2840
2841 context->getBooleanv(pname, boolParams);
2842
2843 for(unsigned int i = 0; i < numParams; ++i)
2844 {
2845 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2846 }
2847
2848 delete [] boolParams;
2849 }
2850 else if(nativeType == GL_FLOAT)
2851 {
2852 GLfloat *floatParams = nullptr;
2853 floatParams = new GLfloat[numParams];
2854
2855 context->getFloatv(pname, floatParams);
2856
2857 for(unsigned int i = 0; i < numParams; ++i)
2858 {
2859 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2860 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002861 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002862 }
2863 else
2864 {
2865 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2866 }
2867 }
2868
2869 delete [] floatParams;
2870 }
2871 }
2872 }
2873}
2874
2875void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2876{
2877 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2878
Chris Forbes108f3e12018-08-30 19:41:59 -07002879 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002880
2881 if(context)
2882 {
2883 es2::Program *programObject = context->getProgram(program);
2884
2885 if(!programObject)
2886 {
2887 if(context->getShader(program))
2888 {
2889 return error(GL_INVALID_OPERATION);
2890 }
2891 else
2892 {
2893 return error(GL_INVALID_VALUE);
2894 }
2895 }
2896
Nicolas Capens0bac2852016-05-07 06:09:58 -04002897 switch(pname)
2898 {
2899 case GL_DELETE_STATUS:
2900 *params = programObject->isFlaggedForDeletion();
2901 return;
2902 case GL_LINK_STATUS:
2903 *params = programObject->isLinked();
2904 return;
2905 case GL_VALIDATE_STATUS:
2906 *params = programObject->isValidated();
2907 return;
2908 case GL_INFO_LOG_LENGTH:
2909 *params = (GLint)programObject->getInfoLogLength();
2910 return;
2911 case GL_ATTACHED_SHADERS:
2912 *params = programObject->getAttachedShadersCount();
2913 return;
2914 case GL_ACTIVE_ATTRIBUTES:
2915 *params = (GLint)programObject->getActiveAttributeCount();
2916 return;
2917 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2918 *params = programObject->getActiveAttributeMaxLength();
2919 return;
2920 case GL_ACTIVE_UNIFORMS:
2921 *params = (GLint)programObject->getActiveUniformCount();
2922 return;
2923 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2924 *params = programObject->getActiveUniformMaxLength();
2925 return;
2926 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002927 *params = (GLint)programObject->getActiveUniformBlockCount();
2928 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002929 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002930 *params = programObject->getActiveUniformBlockMaxLength();
2931 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002932 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002933 *params = programObject->getTransformFeedbackBufferMode();
2934 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002935 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002936 *params = programObject->getTransformFeedbackVaryingCount();
2937 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002938 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002939 *params = programObject->getTransformFeedbackVaryingMaxLength();
2940 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002941 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002942 *params = programObject->getBinaryRetrievableHint();
2943 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002944 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002945 *params = programObject->getBinaryLength();
2946 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002947 default:
2948 return error(GL_INVALID_ENUM);
2949 }
2950 }
2951}
2952
2953void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2954{
2955 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2956 program, bufsize, length, infolog);
2957
2958 if(bufsize < 0)
2959 {
2960 return error(GL_INVALID_VALUE);
2961 }
2962
Chris Forbes108f3e12018-08-30 19:41:59 -07002963 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002964
2965 if(context)
2966 {
2967 es2::Program *programObject = context->getProgram(program);
2968
2969 if(!programObject)
2970 {
2971 if(context->getShader(program))
2972 {
2973 return error(GL_INVALID_OPERATION);
2974 }
2975 else
2976 {
2977 return error(GL_INVALID_VALUE);
2978 }
2979 }
2980
2981 programObject->getInfoLog(bufsize, length, infolog);
2982 }
2983}
2984
2985void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2986{
2987 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2988
2989 switch(pname)
2990 {
2991 case GL_CURRENT_QUERY_EXT:
2992 break;
2993 default:
2994 return error(GL_INVALID_ENUM);
2995 }
2996
Chris Forbes108f3e12018-08-30 19:41:59 -07002997 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002998
2999 if(context)
3000 {
3001 params[0] = context->getActiveQuery(target);
3002 }
3003}
3004
3005void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3006{
3007 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3008
3009 switch(pname)
3010 {
3011 case GL_QUERY_RESULT_EXT:
3012 case GL_QUERY_RESULT_AVAILABLE_EXT:
3013 break;
3014 default:
3015 return error(GL_INVALID_ENUM);
3016 }
3017
Chris Forbes108f3e12018-08-30 19:41:59 -07003018 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003019
3020 if(context)
3021 {
3022 es2::Query *queryObject = context->getQuery(name);
3023
3024 if(!queryObject)
3025 {
3026 return error(GL_INVALID_OPERATION);
3027 }
3028
3029 if(context->getActiveQuery(queryObject->getType()) == name)
3030 {
3031 return error(GL_INVALID_OPERATION);
3032 }
3033
3034 switch(pname)
3035 {
3036 case GL_QUERY_RESULT_EXT:
3037 params[0] = queryObject->getResult();
3038 break;
3039 case GL_QUERY_RESULT_AVAILABLE_EXT:
3040 params[0] = queryObject->isResultAvailable();
3041 break;
3042 default:
3043 ASSERT(false);
3044 }
3045 }
3046}
3047
3048void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3049{
3050 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3051
Chris Forbes108f3e12018-08-30 19:41:59 -07003052 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003053
3054 if(context)
3055 {
3056 if(target != GL_RENDERBUFFER)
3057 {
3058 return error(GL_INVALID_ENUM);
3059 }
3060
3061 if(context->getRenderbufferName() == 0)
3062 {
3063 return error(GL_INVALID_OPERATION);
3064 }
3065
3066 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3067
3068 switch(pname)
3069 {
3070 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3071 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003072 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3073 {
3074 GLint internalformat = renderbuffer->getFormat();
3075 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3076 }
3077 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003078 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3079 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3080 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3081 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3082 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3083 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003084 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003085 default:
3086 return error(GL_INVALID_ENUM);
3087 }
3088 }
3089}
3090
3091void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3092{
3093 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3094
Chris Forbes108f3e12018-08-30 19:41:59 -07003095 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003096
3097 if(context)
3098 {
3099 es2::Shader *shaderObject = context->getShader(shader);
3100
3101 if(!shaderObject)
3102 {
3103 if(context->getProgram(shader))
3104 {
3105 return error(GL_INVALID_OPERATION);
3106 }
3107 else
3108 {
3109 return error(GL_INVALID_VALUE);
3110 }
3111 }
3112
3113 switch(pname)
3114 {
3115 case GL_SHADER_TYPE:
3116 *params = shaderObject->getType();
3117 return;
3118 case GL_DELETE_STATUS:
3119 *params = shaderObject->isFlaggedForDeletion();
3120 return;
3121 case GL_COMPILE_STATUS:
3122 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3123 return;
3124 case GL_INFO_LOG_LENGTH:
3125 *params = (GLint)shaderObject->getInfoLogLength();
3126 return;
3127 case GL_SHADER_SOURCE_LENGTH:
3128 *params = (GLint)shaderObject->getSourceLength();
3129 return;
3130 default:
3131 return error(GL_INVALID_ENUM);
3132 }
3133 }
3134}
3135
3136void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3137{
3138 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3139 shader, bufsize, length, infolog);
3140
3141 if(bufsize < 0)
3142 {
3143 return error(GL_INVALID_VALUE);
3144 }
3145
Chris Forbes108f3e12018-08-30 19:41:59 -07003146 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003147
3148 if(context)
3149 {
3150 es2::Shader *shaderObject = context->getShader(shader);
3151
3152 if(!shaderObject)
3153 {
3154 if(context->getProgram(shader))
3155 {
3156 return error(GL_INVALID_OPERATION);
3157 }
3158 else
3159 {
3160 return error(GL_INVALID_VALUE);
3161 }
3162 }
3163
3164 shaderObject->getInfoLog(bufsize, length, infolog);
3165 }
3166}
3167
3168void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3169{
3170 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3171 shadertype, precisiontype, range, precision);
3172
3173 switch(shadertype)
3174 {
3175 case GL_VERTEX_SHADER:
3176 case GL_FRAGMENT_SHADER:
3177 break;
3178 default:
3179 return error(GL_INVALID_ENUM);
3180 }
3181
3182 switch(precisiontype)
3183 {
3184 case GL_LOW_FLOAT:
3185 case GL_MEDIUM_FLOAT:
3186 case GL_HIGH_FLOAT:
3187 // IEEE 754 single-precision
3188 range[0] = 127;
3189 range[1] = 127;
3190 *precision = 23;
3191 break;
3192 case GL_LOW_INT:
3193 case GL_MEDIUM_INT:
3194 case GL_HIGH_INT:
3195 // Full integer precision is supported
3196 range[0] = 31;
3197 range[1] = 30;
3198 *precision = 0;
3199 break;
3200 default:
3201 return error(GL_INVALID_ENUM);
3202 }
3203}
3204
3205void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3206{
3207 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3208 shader, bufsize, length, source);
3209
3210 if(bufsize < 0)
3211 {
3212 return error(GL_INVALID_VALUE);
3213 }
3214
Chris Forbes108f3e12018-08-30 19:41:59 -07003215 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003216
3217 if(context)
3218 {
3219 es2::Shader *shaderObject = context->getShader(shader);
3220
3221 if(!shaderObject)
3222 {
3223 if(context->getProgram(shader))
3224 {
3225 return error(GL_INVALID_OPERATION);
3226 }
3227 else
3228 {
3229 return error(GL_INVALID_VALUE);
3230 }
3231 }
3232
3233 shaderObject->getSource(bufsize, length, source);
3234 }
3235}
3236
3237const GLubyte* GetString(GLenum name)
3238{
3239 TRACE("(GLenum name = 0x%X)", name);
3240
3241 switch(name)
3242 {
3243 case GL_VENDOR:
3244 return (GLubyte*)"Google Inc.";
3245 case GL_RENDERER:
3246 return (GLubyte*)"Google SwiftShader";
3247 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003248 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003249 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003250 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003251 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003252 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003253 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003254 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3255 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003256 default:
3257 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3258 }
3259}
3260
3261void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3262{
3263 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3264
Chris Forbes108f3e12018-08-30 19:41:59 -07003265 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003266
3267 if(context)
3268 {
3269 es2::Texture *texture;
3270
Nicolas Capens0bac2852016-05-07 06:09:58 -04003271 switch(target)
3272 {
Nicolas Capens83463112018-06-12 23:55:16 -04003273 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3274 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3275 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3276 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3277 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3278 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003279 default:
3280 return error(GL_INVALID_ENUM);
3281 }
3282
3283 switch(pname)
3284 {
3285 case GL_TEXTURE_MAG_FILTER:
3286 *params = (GLfloat)texture->getMagFilter();
3287 break;
3288 case GL_TEXTURE_MIN_FILTER:
3289 *params = (GLfloat)texture->getMinFilter();
3290 break;
3291 case GL_TEXTURE_WRAP_S:
3292 *params = (GLfloat)texture->getWrapS();
3293 break;
3294 case GL_TEXTURE_WRAP_T:
3295 *params = (GLfloat)texture->getWrapT();
3296 break;
3297 case GL_TEXTURE_WRAP_R_OES:
3298 *params = (GLfloat)texture->getWrapR();
3299 break;
3300 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3301 *params = texture->getMaxAnisotropy();
3302 break;
3303 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3304 *params = (GLfloat)1;
3305 break;
3306 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003307 *params = (GLfloat)texture->getBaseLevel();
3308 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003309 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003310 *params = (GLfloat)texture->getCompareFunc();
3311 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003312 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003313 *params = (GLfloat)texture->getCompareMode();
3314 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003315 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003316 *params = (GLfloat)texture->getImmutableFormat();
3317 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003318 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003319 *params = (GLfloat)texture->getImmutableLevels();
3320 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003321 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003322 *params = (GLfloat)texture->getMaxLevel();
3323 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003324 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003325 *params = texture->getMaxLOD();
3326 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003327 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003328 *params = texture->getMinLOD();
3329 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003330 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003331 *params = (GLfloat)texture->getSwizzleR();
3332 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003333 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003334 *params = (GLfloat)texture->getSwizzleG();
3335 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003336 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003337 *params = (GLfloat)texture->getSwizzleB();
3338 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003339 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003340 *params = (GLfloat)texture->getSwizzleA();
3341 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003342 default:
3343 return error(GL_INVALID_ENUM);
3344 }
3345 }
3346}
3347
3348void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3349{
3350 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3351
Chris Forbes108f3e12018-08-30 19:41:59 -07003352 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003353
3354 if(context)
3355 {
3356 es2::Texture *texture;
3357
Nicolas Capens0bac2852016-05-07 06:09:58 -04003358 switch(target)
3359 {
Nicolas Capens83463112018-06-12 23:55:16 -04003360 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3361 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3362 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3363 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3364 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3365 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003366 default:
3367 return error(GL_INVALID_ENUM);
3368 }
3369
3370 switch(pname)
3371 {
3372 case GL_TEXTURE_MAG_FILTER:
3373 *params = texture->getMagFilter();
3374 break;
3375 case GL_TEXTURE_MIN_FILTER:
3376 *params = texture->getMinFilter();
3377 break;
3378 case GL_TEXTURE_WRAP_S:
3379 *params = texture->getWrapS();
3380 break;
3381 case GL_TEXTURE_WRAP_T:
3382 *params = texture->getWrapT();
3383 break;
3384 case GL_TEXTURE_WRAP_R_OES:
3385 *params = texture->getWrapR();
3386 break;
3387 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3388 *params = (GLint)texture->getMaxAnisotropy();
3389 break;
3390 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3391 *params = 1;
3392 break;
3393 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003394 *params = texture->getBaseLevel();
3395 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003396 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003397 *params = (GLint)texture->getCompareFunc();
3398 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003399 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003400 *params = (GLint)texture->getCompareMode();
3401 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003402 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003403 *params = (GLint)texture->getImmutableFormat();
3404 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003405 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003406 *params = (GLint)texture->getImmutableLevels();
3407 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003408 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003409 *params = texture->getMaxLevel();
3410 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003411 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003412 *params = (GLint)roundf(texture->getMaxLOD());
3413 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003414 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003415 *params = (GLint)roundf(texture->getMinLOD());
3416 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003417 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003418 *params = (GLint)texture->getSwizzleR();
3419 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003420 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003421 *params = (GLint)texture->getSwizzleG();
3422 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003423 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003424 *params = (GLint)texture->getSwizzleB();
3425 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003426 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003427 *params = (GLint)texture->getSwizzleA();
3428 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003429 default:
3430 return error(GL_INVALID_ENUM);
3431 }
3432 }
3433}
3434
3435void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3436{
3437 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3438 program, location, bufSize, params);
3439
3440 if(bufSize < 0)
3441 {
3442 return error(GL_INVALID_VALUE);
3443 }
3444
Chris Forbes108f3e12018-08-30 19:41:59 -07003445 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003446
3447 if(context)
3448 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003449 es2::Program *programObject = context->getProgram(program);
3450
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003451 if(!programObject)
3452 {
3453 if(context->getShader(program))
3454 {
3455 return error(GL_INVALID_OPERATION);
3456 }
3457 else
3458 {
3459 return error(GL_INVALID_VALUE);
3460 }
3461 }
3462
3463 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003464 {
3465 return error(GL_INVALID_OPERATION);
3466 }
3467
3468 if(!programObject->getUniformfv(location, &bufSize, params))
3469 {
3470 return error(GL_INVALID_OPERATION);
3471 }
3472 }
3473}
3474
3475void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3476{
3477 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3478
Chris Forbes108f3e12018-08-30 19:41:59 -07003479 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003480
3481 if(context)
3482 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003483 es2::Program *programObject = context->getProgram(program);
3484
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003485 if(!programObject)
3486 {
3487 if(context->getShader(program))
3488 {
3489 return error(GL_INVALID_OPERATION);
3490 }
3491 else
3492 {
3493 return error(GL_INVALID_VALUE);
3494 }
3495 }
3496
3497 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003498 {
3499 return error(GL_INVALID_OPERATION);
3500 }
3501
3502 if(!programObject->getUniformfv(location, nullptr, params))
3503 {
3504 return error(GL_INVALID_OPERATION);
3505 }
3506 }
3507}
3508
3509void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3510{
3511 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3512 program, location, bufSize, params);
3513
3514 if(bufSize < 0)
3515 {
3516 return error(GL_INVALID_VALUE);
3517 }
3518
Chris Forbes108f3e12018-08-30 19:41:59 -07003519 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003520
3521 if(context)
3522 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003523 es2::Program *programObject = context->getProgram(program);
3524
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003525 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003526 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003527 if(context->getShader(program))
3528 {
3529 return error(GL_INVALID_OPERATION);
3530 }
3531 else
3532 {
3533 return error(GL_INVALID_VALUE);
3534 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003535 }
3536
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003537 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003538 {
3539 return error(GL_INVALID_OPERATION);
3540 }
3541
3542 if(!programObject->getUniformiv(location, &bufSize, params))
3543 {
3544 return error(GL_INVALID_OPERATION);
3545 }
3546 }
3547}
3548
3549void GetUniformiv(GLuint program, GLint location, GLint* params)
3550{
3551 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3552
Chris Forbes108f3e12018-08-30 19:41:59 -07003553 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003554
3555 if(context)
3556 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003557 es2::Program *programObject = context->getProgram(program);
3558
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003559 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003560 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003561 if(context->getShader(program))
3562 {
3563 return error(GL_INVALID_OPERATION);
3564 }
3565 else
3566 {
3567 return error(GL_INVALID_VALUE);
3568 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003569 }
3570
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003571 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003572 {
3573 return error(GL_INVALID_OPERATION);
3574 }
3575
3576 if(!programObject->getUniformiv(location, nullptr, params))
3577 {
3578 return error(GL_INVALID_OPERATION);
3579 }
3580 }
3581}
3582
3583int GetUniformLocation(GLuint program, const GLchar* name)
3584{
3585 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3586
Chris Forbes108f3e12018-08-30 19:41:59 -07003587 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003588
3589 if(strstr(name, "gl_") == name)
3590 {
3591 return -1;
3592 }
3593
3594 if(context)
3595 {
3596 es2::Program *programObject = context->getProgram(program);
3597
3598 if(!programObject)
3599 {
3600 if(context->getShader(program))
3601 {
3602 return error(GL_INVALID_OPERATION, -1);
3603 }
3604 else
3605 {
3606 return error(GL_INVALID_VALUE, -1);
3607 }
3608 }
3609
3610 if(!programObject->isLinked())
3611 {
3612 return error(GL_INVALID_OPERATION, -1);
3613 }
3614
3615 return programObject->getUniformLocation(name);
3616 }
3617
3618 return -1;
3619}
3620
3621void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3622{
3623 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3624
Chris Forbes108f3e12018-08-30 19:41:59 -07003625 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003626
3627 if(context)
3628 {
3629 if(index >= es2::MAX_VERTEX_ATTRIBS)
3630 {
3631 return error(GL_INVALID_VALUE);
3632 }
3633
3634 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3635
Nicolas Capens0bac2852016-05-07 06:09:58 -04003636 switch(pname)
3637 {
3638 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3639 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3640 break;
3641 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3642 *params = (GLfloat)attribState.mSize;
3643 break;
3644 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3645 *params = (GLfloat)attribState.mStride;
3646 break;
3647 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3648 *params = (GLfloat)attribState.mType;
3649 break;
3650 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3651 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3652 break;
3653 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3654 *params = (GLfloat)attribState.mBoundBuffer.name();
3655 break;
3656 case GL_CURRENT_VERTEX_ATTRIB:
3657 {
3658 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3659 for(int i = 0; i < 4; ++i)
3660 {
3661 params[i] = attrib.getCurrentValueF(i);
3662 }
3663 }
3664 break;
3665 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003666 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3667 break;
3668 default:
3669 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003670 }
3671 }
3672}
3673
3674void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3675{
3676 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3677
Chris Forbes108f3e12018-08-30 19:41:59 -07003678 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003679
3680 if(context)
3681 {
3682 if(index >= es2::MAX_VERTEX_ATTRIBS)
3683 {
3684 return error(GL_INVALID_VALUE);
3685 }
3686
3687 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3688
Nicolas Capens0bac2852016-05-07 06:09:58 -04003689 switch(pname)
3690 {
3691 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3692 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3693 break;
3694 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3695 *params = attribState.mSize;
3696 break;
3697 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3698 *params = attribState.mStride;
3699 break;
3700 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3701 *params = attribState.mType;
3702 break;
3703 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3704 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3705 break;
3706 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3707 *params = attribState.mBoundBuffer.name();
3708 break;
3709 case GL_CURRENT_VERTEX_ATTRIB:
3710 {
3711 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3712 for(int i = 0; i < 4; ++i)
3713 {
3714 float currentValue = attrib.getCurrentValueF(i);
3715 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3716 }
3717 }
3718 break;
3719 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003720 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3721 break;
3722 default:
3723 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003724 }
3725 }
3726}
3727
3728void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3729{
3730 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3731
Chris Forbes108f3e12018-08-30 19:41:59 -07003732 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003733
3734 if(context)
3735 {
3736 if(index >= es2::MAX_VERTEX_ATTRIBS)
3737 {
3738 return error(GL_INVALID_VALUE);
3739 }
3740
3741 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3742 {
3743 return error(GL_INVALID_ENUM);
3744 }
3745
3746 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3747 }
3748}
3749
3750void Hint(GLenum target, GLenum mode)
3751{
3752 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3753
3754 switch(mode)
3755 {
3756 case GL_FASTEST:
3757 case GL_NICEST:
3758 case GL_DONT_CARE:
3759 break;
3760 default:
3761 return error(GL_INVALID_ENUM);
3762 }
3763
Chris Forbes108f3e12018-08-30 19:41:59 -07003764 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003765
3766 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003767 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003768 switch(target)
3769 {
3770 case GL_GENERATE_MIPMAP_HINT:
3771 context->setGenerateMipmapHint(mode);
3772 break;
3773 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3774 context->setFragmentShaderDerivativeHint(mode);
3775 break;
3776 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3777 context->setTextureFilteringHint(mode);
3778 break;
3779 default:
3780 return error(GL_INVALID_ENUM);
3781 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003782 }
3783}
3784
3785GLboolean IsBuffer(GLuint buffer)
3786{
3787 TRACE("(GLuint buffer = %d)", buffer);
3788
Chris Forbes108f3e12018-08-30 19:41:59 -07003789 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003790
3791 if(context && buffer)
3792 {
3793 es2::Buffer *bufferObject = context->getBuffer(buffer);
3794
3795 if(bufferObject)
3796 {
3797 return GL_TRUE;
3798 }
3799 }
3800
3801 return GL_FALSE;
3802}
3803
3804GLboolean IsEnabled(GLenum cap)
3805{
3806 TRACE("(GLenum cap = 0x%X)", cap);
3807
Chris Forbes108f3e12018-08-30 19:41:59 -07003808 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003809
3810 if(context)
3811 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003812 switch(cap)
3813 {
3814 case GL_CULL_FACE: return context->isCullFaceEnabled();
3815 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3816 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3817 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3818 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3819 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3820 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3821 case GL_BLEND: return context->isBlendEnabled();
3822 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003823 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3824 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003825 default:
3826 return error(GL_INVALID_ENUM, false);
3827 }
3828 }
3829
3830 return false;
3831}
3832
3833GLboolean IsFenceNV(GLuint fence)
3834{
3835 TRACE("(GLuint fence = %d)", fence);
3836
Chris Forbes108f3e12018-08-30 19:41:59 -07003837 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003838
3839 if(context)
3840 {
3841 es2::Fence *fenceObject = context->getFence(fence);
3842
3843 if(!fenceObject)
3844 {
3845 return GL_FALSE;
3846 }
3847
3848 return fenceObject->isFence();
3849 }
3850
3851 return GL_FALSE;
3852}
3853
3854GLboolean IsFramebuffer(GLuint framebuffer)
3855{
3856 TRACE("(GLuint framebuffer = %d)", framebuffer);
3857
Chris Forbes108f3e12018-08-30 19:41:59 -07003858 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003859
3860 if(context && framebuffer)
3861 {
3862 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3863
3864 if(framebufferObject)
3865 {
3866 return GL_TRUE;
3867 }
3868 }
3869
3870 return GL_FALSE;
3871}
3872
3873GLboolean IsProgram(GLuint program)
3874{
3875 TRACE("(GLuint program = %d)", program);
3876
Chris Forbes108f3e12018-08-30 19:41:59 -07003877 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003878
3879 if(context && program)
3880 {
3881 es2::Program *programObject = context->getProgram(program);
3882
3883 if(programObject)
3884 {
3885 return GL_TRUE;
3886 }
3887 }
3888
3889 return GL_FALSE;
3890}
3891
3892GLboolean IsQueryEXT(GLuint name)
3893{
3894 TRACE("(GLuint name = %d)", name);
3895
3896 if(name == 0)
3897 {
3898 return GL_FALSE;
3899 }
3900
Chris Forbes108f3e12018-08-30 19:41:59 -07003901 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003902
3903 if(context)
3904 {
3905 es2::Query *queryObject = context->getQuery(name);
3906
3907 if(queryObject)
3908 {
3909 return GL_TRUE;
3910 }
3911 }
3912
3913 return GL_FALSE;
3914}
3915
3916GLboolean IsRenderbuffer(GLuint renderbuffer)
3917{
3918 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3919
Chris Forbes108f3e12018-08-30 19:41:59 -07003920 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003921
3922 if(context && renderbuffer)
3923 {
3924 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3925
3926 if(renderbufferObject)
3927 {
3928 return GL_TRUE;
3929 }
3930 }
3931
3932 return GL_FALSE;
3933}
3934
3935GLboolean IsShader(GLuint shader)
3936{
3937 TRACE("(GLuint shader = %d)", shader);
3938
Chris Forbes108f3e12018-08-30 19:41:59 -07003939 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003940
3941 if(context && shader)
3942 {
3943 es2::Shader *shaderObject = context->getShader(shader);
3944
3945 if(shaderObject)
3946 {
3947 return GL_TRUE;
3948 }
3949 }
3950
3951 return GL_FALSE;
3952}
3953
3954GLboolean IsTexture(GLuint texture)
3955{
3956 TRACE("(GLuint texture = %d)", texture);
3957
Chris Forbes108f3e12018-08-30 19:41:59 -07003958 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003959
3960 if(context && texture)
3961 {
3962 es2::Texture *textureObject = context->getTexture(texture);
3963
3964 if(textureObject)
3965 {
3966 return GL_TRUE;
3967 }
3968 }
3969
3970 return GL_FALSE;
3971}
3972
3973void LineWidth(GLfloat width)
3974{
3975 TRACE("(GLfloat width = %f)", width);
3976
3977 if(width <= 0.0f)
3978 {
3979 return error(GL_INVALID_VALUE);
3980 }
3981
Chris Forbes108f3e12018-08-30 19:41:59 -07003982 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003983
3984 if(context)
3985 {
3986 context->setLineWidth(width);
3987 }
3988}
3989
3990void LinkProgram(GLuint program)
3991{
3992 TRACE("(GLuint program = %d)", program);
3993
Chris Forbes108f3e12018-08-30 19:41:59 -07003994 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003995
3996 if(context)
3997 {
3998 es2::Program *programObject = context->getProgram(program);
3999
4000 if(!programObject)
4001 {
4002 if(context->getShader(program))
4003 {
4004 return error(GL_INVALID_OPERATION);
4005 }
4006 else
4007 {
4008 return error(GL_INVALID_VALUE);
4009 }
4010 }
4011
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004012 if(programObject == context->getCurrentProgram())
4013 {
4014 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4015 if(transformFeedback && transformFeedback->isActive())
4016 {
4017 return error(GL_INVALID_OPERATION);
4018 }
4019 }
4020
Nicolas Capens0bac2852016-05-07 06:09:58 -04004021 programObject->link();
4022 }
4023}
4024
4025void PixelStorei(GLenum pname, GLint param)
4026{
4027 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4028
Chris Forbes108f3e12018-08-30 19:41:59 -07004029 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004030
4031 if(context)
4032 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004033 switch(pname)
4034 {
4035 case GL_UNPACK_ALIGNMENT:
4036 if(param != 1 && param != 2 && param != 4 && param != 8)
4037 {
4038 return error(GL_INVALID_VALUE);
4039 }
4040 context->setUnpackAlignment(param);
4041 break;
4042 case GL_PACK_ALIGNMENT:
4043 if(param != 1 && param != 2 && param != 4 && param != 8)
4044 {
4045 return error(GL_INVALID_VALUE);
4046 }
4047 context->setPackAlignment(param);
4048 break;
4049 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004050 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004051 {
Nicolas Capens83463112018-06-12 23:55:16 -04004052 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004053 }
Nicolas Capens83463112018-06-12 23:55:16 -04004054 context->setPackRowLength(param);
4055 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004056 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004057 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004058 {
Nicolas Capens83463112018-06-12 23:55:16 -04004059 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004060 }
Nicolas Capens83463112018-06-12 23:55:16 -04004061 context->setPackSkipPixels(param);
4062 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004063 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004064 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004065 {
Nicolas Capens83463112018-06-12 23:55:16 -04004066 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004067 }
Nicolas Capens83463112018-06-12 23:55:16 -04004068 context->setPackSkipRows(param);
4069 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004070 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004071 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004072 {
Nicolas Capens83463112018-06-12 23:55:16 -04004073 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004074 }
Nicolas Capens83463112018-06-12 23:55:16 -04004075 context->setUnpackRowLength(param);
4076 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004077 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004078 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004079 {
Nicolas Capens83463112018-06-12 23:55:16 -04004080 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 }
Nicolas Capens83463112018-06-12 23:55:16 -04004082 context->setUnpackImageHeight(param);
4083 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004084 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004085 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004086 {
Nicolas Capens83463112018-06-12 23:55:16 -04004087 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 }
Nicolas Capens83463112018-06-12 23:55:16 -04004089 context->setUnpackSkipPixels(param);
4090 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004091 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004092 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004093 {
Nicolas Capens83463112018-06-12 23:55:16 -04004094 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 }
Nicolas Capens83463112018-06-12 23:55:16 -04004096 context->setUnpackSkipRows(param);
4097 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004098 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004099 if(param < 0)
4100 {
4101 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 }
Nicolas Capens83463112018-06-12 23:55:16 -04004103 context->setUnpackSkipImages(param);
4104 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004105 default:
4106 return error(GL_INVALID_ENUM);
4107 }
4108 }
4109}
4110
4111void PolygonOffset(GLfloat factor, GLfloat units)
4112{
4113 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4114
Chris Forbes108f3e12018-08-30 19:41:59 -07004115 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004116
4117 if(context)
4118 {
4119 context->setPolygonOffsetParams(factor, units);
4120 }
4121}
4122
4123void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4124 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4125{
4126 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4127 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4128 x, y, width, height, format, type, bufSize, data);
4129
4130 if(width < 0 || height < 0 || bufSize < 0)
4131 {
4132 return error(GL_INVALID_VALUE);
4133 }
4134
Chris Forbes108f3e12018-08-30 19:41:59 -07004135 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004136
4137 if(context)
4138 {
4139 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4140 }
4141}
4142
4143void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4144{
4145 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4146 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4147 x, y, width, height, format, type, pixels);
4148
4149 if(width < 0 || height < 0)
4150 {
4151 return error(GL_INVALID_VALUE);
4152 }
4153
Chris Forbes108f3e12018-08-30 19:41:59 -07004154 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004155
4156 if(context)
4157 {
4158 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4159 }
4160}
4161
4162void ReleaseShaderCompiler(void)
4163{
4164 TRACE("()");
4165
4166 es2::Shader::releaseCompiler();
4167}
4168
Nicolas Capens400667e2017-03-29 14:40:14 -04004169void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004170{
4171 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4172 target, samples, internalformat, width, height);
4173
4174 switch(target)
4175 {
4176 case GL_RENDERBUFFER:
4177 break;
4178 default:
4179 return error(GL_INVALID_ENUM);
4180 }
4181
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004182 if(width < 0 || height < 0 || samples < 0 ||
4183 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4184 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004185 {
4186 return error(GL_INVALID_VALUE);
4187 }
4188
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004189 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004190 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004191 {
4192 return error(GL_INVALID_OPERATION);
4193 }
4194
Chris Forbes108f3e12018-08-30 19:41:59 -07004195 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004196
4197 if(context)
4198 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004199 GLuint handle = context->getRenderbufferName();
4200 if(handle == 0)
4201 {
4202 return error(GL_INVALID_OPERATION);
4203 }
4204
Nicolas Capens83463112018-06-12 23:55:16 -04004205 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004206 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004207 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004208 }
Nicolas Capens83463112018-06-12 23:55:16 -04004209 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004210 {
4211 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4212 }
Nicolas Capens83463112018-06-12 23:55:16 -04004213 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004214 {
4215 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4216 }
Nicolas Capens83463112018-06-12 23:55:16 -04004217 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004218 {
4219 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4220 }
4221 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004222 }
4223}
4224
Nicolas Capens400667e2017-03-29 14:40:14 -04004225void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4226{
4227 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4228}
4229
Nicolas Capens0bac2852016-05-07 06:09:58 -04004230void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4231{
Nicolas Capens400667e2017-03-29 14:40:14 -04004232 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004233}
4234
4235void SampleCoverage(GLclampf value, GLboolean invert)
4236{
4237 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4238
Chris Forbes108f3e12018-08-30 19:41:59 -07004239 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004240
4241 if(context)
4242 {
4243 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4244 }
4245}
4246
4247void SetFenceNV(GLuint fence, GLenum condition)
4248{
4249 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4250
4251 if(condition != GL_ALL_COMPLETED_NV)
4252 {
4253 return error(GL_INVALID_ENUM);
4254 }
4255
Chris Forbes108f3e12018-08-30 19:41:59 -07004256 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004257
4258 if(context)
4259 {
4260 es2::Fence *fenceObject = context->getFence(fence);
4261
4262 if(!fenceObject)
4263 {
4264 return error(GL_INVALID_OPERATION);
4265 }
4266
4267 fenceObject->setFence(condition);
4268 }
4269}
4270
4271void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4272{
4273 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4274
4275 if(width < 0 || height < 0)
4276 {
4277 return error(GL_INVALID_VALUE);
4278 }
4279
Chris Forbes108f3e12018-08-30 19:41:59 -07004280 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004281
4282 if(context)
4283 {
4284 context->setScissorParams(x, y, width, height);
4285 }
4286}
4287
4288void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4289{
4290 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4291 "const GLvoid* binary = %p, GLsizei length = %d)",
4292 n, shaders, binaryformat, binary, length);
4293
4294 // No binary shader formats are supported.
4295 return error(GL_INVALID_ENUM);
4296}
4297
4298void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4299{
4300 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4301 shader, count, string, length);
4302
4303 if(count < 0)
4304 {
4305 return error(GL_INVALID_VALUE);
4306 }
4307
Chris Forbes108f3e12018-08-30 19:41:59 -07004308 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004309
4310 if(context)
4311 {
4312 es2::Shader *shaderObject = context->getShader(shader);
4313
4314 if(!shaderObject)
4315 {
4316 if(context->getProgram(shader))
4317 {
4318 return error(GL_INVALID_OPERATION);
4319 }
4320 else
4321 {
4322 return error(GL_INVALID_VALUE);
4323 }
4324 }
4325
4326 shaderObject->setSource(count, string, length);
4327 }
4328}
4329
4330void StencilFunc(GLenum func, GLint ref, GLuint mask)
4331{
4332 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4333}
4334
4335void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4336{
4337 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4338
4339 switch(face)
4340 {
4341 case GL_FRONT:
4342 case GL_BACK:
4343 case GL_FRONT_AND_BACK:
4344 break;
4345 default:
4346 return error(GL_INVALID_ENUM);
4347 }
4348
4349 switch(func)
4350 {
4351 case GL_NEVER:
4352 case GL_ALWAYS:
4353 case GL_LESS:
4354 case GL_LEQUAL:
4355 case GL_EQUAL:
4356 case GL_GEQUAL:
4357 case GL_GREATER:
4358 case GL_NOTEQUAL:
4359 break;
4360 default:
4361 return error(GL_INVALID_ENUM);
4362 }
4363
Chris Forbes108f3e12018-08-30 19:41:59 -07004364 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004365
4366 if(context)
4367 {
4368 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4369 {
4370 context->setStencilParams(func, ref, mask);
4371 }
4372
4373 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4374 {
4375 context->setStencilBackParams(func, ref, mask);
4376 }
4377 }
4378}
4379
4380void StencilMask(GLuint mask)
4381{
4382 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4383}
4384
4385void StencilMaskSeparate(GLenum face, GLuint mask)
4386{
4387 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4388
4389 switch(face)
4390 {
4391 case GL_FRONT:
4392 case GL_BACK:
4393 case GL_FRONT_AND_BACK:
4394 break;
4395 default:
4396 return error(GL_INVALID_ENUM);
4397 }
4398
Chris Forbes108f3e12018-08-30 19:41:59 -07004399 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004400
4401 if(context)
4402 {
4403 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4404 {
4405 context->setStencilWritemask(mask);
4406 }
4407
4408 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4409 {
4410 context->setStencilBackWritemask(mask);
4411 }
4412 }
4413}
4414
4415void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4416{
4417 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4418}
4419
4420void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4421{
4422 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4423 face, fail, zfail, zpass);
4424
4425 switch(face)
4426 {
4427 case GL_FRONT:
4428 case GL_BACK:
4429 case GL_FRONT_AND_BACK:
4430 break;
4431 default:
4432 return error(GL_INVALID_ENUM);
4433 }
4434
4435 switch(fail)
4436 {
4437 case GL_ZERO:
4438 case GL_KEEP:
4439 case GL_REPLACE:
4440 case GL_INCR:
4441 case GL_DECR:
4442 case GL_INVERT:
4443 case GL_INCR_WRAP:
4444 case GL_DECR_WRAP:
4445 break;
4446 default:
4447 return error(GL_INVALID_ENUM);
4448 }
4449
4450 switch(zfail)
4451 {
4452 case GL_ZERO:
4453 case GL_KEEP:
4454 case GL_REPLACE:
4455 case GL_INCR:
4456 case GL_DECR:
4457 case GL_INVERT:
4458 case GL_INCR_WRAP:
4459 case GL_DECR_WRAP:
4460 break;
4461 default:
4462 return error(GL_INVALID_ENUM);
4463 }
4464
4465 switch(zpass)
4466 {
4467 case GL_ZERO:
4468 case GL_KEEP:
4469 case GL_REPLACE:
4470 case GL_INCR:
4471 case GL_DECR:
4472 case GL_INVERT:
4473 case GL_INCR_WRAP:
4474 case GL_DECR_WRAP:
4475 break;
4476 default:
4477 return error(GL_INVALID_ENUM);
4478 }
4479
Chris Forbes108f3e12018-08-30 19:41:59 -07004480 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004481
4482 if(context)
4483 {
4484 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4485 {
4486 context->setStencilOperations(fail, zfail, zpass);
4487 }
4488
4489 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4490 {
4491 context->setStencilBackOperations(fail, zfail, zpass);
4492 }
4493 }
4494}
4495
4496GLboolean TestFenceNV(GLuint fence)
4497{
4498 TRACE("(GLuint fence = %d)", fence);
4499
Chris Forbes108f3e12018-08-30 19:41:59 -07004500 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004501
4502 if(context)
4503 {
4504 es2::Fence *fenceObject = context->getFence(fence);
4505
4506 if(!fenceObject)
4507 {
4508 return error(GL_INVALID_OPERATION, GL_TRUE);
4509 }
4510
4511 return fenceObject->testFence();
4512 }
4513
4514 return GL_TRUE;
4515}
4516
4517void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004518 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004519{
4520 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004521 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4522 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004523
4524 if(!validImageSize(level, width, height))
4525 {
4526 return error(GL_INVALID_VALUE);
4527 }
4528
Chris Forbes108f3e12018-08-30 19:41:59 -07004529 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004530
4531 if(context)
4532 {
Nicolas Capens83463112018-06-12 23:55:16 -04004533 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004534 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4535 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4536 {
4537 internalformat = GL_BGRA_EXT;
4538 }
4539
Nicolas Capens83463112018-06-12 23:55:16 -04004540 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004541 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004542 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004543 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004544 }
4545
4546 if(border != 0)
4547 {
4548 return error(GL_INVALID_VALUE);
4549 }
4550
4551 switch(target)
4552 {
Alexis Hetu46768622018-01-16 22:09:28 -05004553 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004554 if(level != 0)
4555 {
4556 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4557 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004558 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004559 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004560 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4561 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4562 {
4563 return error(GL_INVALID_VALUE);
4564 }
4565 break;
4566 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4567 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4568 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4569 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4570 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4571 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4572 if(width != height)
4573 {
4574 return error(GL_INVALID_VALUE);
4575 }
4576
4577 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4578 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4579 {
4580 return error(GL_INVALID_VALUE);
4581 }
4582 break;
4583 default:
4584 return error(GL_INVALID_ENUM);
4585 }
4586
Nicolas Capens5555af42017-12-14 13:14:03 -05004587 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004588 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004589 {
4590 return error(validationError);
4591 }
4592
Nicolas Capens894858a2018-03-22 00:55:23 -04004593 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4594
Alexis Hetu46768622018-01-16 22:09:28 -05004595 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004596 {
Alexis Hetu46768622018-01-16 22:09:28 -05004597 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004598
4599 if(!texture)
4600 {
4601 return error(GL_INVALID_OPERATION);
4602 }
4603
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004604 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004605 }
4606 else
4607 {
4608 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4609
4610 if(!texture)
4611 {
4612 return error(GL_INVALID_OPERATION);
4613 }
4614
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004615 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004616 }
4617 }
4618}
4619
4620void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4621{
4622 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4623
Chris Forbes108f3e12018-08-30 19:41:59 -07004624 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004625
4626 if(context)
4627 {
4628 es2::Texture *texture;
4629
Nicolas Capens0bac2852016-05-07 06:09:58 -04004630 switch(target)
4631 {
Nicolas Capens83463112018-06-12 23:55:16 -04004632 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4633 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4634 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4635 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4636 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4637 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004638 default:
4639 return error(GL_INVALID_ENUM);
4640 }
4641
4642 switch(pname)
4643 {
4644 case GL_TEXTURE_WRAP_S:
4645 if(!texture->setWrapS((GLenum)param))
4646 {
4647 return error(GL_INVALID_ENUM);
4648 }
4649 break;
4650 case GL_TEXTURE_WRAP_T:
4651 if(!texture->setWrapT((GLenum)param))
4652 {
4653 return error(GL_INVALID_ENUM);
4654 }
4655 break;
4656 case GL_TEXTURE_WRAP_R_OES:
4657 if(!texture->setWrapR((GLenum)param))
4658 {
4659 return error(GL_INVALID_ENUM);
4660 }
4661 break;
4662 case GL_TEXTURE_MIN_FILTER:
4663 if(!texture->setMinFilter((GLenum)param))
4664 {
4665 return error(GL_INVALID_ENUM);
4666 }
4667 break;
4668 case GL_TEXTURE_MAG_FILTER:
4669 if(!texture->setMagFilter((GLenum)param))
4670 {
4671 return error(GL_INVALID_ENUM);
4672 }
4673 break;
4674 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4675 if(!texture->setMaxAnisotropy(param))
4676 {
4677 return error(GL_INVALID_VALUE);
4678 }
4679 break;
4680 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004681 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004682 {
4683 return error(GL_INVALID_VALUE);
4684 }
4685 break;
4686 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004687 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004688 {
4689 return error(GL_INVALID_VALUE);
4690 }
4691 break;
4692 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004693 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004694 {
4695 return error(GL_INVALID_VALUE);
4696 }
4697 break;
4698 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004699 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004700 {
4701 return error(GL_INVALID_VALUE);
4702 }
4703 break;
4704 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004705 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004706 {
4707 return error(GL_INVALID_VALUE);
4708 }
4709 break;
4710 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004711 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004712 {
4713 return error(GL_INVALID_VALUE);
4714 }
4715 break;
4716 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004717 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004718 {
4719 return error(GL_INVALID_VALUE);
4720 }
4721 break;
4722 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004723 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004724 {
4725 return error(GL_INVALID_VALUE);
4726 }
4727 break;
4728 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004729 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004730 {
4731 return error(GL_INVALID_VALUE);
4732 }
4733 break;
4734 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004735 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004736 {
4737 return error(GL_INVALID_VALUE);
4738 }
4739 break;
4740 default:
4741 return error(GL_INVALID_ENUM);
4742 }
4743 }
4744}
4745
4746void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4747{
4748 glTexParameterf(target, pname, *params);
4749}
4750
4751void TexParameteri(GLenum target, GLenum pname, GLint param)
4752{
4753 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4754
Chris Forbes108f3e12018-08-30 19:41:59 -07004755 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004756
4757 if(context)
4758 {
4759 es2::Texture *texture;
4760
Nicolas Capens0bac2852016-05-07 06:09:58 -04004761 switch(target)
4762 {
Nicolas Capens83463112018-06-12 23:55:16 -04004763 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4764 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4765 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4766 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4767 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4768 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004769 default:
4770 return error(GL_INVALID_ENUM);
4771 }
4772
4773 switch(pname)
4774 {
4775 case GL_TEXTURE_WRAP_S:
4776 if(!texture->setWrapS((GLenum)param))
4777 {
4778 return error(GL_INVALID_ENUM);
4779 }
4780 break;
4781 case GL_TEXTURE_WRAP_T:
4782 if(!texture->setWrapT((GLenum)param))
4783 {
4784 return error(GL_INVALID_ENUM);
4785 }
4786 break;
4787 case GL_TEXTURE_WRAP_R_OES:
4788 if(!texture->setWrapR((GLenum)param))
4789 {
4790 return error(GL_INVALID_ENUM);
4791 }
4792 break;
4793 case GL_TEXTURE_MIN_FILTER:
4794 if(!texture->setMinFilter((GLenum)param))
4795 {
4796 return error(GL_INVALID_ENUM);
4797 }
4798 break;
4799 case GL_TEXTURE_MAG_FILTER:
4800 if(!texture->setMagFilter((GLenum)param))
4801 {
4802 return error(GL_INVALID_ENUM);
4803 }
4804 break;
4805 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4806 if(!texture->setMaxAnisotropy((GLfloat)param))
4807 {
4808 return error(GL_INVALID_VALUE);
4809 }
4810 break;
4811 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004812 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4813 {
4814 return error(GL_INVALID_OPERATION); // Base level has to be 0
4815 }
Nicolas Capens83463112018-06-12 23:55:16 -04004816 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004817 {
4818 return error(GL_INVALID_VALUE);
4819 }
4820 break;
4821 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004822 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004823 {
4824 return error(GL_INVALID_VALUE);
4825 }
4826 break;
4827 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004828 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004829 {
4830 return error(GL_INVALID_VALUE);
4831 }
4832 break;
4833 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004834 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004835 {
4836 return error(GL_INVALID_VALUE);
4837 }
4838 break;
4839 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004840 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004841 {
4842 return error(GL_INVALID_VALUE);
4843 }
4844 break;
4845 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004846 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004847 {
4848 return error(GL_INVALID_VALUE);
4849 }
4850 break;
4851 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004852 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004853 {
4854 return error(GL_INVALID_VALUE);
4855 }
4856 break;
4857 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004858 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004859 {
4860 return error(GL_INVALID_VALUE);
4861 }
4862 break;
4863 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004864 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004865 {
4866 return error(GL_INVALID_VALUE);
4867 }
4868 break;
4869 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004870 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004871 {
4872 return error(GL_INVALID_VALUE);
4873 }
4874 break;
4875 default:
4876 return error(GL_INVALID_ENUM);
4877 }
4878 }
4879}
4880
4881void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4882{
4883 glTexParameteri(target, pname, *params);
4884}
4885
4886void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004887 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004888{
4889 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4890 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004891 "const GLvoid* data = %p)",
4892 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004893
4894 if(!es2::IsTextureTarget(target))
4895 {
4896 return error(GL_INVALID_ENUM);
4897 }
4898
4899 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4900 {
4901 return error(GL_INVALID_VALUE);
4902 }
4903
4904 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4905 {
4906 return error(GL_INVALID_VALUE);
4907 }
4908
4909 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4910 {
4911 return error(GL_INVALID_VALUE);
4912 }
4913
Chris Forbes108f3e12018-08-30 19:41:59 -07004914 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004915
4916 if(context)
4917 {
Alexis Hetu46768622018-01-16 22:09:28 -05004918 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004919 {
Alexis Hetu46768622018-01-16 22:09:28 -05004920 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004921
Nicolas Capens83463112018-06-12 23:55:16 -04004922 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004923 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004924 {
4925 return error(validationError);
4926 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004927
Nicolas Capens5555af42017-12-14 13:14:03 -05004928 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004929 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004930 {
4931 return error(validationError);
4932 }
4933
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004934 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004935 }
4936 else if(es2::IsCubemapTextureTarget(target))
4937 {
4938 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4939
Nicolas Capens83463112018-06-12 23:55:16 -04004940 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004941 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004942 {
4943 return error(validationError);
4944 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004945
Nicolas Capens5555af42017-12-14 13:14:03 -05004946 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004947 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004948 {
4949 return error(validationError);
4950 }
4951
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004952 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004953 }
4954 else UNREACHABLE(target);
4955 }
4956}
4957
4958void Uniform1f(GLint location, GLfloat x)
4959{
4960 glUniform1fv(location, 1, &x);
4961}
4962
4963void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4964{
4965 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4966
4967 if(count < 0)
4968 {
4969 return error(GL_INVALID_VALUE);
4970 }
4971
Chris Forbes108f3e12018-08-30 19:41:59 -07004972 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004973
4974 if(context)
4975 {
4976 es2::Program *program = context->getCurrentProgram();
4977
4978 if(!program)
4979 {
4980 return error(GL_INVALID_OPERATION);
4981 }
4982
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004983 if(location == -1)
4984 {
4985 return;
4986 }
4987
Nicolas Capens0bac2852016-05-07 06:09:58 -04004988 if(!program->setUniform1fv(location, count, v))
4989 {
4990 return error(GL_INVALID_OPERATION);
4991 }
4992 }
4993}
4994
4995void Uniform1i(GLint location, GLint x)
4996{
4997 glUniform1iv(location, 1, &x);
4998}
4999
5000void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5001{
5002 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5003
5004 if(count < 0)
5005 {
5006 return error(GL_INVALID_VALUE);
5007 }
5008
Chris Forbes108f3e12018-08-30 19:41:59 -07005009 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005010
5011 if(context)
5012 {
5013 es2::Program *program = context->getCurrentProgram();
5014
5015 if(!program)
5016 {
5017 return error(GL_INVALID_OPERATION);
5018 }
5019
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005020 if(location == -1)
5021 {
5022 return;
5023 }
5024
Nicolas Capens0bac2852016-05-07 06:09:58 -04005025 if(!program->setUniform1iv(location, count, v))
5026 {
5027 return error(GL_INVALID_OPERATION);
5028 }
5029 }
5030}
5031
5032void Uniform2f(GLint location, GLfloat x, GLfloat y)
5033{
5034 GLfloat xy[2] = {x, y};
5035
5036 glUniform2fv(location, 1, (GLfloat*)&xy);
5037}
5038
5039void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5040{
5041 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5042
5043 if(count < 0)
5044 {
5045 return error(GL_INVALID_VALUE);
5046 }
5047
Chris Forbes108f3e12018-08-30 19:41:59 -07005048 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005049
5050 if(context)
5051 {
5052 es2::Program *program = context->getCurrentProgram();
5053
5054 if(!program)
5055 {
5056 return error(GL_INVALID_OPERATION);
5057 }
5058
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005059 if(location == -1)
5060 {
5061 return;
5062 }
5063
Nicolas Capens0bac2852016-05-07 06:09:58 -04005064 if(!program->setUniform2fv(location, count, v))
5065 {
5066 return error(GL_INVALID_OPERATION);
5067 }
5068 }
5069}
5070
5071void Uniform2i(GLint location, GLint x, GLint y)
5072{
5073 GLint xy[4] = {x, y};
5074
5075 glUniform2iv(location, 1, (GLint*)&xy);
5076}
5077
5078void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5079{
5080 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5081
5082 if(count < 0)
5083 {
5084 return error(GL_INVALID_VALUE);
5085 }
5086
Chris Forbes108f3e12018-08-30 19:41:59 -07005087 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005088
5089 if(context)
5090 {
5091 es2::Program *program = context->getCurrentProgram();
5092
5093 if(!program)
5094 {
5095 return error(GL_INVALID_OPERATION);
5096 }
5097
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005098 if(location == -1)
5099 {
5100 return;
5101 }
5102
Nicolas Capens0bac2852016-05-07 06:09:58 -04005103 if(!program->setUniform2iv(location, count, v))
5104 {
5105 return error(GL_INVALID_OPERATION);
5106 }
5107 }
5108}
5109
5110void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5111{
5112 GLfloat xyz[3] = {x, y, z};
5113
5114 glUniform3fv(location, 1, (GLfloat*)&xyz);
5115}
5116
5117void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5118{
5119 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5120
5121 if(count < 0)
5122 {
5123 return error(GL_INVALID_VALUE);
5124 }
5125
Chris Forbes108f3e12018-08-30 19:41:59 -07005126 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005127
5128 if(context)
5129 {
5130 es2::Program *program = context->getCurrentProgram();
5131
5132 if(!program)
5133 {
5134 return error(GL_INVALID_OPERATION);
5135 }
5136
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005137 if(location == -1)
5138 {
5139 return;
5140 }
5141
Nicolas Capens0bac2852016-05-07 06:09:58 -04005142 if(!program->setUniform3fv(location, count, v))
5143 {
5144 return error(GL_INVALID_OPERATION);
5145 }
5146 }
5147}
5148
5149void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5150{
5151 GLint xyz[3] = {x, y, z};
5152
5153 glUniform3iv(location, 1, (GLint*)&xyz);
5154}
5155
5156void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5157{
5158 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5159
5160 if(count < 0)
5161 {
5162 return error(GL_INVALID_VALUE);
5163 }
5164
Chris Forbes108f3e12018-08-30 19:41:59 -07005165 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005166
5167 if(context)
5168 {
5169 es2::Program *program = context->getCurrentProgram();
5170
5171 if(!program)
5172 {
5173 return error(GL_INVALID_OPERATION);
5174 }
5175
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005176 if(location == -1)
5177 {
5178 return;
5179 }
5180
Nicolas Capens0bac2852016-05-07 06:09:58 -04005181 if(!program->setUniform3iv(location, count, v))
5182 {
5183 return error(GL_INVALID_OPERATION);
5184 }
5185 }
5186}
5187
5188void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5189{
5190 GLfloat xyzw[4] = {x, y, z, w};
5191
5192 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5193}
5194
5195void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5196{
5197 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5198
5199 if(count < 0)
5200 {
5201 return error(GL_INVALID_VALUE);
5202 }
5203
Chris Forbes108f3e12018-08-30 19:41:59 -07005204 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005205
5206 if(context)
5207 {
5208 es2::Program *program = context->getCurrentProgram();
5209
5210 if(!program)
5211 {
5212 return error(GL_INVALID_OPERATION);
5213 }
5214
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005215 if(location == -1)
5216 {
5217 return;
5218 }
5219
Nicolas Capens0bac2852016-05-07 06:09:58 -04005220 if(!program->setUniform4fv(location, count, v))
5221 {
5222 return error(GL_INVALID_OPERATION);
5223 }
5224 }
5225}
5226
5227void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5228{
5229 GLint xyzw[4] = {x, y, z, w};
5230
5231 glUniform4iv(location, 1, (GLint*)&xyzw);
5232}
5233
5234void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5235{
5236 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5237
5238 if(count < 0)
5239 {
5240 return error(GL_INVALID_VALUE);
5241 }
5242
Chris Forbes108f3e12018-08-30 19:41:59 -07005243 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005244
5245 if(context)
5246 {
5247 es2::Program *program = context->getCurrentProgram();
5248
5249 if(!program)
5250 {
5251 return error(GL_INVALID_OPERATION);
5252 }
5253
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005254 if(location == -1)
5255 {
5256 return;
5257 }
5258
Nicolas Capens0bac2852016-05-07 06:09:58 -04005259 if(!program->setUniform4iv(location, count, v))
5260 {
5261 return error(GL_INVALID_OPERATION);
5262 }
5263 }
5264}
5265
5266void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5267{
5268 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5269 location, count, transpose, value);
5270
5271 if(count < 0)
5272 {
5273 return error(GL_INVALID_VALUE);
5274 }
5275
Chris Forbes108f3e12018-08-30 19:41:59 -07005276 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005277
5278 if(context)
5279 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005280 es2::Program *program = context->getCurrentProgram();
5281
5282 if(!program)
5283 {
5284 return error(GL_INVALID_OPERATION);
5285 }
5286
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005287 if(location == -1)
5288 {
5289 return;
5290 }
5291
Nicolas Capens0bac2852016-05-07 06:09:58 -04005292 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5293 {
5294 return error(GL_INVALID_OPERATION);
5295 }
5296 }
5297}
5298
5299void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5300{
5301 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5302 location, count, transpose, value);
5303
5304 if(count < 0)
5305 {
5306 return error(GL_INVALID_VALUE);
5307 }
5308
Chris Forbes108f3e12018-08-30 19:41:59 -07005309 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005310
5311 if(context)
5312 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005313 es2::Program *program = context->getCurrentProgram();
5314
5315 if(!program)
5316 {
5317 return error(GL_INVALID_OPERATION);
5318 }
5319
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005320 if(location == -1)
5321 {
5322 return;
5323 }
5324
Nicolas Capens0bac2852016-05-07 06:09:58 -04005325 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5326 {
5327 return error(GL_INVALID_OPERATION);
5328 }
5329 }
5330}
5331
5332void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5333{
5334 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5335 location, count, transpose, value);
5336
5337 if(count < 0)
5338 {
5339 return error(GL_INVALID_VALUE);
5340 }
5341
Chris Forbes108f3e12018-08-30 19:41:59 -07005342 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005343
5344 if(context)
5345 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005346 es2::Program *program = context->getCurrentProgram();
5347
5348 if(!program)
5349 {
5350 return error(GL_INVALID_OPERATION);
5351 }
5352
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005353 if(location == -1)
5354 {
5355 return;
5356 }
5357
Nicolas Capens0bac2852016-05-07 06:09:58 -04005358 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5359 {
5360 return error(GL_INVALID_OPERATION);
5361 }
5362 }
5363}
5364
5365void UseProgram(GLuint program)
5366{
5367 TRACE("(GLuint program = %d)", program);
5368
Chris Forbes108f3e12018-08-30 19:41:59 -07005369 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005370
5371 if(context)
5372 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005373 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5374 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5375 {
5376 return error(GL_INVALID_OPERATION);
5377 }
5378
Nicolas Capens0bac2852016-05-07 06:09:58 -04005379 es2::Program *programObject = context->getProgram(program);
5380
5381 if(!programObject && program != 0)
5382 {
5383 if(context->getShader(program))
5384 {
5385 return error(GL_INVALID_OPERATION);
5386 }
5387 else
5388 {
5389 return error(GL_INVALID_VALUE);
5390 }
5391 }
5392
5393 if(program != 0 && !programObject->isLinked())
5394 {
5395 return error(GL_INVALID_OPERATION);
5396 }
5397
5398 context->useProgram(program);
5399 }
5400}
5401
5402void ValidateProgram(GLuint program)
5403{
5404 TRACE("(GLuint program = %d)", program);
5405
Chris Forbes108f3e12018-08-30 19:41:59 -07005406 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005407
5408 if(context)
5409 {
5410 es2::Program *programObject = context->getProgram(program);
5411
5412 if(!programObject)
5413 {
5414 if(context->getShader(program))
5415 {
5416 return error(GL_INVALID_OPERATION);
5417 }
5418 else
5419 {
5420 return error(GL_INVALID_VALUE);
5421 }
5422 }
5423
Ben Vanik1fd3b282017-07-10 14:08:12 -07005424 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005425 }
5426}
5427
5428void VertexAttrib1f(GLuint index, GLfloat x)
5429{
5430 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5431
5432 if(index >= es2::MAX_VERTEX_ATTRIBS)
5433 {
5434 return error(GL_INVALID_VALUE);
5435 }
5436
Chris Forbes108f3e12018-08-30 19:41:59 -07005437 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005438
5439 if(context)
5440 {
5441 GLfloat vals[4] = { x, 0, 0, 1 };
5442 context->setVertexAttrib(index, vals);
5443 }
5444}
5445
5446void VertexAttrib1fv(GLuint index, const GLfloat* values)
5447{
5448 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5449
5450 if(index >= es2::MAX_VERTEX_ATTRIBS)
5451 {
5452 return error(GL_INVALID_VALUE);
5453 }
5454
Chris Forbes108f3e12018-08-30 19:41:59 -07005455 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005456
5457 if(context)
5458 {
5459 GLfloat vals[4] = { values[0], 0, 0, 1 };
5460 context->setVertexAttrib(index, vals);
5461 }
5462}
5463
5464void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5465{
5466 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5467
5468 if(index >= es2::MAX_VERTEX_ATTRIBS)
5469 {
5470 return error(GL_INVALID_VALUE);
5471 }
5472
Chris Forbes108f3e12018-08-30 19:41:59 -07005473 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005474
5475 if(context)
5476 {
5477 GLfloat vals[4] = { x, y, 0, 1 };
5478 context->setVertexAttrib(index, vals);
5479 }
5480}
5481
5482void VertexAttrib2fv(GLuint index, const GLfloat* values)
5483{
5484 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5485
5486 if(index >= es2::MAX_VERTEX_ATTRIBS)
5487 {
5488 return error(GL_INVALID_VALUE);
5489 }
5490
Chris Forbes108f3e12018-08-30 19:41:59 -07005491 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005492
5493 if(context)
5494 {
5495 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5496 context->setVertexAttrib(index, vals);
5497 }
5498}
5499
5500void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5501{
5502 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5503
5504 if(index >= es2::MAX_VERTEX_ATTRIBS)
5505 {
5506 return error(GL_INVALID_VALUE);
5507 }
5508
Chris Forbes108f3e12018-08-30 19:41:59 -07005509 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005510
5511 if(context)
5512 {
5513 GLfloat vals[4] = { x, y, z, 1 };
5514 context->setVertexAttrib(index, vals);
5515 }
5516}
5517
5518void VertexAttrib3fv(GLuint index, const GLfloat* values)
5519{
5520 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5521
5522 if(index >= es2::MAX_VERTEX_ATTRIBS)
5523 {
5524 return error(GL_INVALID_VALUE);
5525 }
5526
Chris Forbes108f3e12018-08-30 19:41:59 -07005527 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005528
5529 if(context)
5530 {
5531 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5532 context->setVertexAttrib(index, vals);
5533 }
5534}
5535
5536void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5537{
5538 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5539
5540 if(index >= es2::MAX_VERTEX_ATTRIBS)
5541 {
5542 return error(GL_INVALID_VALUE);
5543 }
5544
Chris Forbes108f3e12018-08-30 19:41:59 -07005545 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005546
5547 if(context)
5548 {
5549 GLfloat vals[4] = { x, y, z, w };
5550 context->setVertexAttrib(index, vals);
5551 }
5552}
5553
5554void VertexAttrib4fv(GLuint index, const GLfloat* values)
5555{
5556 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5557
5558 if(index >= es2::MAX_VERTEX_ATTRIBS)
5559 {
5560 return error(GL_INVALID_VALUE);
5561 }
5562
Chris Forbes108f3e12018-08-30 19:41:59 -07005563 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005564
5565 if(context)
5566 {
5567 context->setVertexAttrib(index, values);
5568 }
5569}
5570
5571void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5572{
5573 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5574 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5575 index, size, type, normalized, stride, ptr);
5576
5577 if(index >= es2::MAX_VERTEX_ATTRIBS)
5578 {
5579 return error(GL_INVALID_VALUE);
5580 }
5581
5582 if(size < 1 || size > 4)
5583 {
5584 return error(GL_INVALID_VALUE);
5585 }
5586
Nicolas Capens0bac2852016-05-07 06:09:58 -04005587 switch(type)
5588 {
5589 case GL_BYTE:
5590 case GL_UNSIGNED_BYTE:
5591 case GL_SHORT:
5592 case GL_UNSIGNED_SHORT:
5593 case GL_FIXED:
5594 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005595 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005596 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005597 break;
5598 case GL_INT_2_10_10_10_REV:
5599 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005600 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005601 {
Nicolas Capens83463112018-06-12 23:55:16 -04005602 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005603 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005604 case GL_INT:
5605 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005606 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005607 default:
5608 return error(GL_INVALID_ENUM);
5609 }
5610
5611 if(stride < 0)
5612 {
5613 return error(GL_INVALID_VALUE);
5614 }
5615
Chris Forbes108f3e12018-08-30 19:41:59 -07005616 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005617
5618 if(context)
5619 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005620 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5621 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5622 {
5623 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5624 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5625 return error(GL_INVALID_OPERATION);
5626 }
5627
Alexis Hetu6f284032017-12-11 15:19:36 -05005628 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005629 }
5630}
5631
5632void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5633{
5634 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5635
5636 if(width < 0 || height < 0)
5637 {
5638 return error(GL_INVALID_VALUE);
5639 }
5640
Chris Forbes108f3e12018-08-30 19:41:59 -07005641 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005642
5643 if(context)
5644 {
5645 context->setViewportParams(x, y, width, height);
5646 }
5647}
5648
Alexis Hetub9dda642016-10-06 11:25:32 -04005649static void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter, bool allowPartialDepthStencilBlit)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005650{
5651 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5652 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5653 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5654 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5655
5656 switch(filter)
5657 {
5658 case GL_NEAREST:
5659 break;
5660 default:
5661 return error(GL_INVALID_ENUM);
5662 }
5663
5664 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5665 {
5666 return error(GL_INVALID_VALUE);
5667 }
5668
Chris Forbes108f3e12018-08-30 19:41:59 -07005669 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005670
5671 if(context)
5672 {
5673 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5674 {
5675 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5676 return error(GL_INVALID_OPERATION);
5677 }
5678
Alexis Hetub9dda642016-10-06 11:25:32 -04005679 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005680 }
5681}
5682
Alexis Hetub9dda642016-10-06 11:25:32 -04005683void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5684{
5685 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5686}
5687
Nicolas Capens0bac2852016-05-07 06:09:58 -04005688void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5689 GLbitfield mask, GLenum filter)
5690{
5691 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5692 {
5693 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5694 return error(GL_INVALID_OPERATION);
5695 }
5696
Alexis Hetub9dda642016-10-06 11:25:32 -04005697 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005698}
5699
5700void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005701 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005702{
5703 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5704 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005705 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5706 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005707
5708 switch(target)
5709 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005710 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005711 switch(format)
5712 {
5713 case GL_DEPTH_COMPONENT:
5714 case GL_DEPTH_STENCIL_OES:
5715 return error(GL_INVALID_OPERATION);
5716 default:
5717 break;
5718 }
5719 break;
5720 default:
5721 return error(GL_INVALID_ENUM);
5722 }
5723
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005724 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005725 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005726 return error(GL_INVALID_OPERATION);
5727 }
5728
Nicolas Capens83463112018-06-12 23:55:16 -04005729 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005730 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005731 {
5732 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005733 }
5734
5735 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5736 {
5737 return error(GL_INVALID_VALUE);
5738 }
5739
Nicolas Capensefdf1032018-05-08 16:03:16 -04005740 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005741 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5742 {
5743 return error(GL_INVALID_VALUE);
5744 }
5745
5746 if(border != 0)
5747 {
5748 return error(GL_INVALID_VALUE);
5749 }
5750
Chris Forbes108f3e12018-08-30 19:41:59 -07005751 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005752
5753 if(context)
5754 {
5755 es2::Texture3D *texture = context->getTexture3D();
5756
5757 if(!texture)
5758 {
5759 return error(GL_INVALID_OPERATION);
5760 }
5761
Nicolas Capens2fc90512018-01-23 22:24:22 +00005762 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005763 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005764 {
5765 return error(validationError);
5766 }
5767
Nicolas Capens894858a2018-03-22 00:55:23 -04005768 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005769 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005770 }
5771}
5772
Alexis Hetu53f48092016-06-17 14:08:06 -04005773void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005774{
5775 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5776 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005777 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5778 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005779
5780 switch(target)
5781 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005782 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005783 break;
5784 default:
5785 return error(GL_INVALID_ENUM);
5786 }
5787
Nicolas Capens0bac2852016-05-07 06:09:58 -04005788 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5789 {
5790 return error(GL_INVALID_VALUE);
5791 }
5792
5793 if((width < 0) || (height < 0) || (depth < 0))
5794 {
5795 return error(GL_INVALID_VALUE);
5796 }
5797
Chris Forbes108f3e12018-08-30 19:41:59 -07005798 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005799
5800 if(context)
5801 {
5802 es2::Texture3D *texture = context->getTexture3D();
5803
Nicolas Capens83463112018-06-12 23:55:16 -04005804 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005805 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005806 {
5807 return error(validationError);
5808 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005809
Nicolas Capens5555af42017-12-14 13:14:03 -05005810 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005811 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005812 {
5813 return error(validationError);
5814 }
5815
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005816 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005817 }
5818}
5819
5820void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5821{
5822 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5823 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5824 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5825
5826 switch(target)
5827 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005828 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005829 break;
5830 default:
5831 return error(GL_INVALID_ENUM);
5832 }
5833
5834 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5835 {
5836 return error(GL_INVALID_VALUE);
5837 }
5838
Chris Forbes108f3e12018-08-30 19:41:59 -07005839 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005840
5841 if(context)
5842 {
5843 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5844
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005845 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005846 {
5847 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5848 }
5849
5850 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5851
5852 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5853 {
5854 return error(GL_INVALID_OPERATION);
5855 }
5856
5857 es2::Texture3D *texture = context->getTexture3D();
5858
Nicolas Capens83463112018-06-12 23:55:16 -04005859 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005860 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005861 {
5862 return error(validationError);
5863 }
5864
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005865 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005866 }
5867}
5868
5869void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5870{
5871 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5872 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5873 target, level, internalformat, width, height, depth, border, imageSize, data);
5874
5875 switch(target)
5876 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005877 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005878 break;
5879 default:
5880 return error(GL_INVALID_ENUM);
5881 }
5882
5883 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5884 {
5885 return error(GL_INVALID_VALUE);
5886 }
5887
Nicolas Capensefdf1032018-05-08 16:03:16 -04005888 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005889 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5890 {
5891 return error(GL_INVALID_VALUE);
5892 }
5893
Nicolas Capens83463112018-06-12 23:55:16 -04005894 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005895 {
Nicolas Capens03589982018-02-01 17:28:32 -05005896 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005897 }
5898
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005899 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005900 {
5901 return error(GL_INVALID_VALUE);
5902 }
5903
Chris Forbes108f3e12018-08-30 19:41:59 -07005904 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005905
5906 if(context)
5907 {
5908 es2::Texture3D *texture = context->getTexture3D();
5909
5910 if(!texture)
5911 {
5912 return error(GL_INVALID_OPERATION);
5913 }
5914
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005915 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005916
Nicolas Capense65f5642018-02-26 17:47:06 -05005917 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005918 {
5919 return error(validationError);
5920 }
5921
Nicolas Capens0bac2852016-05-07 06:09:58 -04005922 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5923 }
5924}
5925
5926void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5927{
5928 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5929 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5930 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5931 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5932
5933 switch(target)
5934 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005935 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005936 break;
5937 default:
5938 return error(GL_INVALID_ENUM);
5939 }
5940
5941 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5942 {
5943 return error(GL_INVALID_VALUE);
5944 }
5945
5946 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5947 {
5948 return error(GL_INVALID_VALUE);
5949 }
5950
Nicolas Capens83463112018-06-12 23:55:16 -04005951 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005952 {
Nicolas Capens03589982018-02-01 17:28:32 -05005953 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005954 }
5955
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005956 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005957 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005958 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005959 }
5960
Chris Forbes108f3e12018-08-30 19:41:59 -07005961 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005962
5963 if(context)
5964 {
5965 es2::Texture3D *texture = context->getTexture3D();
5966
5967 if(!texture)
5968 {
5969 return error(GL_INVALID_OPERATION);
5970 }
5971
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005972 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005973 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005974 {
5975 return error(validationError);
5976 }
5977
5978 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005979 }
5980}
5981
5982void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5983{
5984 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5985 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5986
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005987 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005988 {
5989 return error(GL_INVALID_ENUM);
5990 }
5991
Chris Forbes108f3e12018-08-30 19:41:59 -07005992 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005993
5994 if(context)
5995 {
5996 if(texture == 0)
5997 {
5998 textarget = GL_NONE;
5999 }
6000 else
6001 {
6002 es2::Texture *tex = context->getTexture(texture);
6003
6004 if(!tex)
6005 {
6006 return error(GL_INVALID_OPERATION);
6007 }
6008
Nicolas Capens0bac2852016-05-07 06:09:58 -04006009 switch(textarget)
6010 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006011 case GL_TEXTURE_3D:
6012 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006013 {
6014 return error(GL_INVALID_OPERATION);
6015 }
6016 break;
6017 default:
6018 return error(GL_INVALID_ENUM);
6019 }
6020
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006021 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006022 {
6023 return error(GL_INVALID_VALUE);
6024 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006025
6026 if(tex->isCompressed(textarget, level))
6027 {
6028 return error(GL_INVALID_OPERATION);
6029 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006030 }
6031
6032 es2::Framebuffer *framebuffer = nullptr;
6033 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006034 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006035 {
6036 framebuffer = context->getReadFramebuffer();
6037 framebufferName = context->getReadFramebufferName();
6038 }
6039 else
6040 {
6041 framebuffer = context->getDrawFramebuffer();
6042 framebufferName = context->getDrawFramebufferName();
6043 }
6044
6045 if(framebufferName == 0 || !framebuffer)
6046 {
6047 return error(GL_INVALID_OPERATION);
6048 }
6049
Nicolas Capens0bac2852016-05-07 06:09:58 -04006050 switch(attachment)
6051 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006052 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6053 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006054 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006055 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6056 {
6057 return error(GL_INVALID_ENUM);
6058 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006059 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006060 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006061 }
6062 }
6063}
6064
6065void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6066{
6067 if(egl::getClientVersion() == 1)
6068 {
6069 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6070 }
6071
6072 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6073
6074 switch(target)
6075 {
6076 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006077 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006078 case GL_TEXTURE_EXTERNAL_OES:
6079 break;
6080 default:
6081 return error(GL_INVALID_ENUM);
6082 }
6083
Chris Forbes108f3e12018-08-30 19:41:59 -07006084 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006085
6086 if(context)
6087 {
Alexis Hetu46768622018-01-16 22:09:28 -05006088 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006089
6090 if(!texture)
6091 {
6092 return error(GL_INVALID_OPERATION);
6093 }
6094
Nicolas Capens58df2f62016-06-07 14:48:56 -04006095 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006096
Nicolas Capens58df2f62016-06-07 14:48:56 -04006097 if(!eglImage)
6098 {
6099 return error(GL_INVALID_OPERATION);
6100 }
6101
6102 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006103 }
6104}
6105
6106void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6107{
6108 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6109
6110 UNIMPLEMENTED();
6111}
6112
6113GLboolean IsRenderbufferOES(GLuint renderbuffer)
6114{
6115 return IsRenderbuffer(renderbuffer);
6116}
6117
6118void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6119{
6120 BindRenderbuffer(target, renderbuffer);
6121}
6122
6123void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6124{
6125 DeleteRenderbuffers(n, renderbuffers);
6126}
6127
6128void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6129{
6130 GenRenderbuffers(n, renderbuffers);
6131}
6132
6133void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6134{
6135 RenderbufferStorage(target, internalformat, width, height);
6136}
6137
6138void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6139{
6140 GetRenderbufferParameteriv(target, pname, params);
6141}
6142
6143GLboolean IsFramebufferOES(GLuint framebuffer)
6144{
6145 return IsFramebuffer(framebuffer);
6146}
6147
6148void BindFramebufferOES(GLenum target, GLuint framebuffer)
6149{
6150 BindFramebuffer(target, framebuffer);
6151}
6152
6153void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6154{
6155 DeleteFramebuffers(n, framebuffers);
6156}
6157
6158void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6159{
6160 GenFramebuffers(n, framebuffers);
6161}
6162
6163GLenum CheckFramebufferStatusOES(GLenum target)
6164{
6165 return CheckFramebufferStatus(target);
6166}
6167
6168void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6169{
6170 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6171}
6172
6173void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6174{
6175 FramebufferTexture2D(target, attachment, textarget, texture, level);
6176}
6177
6178void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6179{
6180 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6181}
6182
6183void GenerateMipmapOES(GLenum target)
6184{
6185 GenerateMipmap(target);
6186}
6187
6188void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6189{
6190 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6191
6192 if(n < 0 || n > MAX_DRAW_BUFFERS)
6193 {
6194 return error(GL_INVALID_VALUE);
6195 }
6196
Chris Forbes108f3e12018-08-30 19:41:59 -07006197 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006198
6199 if(context)
6200 {
6201 GLuint drawFramebufferName = context->getDrawFramebufferName();
6202
6203 if((drawFramebufferName == 0) && (n != 1))
6204 {
6205 return error(GL_INVALID_OPERATION);
6206 }
6207
6208 for(unsigned int i = 0; i < (unsigned)n; i++)
6209 {
6210 switch(bufs[i])
6211 {
6212 case GL_BACK:
6213 if(drawFramebufferName != 0)
6214 {
6215 return error(GL_INVALID_OPERATION);
6216 }
6217 break;
6218 case GL_NONE:
6219 break;
6220 case GL_COLOR_ATTACHMENT0_EXT:
6221 case GL_COLOR_ATTACHMENT1_EXT:
6222 case GL_COLOR_ATTACHMENT2_EXT:
6223 case GL_COLOR_ATTACHMENT3_EXT:
6224 case GL_COLOR_ATTACHMENT4_EXT:
6225 case GL_COLOR_ATTACHMENT5_EXT:
6226 case GL_COLOR_ATTACHMENT6_EXT:
6227 case GL_COLOR_ATTACHMENT7_EXT:
6228 case GL_COLOR_ATTACHMENT8_EXT:
6229 case GL_COLOR_ATTACHMENT9_EXT:
6230 case GL_COLOR_ATTACHMENT10_EXT:
6231 case GL_COLOR_ATTACHMENT11_EXT:
6232 case GL_COLOR_ATTACHMENT12_EXT:
6233 case GL_COLOR_ATTACHMENT13_EXT:
6234 case GL_COLOR_ATTACHMENT14_EXT:
6235 case GL_COLOR_ATTACHMENT15_EXT:
6236 {
6237 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6238
6239 if(index >= MAX_COLOR_ATTACHMENTS)
6240 {
6241 return error(GL_INVALID_OPERATION);
6242 }
6243
6244 if(index != i)
6245 {
6246 return error(GL_INVALID_OPERATION);
6247 }
6248
6249 if(drawFramebufferName == 0)
6250 {
6251 return error(GL_INVALID_OPERATION);
6252 }
6253 }
6254 break;
6255 default:
6256 return error(GL_INVALID_ENUM);
6257 }
6258 }
6259
6260 context->setFramebufferDrawBuffers(n, bufs);
6261 }
6262}
6263
6264}
6265
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006266extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006267{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006268 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006269 {
6270 const char *name;
6271 __eglMustCastToProperFunctionPointerType address;
6272 };
6273
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006274 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006275 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006276 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6277
6278 FUNCTION(glActiveTexture),
6279 FUNCTION(glAttachShader),
6280 FUNCTION(glBeginQuery),
6281 FUNCTION(glBeginQueryEXT),
6282 FUNCTION(glBeginTransformFeedback),
6283 FUNCTION(glBindAttribLocation),
6284 FUNCTION(glBindBuffer),
6285 FUNCTION(glBindBufferBase),
6286 FUNCTION(glBindBufferRange),
6287 FUNCTION(glBindFramebuffer),
6288 FUNCTION(glBindFramebufferOES),
6289 FUNCTION(glBindRenderbuffer),
6290 FUNCTION(glBindRenderbufferOES),
6291 FUNCTION(glBindSampler),
6292 FUNCTION(glBindTexture),
6293 FUNCTION(glBindTransformFeedback),
6294 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006295 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006296 FUNCTION(glBlendColor),
6297 FUNCTION(glBlendEquation),
6298 FUNCTION(glBlendEquationSeparate),
6299 FUNCTION(glBlendFunc),
6300 FUNCTION(glBlendFuncSeparate),
6301 FUNCTION(glBlitFramebuffer),
6302 FUNCTION(glBlitFramebufferANGLE),
6303 FUNCTION(glBufferData),
6304 FUNCTION(glBufferSubData),
6305 FUNCTION(glCheckFramebufferStatus),
6306 FUNCTION(glCheckFramebufferStatusOES),
6307 FUNCTION(glClear),
6308 FUNCTION(glClearBufferfi),
6309 FUNCTION(glClearBufferfv),
6310 FUNCTION(glClearBufferiv),
6311 FUNCTION(glClearBufferuiv),
6312 FUNCTION(glClearColor),
6313 FUNCTION(glClearDepthf),
6314 FUNCTION(glClearStencil),
6315 FUNCTION(glClientWaitSync),
6316 FUNCTION(glColorMask),
6317 FUNCTION(glCompileShader),
6318 FUNCTION(glCompressedTexImage2D),
6319 FUNCTION(glCompressedTexImage3D),
6320 FUNCTION(glCompressedTexSubImage2D),
6321 FUNCTION(glCompressedTexSubImage3D),
6322 FUNCTION(glCopyBufferSubData),
6323 FUNCTION(glCopyTexImage2D),
6324 FUNCTION(glCopyTexSubImage2D),
6325 FUNCTION(glCopyTexSubImage3D),
6326 FUNCTION(glCreateProgram),
6327 FUNCTION(glCreateShader),
6328 FUNCTION(glCullFace),
6329 FUNCTION(glDeleteBuffers),
6330 FUNCTION(glDeleteFencesNV),
6331 FUNCTION(glDeleteFramebuffers),
6332 FUNCTION(glDeleteFramebuffersOES),
6333 FUNCTION(glDeleteProgram),
6334 FUNCTION(glDeleteQueries),
6335 FUNCTION(glDeleteQueriesEXT),
6336 FUNCTION(glDeleteRenderbuffers),
6337 FUNCTION(glDeleteRenderbuffersOES),
6338 FUNCTION(glDeleteSamplers),
6339 FUNCTION(glDeleteShader),
6340 FUNCTION(glDeleteSync),
6341 FUNCTION(glDeleteTextures),
6342 FUNCTION(glDeleteTransformFeedbacks),
6343 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006344 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006345 FUNCTION(glDepthFunc),
Nicolas Capens659d89e2018-06-22 13:57:37 -04006346 //FUNCTION(DepthFunc),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006347 FUNCTION(glDepthMask),
6348 FUNCTION(glDepthRangef),
6349 FUNCTION(glDetachShader),
6350 FUNCTION(glDisable),
6351 FUNCTION(glDisableVertexAttribArray),
6352 FUNCTION(glDrawArrays),
6353 FUNCTION(glDrawArraysInstanced),
6354 FUNCTION(glDrawBuffers),
6355 FUNCTION(glDrawBuffersEXT),
6356 FUNCTION(glDrawElements),
6357 FUNCTION(glDrawElementsInstanced),
6358 FUNCTION(glDrawRangeElements),
6359 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6360 FUNCTION(glEGLImageTargetTexture2DOES),
6361 FUNCTION(glEnable),
6362 FUNCTION(glEnableVertexAttribArray),
6363 FUNCTION(glEndQuery),
6364 FUNCTION(glEndQueryEXT),
6365 FUNCTION(glEndTransformFeedback),
6366 FUNCTION(glFenceSync),
6367 FUNCTION(glFinish),
6368 FUNCTION(glFinishFenceNV),
6369 FUNCTION(glFlush),
6370 FUNCTION(glFlushMappedBufferRange),
6371 FUNCTION(glFramebufferRenderbuffer),
6372 FUNCTION(glFramebufferRenderbufferOES),
6373 FUNCTION(glFramebufferTexture2D),
6374 FUNCTION(glFramebufferTexture2DOES),
6375 FUNCTION(glFramebufferTextureLayer),
6376 FUNCTION(glFrontFace),
6377 FUNCTION(glGenBuffers),
6378 FUNCTION(glGenFencesNV),
6379 FUNCTION(glGenFramebuffers),
6380 FUNCTION(glGenFramebuffersOES),
6381 FUNCTION(glGenQueries),
6382 FUNCTION(glGenQueriesEXT),
6383 FUNCTION(glGenRenderbuffers),
6384 FUNCTION(glGenRenderbuffersOES),
6385 FUNCTION(glGenSamplers),
6386 FUNCTION(glGenTextures),
6387 FUNCTION(glGenTransformFeedbacks),
6388 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006389 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006390 FUNCTION(glGenerateMipmap),
6391 FUNCTION(glGenerateMipmapOES),
6392 FUNCTION(glGetActiveAttrib),
6393 FUNCTION(glGetActiveUniform),
6394 FUNCTION(glGetActiveUniformBlockName),
6395 FUNCTION(glGetActiveUniformBlockiv),
6396 FUNCTION(glGetActiveUniformsiv),
6397 FUNCTION(glGetAttachedShaders),
6398 FUNCTION(glGetAttribLocation),
6399 FUNCTION(glGetBooleanv),
6400 FUNCTION(glGetBufferParameteri64v),
6401 FUNCTION(glGetBufferParameteriv),
6402 FUNCTION(glGetBufferPointerv),
6403 FUNCTION(glGetError),
6404 FUNCTION(glGetFenceivNV),
6405 FUNCTION(glGetFloatv),
6406 FUNCTION(glGetFragDataLocation),
6407 FUNCTION(glGetFramebufferAttachmentParameteriv),
6408 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6409 FUNCTION(glGetGraphicsResetStatusEXT),
6410 FUNCTION(glGetInteger64i_v),
6411 FUNCTION(glGetInteger64v),
6412 FUNCTION(glGetIntegeri_v),
6413 FUNCTION(glGetIntegerv),
6414 FUNCTION(glGetInternalformativ),
6415 FUNCTION(glGetProgramBinary),
6416 FUNCTION(glGetProgramInfoLog),
6417 FUNCTION(glGetProgramiv),
6418 FUNCTION(glGetQueryObjectuiv),
6419 FUNCTION(glGetQueryObjectuivEXT),
6420 FUNCTION(glGetQueryiv),
6421 FUNCTION(glGetQueryivEXT),
6422 FUNCTION(glGetRenderbufferParameteriv),
6423 FUNCTION(glGetRenderbufferParameterivOES),
6424 FUNCTION(glGetSamplerParameterfv),
6425 FUNCTION(glGetSamplerParameteriv),
6426 FUNCTION(glGetShaderInfoLog),
6427 FUNCTION(glGetShaderPrecisionFormat),
6428 FUNCTION(glGetShaderSource),
6429 FUNCTION(glGetShaderiv),
6430 FUNCTION(glGetString),
6431 FUNCTION(glGetStringi),
6432 FUNCTION(glGetSynciv),
6433 FUNCTION(glGetTexParameterfv),
6434 FUNCTION(glGetTexParameteriv),
6435 FUNCTION(glGetTransformFeedbackVarying),
6436 FUNCTION(glGetUniformBlockIndex),
6437 FUNCTION(glGetUniformIndices),
6438 FUNCTION(glGetUniformLocation),
6439 FUNCTION(glGetUniformfv),
6440 FUNCTION(glGetUniformiv),
6441 FUNCTION(glGetUniformuiv),
6442 FUNCTION(glGetVertexAttribIiv),
6443 FUNCTION(glGetVertexAttribIuiv),
6444 FUNCTION(glGetVertexAttribPointerv),
6445 FUNCTION(glGetVertexAttribfv),
6446 FUNCTION(glGetVertexAttribiv),
6447 FUNCTION(glGetnUniformfvEXT),
6448 FUNCTION(glGetnUniformivEXT),
6449 FUNCTION(glHint),
6450 FUNCTION(glInvalidateFramebuffer),
6451 FUNCTION(glInvalidateSubFramebuffer),
6452 FUNCTION(glIsBuffer),
6453 FUNCTION(glIsEnabled),
6454 FUNCTION(glIsFenceNV),
6455 FUNCTION(glIsFramebuffer),
6456 FUNCTION(glIsFramebufferOES),
6457 FUNCTION(glIsProgram),
6458 FUNCTION(glIsQuery),
6459 FUNCTION(glIsQueryEXT),
6460 FUNCTION(glIsRenderbuffer),
6461 FUNCTION(glIsRenderbufferOES),
6462 FUNCTION(glIsSampler),
6463 FUNCTION(glIsShader),
6464 FUNCTION(glIsSync),
6465 FUNCTION(glIsTexture),
6466 FUNCTION(glIsTransformFeedback),
6467 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006468 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006469 FUNCTION(glLineWidth),
6470 FUNCTION(glLinkProgram),
6471 FUNCTION(glMapBufferRange),
6472 FUNCTION(glPauseTransformFeedback),
6473 FUNCTION(glPixelStorei),
6474 FUNCTION(glPolygonOffset),
6475 FUNCTION(glProgramBinary),
6476 FUNCTION(glProgramParameteri),
6477 FUNCTION(glReadBuffer),
6478 FUNCTION(glReadPixels),
6479 FUNCTION(glReadnPixelsEXT),
6480 FUNCTION(glReleaseShaderCompiler),
6481 FUNCTION(glRenderbufferStorage),
6482 FUNCTION(glRenderbufferStorageMultisample),
6483 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6484 FUNCTION(glRenderbufferStorageOES),
6485 FUNCTION(glResumeTransformFeedback),
6486 FUNCTION(glSampleCoverage),
6487 FUNCTION(glSamplerParameterf),
6488 FUNCTION(glSamplerParameterfv),
6489 FUNCTION(glSamplerParameteri),
6490 FUNCTION(glSamplerParameteriv),
6491 FUNCTION(glScissor),
6492 FUNCTION(glSetFenceNV),
6493 FUNCTION(glShaderBinary),
6494 FUNCTION(glShaderSource),
6495 FUNCTION(glStencilFunc),
6496 FUNCTION(glStencilFuncSeparate),
6497 FUNCTION(glStencilMask),
6498 FUNCTION(glStencilMaskSeparate),
6499 FUNCTION(glStencilOp),
6500 FUNCTION(glStencilOpSeparate),
6501 FUNCTION(glTestFenceNV),
6502 FUNCTION(glTexImage2D),
6503 FUNCTION(glTexImage3D),
6504 FUNCTION(glTexImage3DOES),
6505 FUNCTION(glTexParameterf),
6506 FUNCTION(glTexParameterfv),
6507 FUNCTION(glTexParameteri),
6508 FUNCTION(glTexParameteriv),
6509 FUNCTION(glTexStorage2D),
6510 FUNCTION(glTexStorage3D),
6511 FUNCTION(glTexSubImage2D),
6512 FUNCTION(glTexSubImage3D),
6513 FUNCTION(glTransformFeedbackVaryings),
6514 FUNCTION(glUniform1f),
6515 FUNCTION(glUniform1fv),
6516 FUNCTION(glUniform1i),
6517 FUNCTION(glUniform1iv),
6518 FUNCTION(glUniform1ui),
6519 FUNCTION(glUniform1uiv),
6520 FUNCTION(glUniform2f),
6521 FUNCTION(glUniform2fv),
6522 FUNCTION(glUniform2i),
6523 FUNCTION(glUniform2iv),
6524 FUNCTION(glUniform2ui),
6525 FUNCTION(glUniform2uiv),
6526 FUNCTION(glUniform3f),
6527 FUNCTION(glUniform3fv),
6528 FUNCTION(glUniform3i),
6529 FUNCTION(glUniform3iv),
6530 FUNCTION(glUniform3ui),
6531 FUNCTION(glUniform3uiv),
6532 FUNCTION(glUniform4f),
6533 FUNCTION(glUniform4fv),
6534 FUNCTION(glUniform4i),
6535 FUNCTION(glUniform4iv),
6536 FUNCTION(glUniform4ui),
6537 FUNCTION(glUniform4uiv),
6538 FUNCTION(glUniformBlockBinding),
6539 FUNCTION(glUniformMatrix2fv),
6540 FUNCTION(glUniformMatrix2x3fv),
6541 FUNCTION(glUniformMatrix2x4fv),
6542 FUNCTION(glUniformMatrix3fv),
6543 FUNCTION(glUniformMatrix3x2fv),
6544 FUNCTION(glUniformMatrix3x4fv),
6545 FUNCTION(glUniformMatrix4fv),
6546 FUNCTION(glUniformMatrix4x2fv),
6547 FUNCTION(glUniformMatrix4x3fv),
6548 FUNCTION(glUnmapBuffer),
6549 FUNCTION(glUseProgram),
6550 FUNCTION(glValidateProgram),
6551 FUNCTION(glVertexAttrib1f),
6552 FUNCTION(glVertexAttrib1fv),
6553 FUNCTION(glVertexAttrib2f),
6554 FUNCTION(glVertexAttrib2fv),
6555 FUNCTION(glVertexAttrib3f),
6556 FUNCTION(glVertexAttrib3fv),
6557 FUNCTION(glVertexAttrib4f),
6558 FUNCTION(glVertexAttrib4fv),
6559 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006560 FUNCTION(glVertexAttribDivisorANGLE),
6561 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006562 FUNCTION(glVertexAttribI4i),
6563 FUNCTION(glVertexAttribI4iv),
6564 FUNCTION(glVertexAttribI4ui),
6565 FUNCTION(glVertexAttribI4uiv),
6566 FUNCTION(glVertexAttribIPointer),
6567 FUNCTION(glVertexAttribPointer),
6568 FUNCTION(glViewport),
6569 FUNCTION(glWaitSync),
6570
6571 #undef FUNCTION
6572 };
6573
6574 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6575 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6576
Nicolas Capens48908cb2018-01-08 13:07:14 -05006577 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6578 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6579 #ifndef NDEBUG
6580 for(size_t i = 0; i < numFunctions - 1; i++)
6581 {
6582 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6583 }
6584 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006585
6586 if(procname && strncmp("gl", procname, 2) == 0)
6587 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006588 struct CompareFunctor
6589 {
6590 bool operator()(const Function &a, const Function &b) const
6591 {
6592 return strcmp(a.name, b.name) < 0;
6593 }
6594 };
6595
6596 Function needle;
6597 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006598 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006599
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006600 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006601 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006602 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006603 }
6604 }
6605
6606 return nullptr;
6607}