blob: d8a4a8fe1e202b5ebf68f672044bcc142d7f6138 [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 Capensa5dfd972018-09-28 15:27:08 -0400965 UNIMPLEMENTED("internalformat = %x, colorbufferFormat = %X", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500966
967 return error(GL_INVALID_OPERATION);
968 }
969 }
970
Nicolas Capens8f215a42018-02-02 13:25:53 -0500971 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400972 {
973 return;
974 }
975
Alexis Hetu46768622018-01-16 22:09:28 -0500976 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400977 {
Alexis Hetu46768622018-01-16 22:09:28 -0500978 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400979
980 if(!texture)
981 {
982 return error(GL_INVALID_OPERATION);
983 }
984
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500985 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400986 }
987 else if(es2::IsCubemapTextureTarget(target))
988 {
989 es2::TextureCubeMap *texture = context->getTextureCubeMap();
990
991 if(!texture)
992 {
993 return error(GL_INVALID_OPERATION);
994 }
995
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500996 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400997 }
998 else UNREACHABLE(target);
999 }
1000}
1001
1002void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1003{
1004 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1005 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1006 target, level, xoffset, yoffset, x, y, width, height);
1007
1008 if(!es2::IsTextureTarget(target))
1009 {
1010 return error(GL_INVALID_ENUM);
1011 }
1012
1013 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1014 {
1015 return error(GL_INVALID_VALUE);
1016 }
1017
1018 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1019 {
1020 return error(GL_INVALID_VALUE);
1021 }
1022
1023 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1024 {
1025 return error(GL_INVALID_VALUE);
1026 }
1027
Chris Forbes108f3e12018-08-30 19:41:59 -07001028 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001029
1030 if(context)
1031 {
1032 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1033
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001034 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001035 {
1036 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1037 }
1038
1039 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1040
1041 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1042 {
1043 return error(GL_INVALID_OPERATION);
1044 }
1045
1046 es2::Texture *texture = nullptr;
1047
Alexis Hetu46768622018-01-16 22:09:28 -05001048 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001049 {
Alexis Hetu46768622018-01-16 22:09:28 -05001050 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001051 }
1052 else if(es2::IsCubemapTextureTarget(target))
1053 {
1054 texture = context->getTextureCubeMap();
1055 }
1056 else UNREACHABLE(target);
1057
Nicolas Capens83463112018-06-12 23:55:16 -04001058 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001059 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001060 {
1061 return error(validationError);
1062 }
1063
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001064 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001065 }
1066}
1067
1068GLuint CreateProgram(void)
1069{
1070 TRACE("()");
1071
Chris Forbes108f3e12018-08-30 19:41:59 -07001072 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001073
1074 if(context)
1075 {
1076 return context->createProgram();
1077 }
1078
1079 return 0;
1080}
1081
1082GLuint CreateShader(GLenum type)
1083{
1084 TRACE("(GLenum type = 0x%X)", type);
1085
Chris Forbes108f3e12018-08-30 19:41:59 -07001086 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001087
1088 if(context)
1089 {
1090 switch(type)
1091 {
1092 case GL_FRAGMENT_SHADER:
1093 case GL_VERTEX_SHADER:
1094 return context->createShader(type);
1095 default:
1096 return error(GL_INVALID_ENUM, 0);
1097 }
1098 }
1099
1100 return 0;
1101}
1102
1103void CullFace(GLenum mode)
1104{
1105 TRACE("(GLenum mode = 0x%X)", mode);
1106
1107 switch(mode)
1108 {
1109 case GL_FRONT:
1110 case GL_BACK:
1111 case GL_FRONT_AND_BACK:
1112 {
Chris Forbes108f3e12018-08-30 19:41:59 -07001113 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001114
1115 if(context)
1116 {
1117 context->setCullMode(mode);
1118 }
1119 }
1120 break;
1121 default:
1122 return error(GL_INVALID_ENUM);
1123 }
1124}
1125
1126void DeleteBuffers(GLsizei n, const GLuint* buffers)
1127{
1128 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1129
1130 if(n < 0)
1131 {
1132 return error(GL_INVALID_VALUE);
1133 }
1134
Chris Forbes108f3e12018-08-30 19:41:59 -07001135 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001136
1137 if(context)
1138 {
1139 for(int i = 0; i < n; i++)
1140 {
1141 context->deleteBuffer(buffers[i]);
1142 }
1143 }
1144}
1145
1146void DeleteFencesNV(GLsizei n, const GLuint* fences)
1147{
1148 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1149
1150 if(n < 0)
1151 {
1152 return error(GL_INVALID_VALUE);
1153 }
1154
Chris Forbes108f3e12018-08-30 19:41:59 -07001155 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001156
1157 if(context)
1158 {
1159 for(int i = 0; i < n; i++)
1160 {
1161 context->deleteFence(fences[i]);
1162 }
1163 }
1164}
1165
1166void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1167{
1168 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1169
1170 if(n < 0)
1171 {
1172 return error(GL_INVALID_VALUE);
1173 }
1174
Chris Forbes108f3e12018-08-30 19:41:59 -07001175 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001176
1177 if(context)
1178 {
1179 for(int i = 0; i < n; i++)
1180 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001181 if(framebuffers[i] != 0) // Attempts to delete default framebuffer silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001182 {
1183 context->deleteFramebuffer(framebuffers[i]);
1184 }
1185 }
1186 }
1187}
1188
1189void DeleteProgram(GLuint program)
1190{
1191 TRACE("(GLuint program = %d)", program);
1192
1193 if(program == 0)
1194 {
1195 return;
1196 }
1197
Chris Forbes108f3e12018-08-30 19:41:59 -07001198 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001199
1200 if(context)
1201 {
1202 if(!context->getProgram(program))
1203 {
1204 if(context->getShader(program))
1205 {
1206 return error(GL_INVALID_OPERATION);
1207 }
1208 else
1209 {
1210 return error(GL_INVALID_VALUE);
1211 }
1212 }
1213
1214 context->deleteProgram(program);
1215 }
1216}
1217
1218void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1219{
1220 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1221
1222 if(n < 0)
1223 {
1224 return error(GL_INVALID_VALUE);
1225 }
1226
Chris Forbes108f3e12018-08-30 19:41:59 -07001227 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001228
1229 if(context)
1230 {
1231 for(int i = 0; i < n; i++)
1232 {
1233 context->deleteQuery(ids[i]);
1234 }
1235 }
1236}
1237
1238void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1239{
1240 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1241
1242 if(n < 0)
1243 {
1244 return error(GL_INVALID_VALUE);
1245 }
1246
Chris Forbes108f3e12018-08-30 19:41:59 -07001247 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001248
1249 if(context)
1250 {
1251 for(int i = 0; i < n; i++)
1252 {
1253 context->deleteRenderbuffer(renderbuffers[i]);
1254 }
1255 }
1256}
1257
1258void DeleteShader(GLuint shader)
1259{
1260 TRACE("(GLuint shader = %d)", shader);
1261
1262 if(shader == 0)
1263 {
1264 return;
1265 }
1266
Chris Forbes108f3e12018-08-30 19:41:59 -07001267 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001268
1269 if(context)
1270 {
1271 if(!context->getShader(shader))
1272 {
1273 if(context->getProgram(shader))
1274 {
1275 return error(GL_INVALID_OPERATION);
1276 }
1277 else
1278 {
1279 return error(GL_INVALID_VALUE);
1280 }
1281 }
1282
1283 context->deleteShader(shader);
1284 }
1285}
1286
1287void DeleteTextures(GLsizei n, const GLuint* textures)
1288{
1289 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1290
1291 if(n < 0)
1292 {
1293 return error(GL_INVALID_VALUE);
1294 }
1295
Chris Forbes108f3e12018-08-30 19:41:59 -07001296 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001297
1298 if(context)
1299 {
1300 for(int i = 0; i < n; i++)
1301 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001302 if(textures[i] != 0) // Attempts to delete default texture silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001303 {
1304 context->deleteTexture(textures[i]);
1305 }
1306 }
1307 }
1308}
1309
1310void DepthFunc(GLenum func)
1311{
1312 TRACE("(GLenum func = 0x%X)", func);
1313
1314 switch(func)
1315 {
1316 case GL_NEVER:
1317 case GL_ALWAYS:
1318 case GL_LESS:
1319 case GL_LEQUAL:
1320 case GL_EQUAL:
1321 case GL_GREATER:
1322 case GL_GEQUAL:
1323 case GL_NOTEQUAL:
1324 break;
1325 default:
1326 return error(GL_INVALID_ENUM);
1327 }
1328
Chris Forbes108f3e12018-08-30 19:41:59 -07001329 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001330
1331 if(context)
1332 {
1333 context->setDepthFunc(func);
1334 }
1335}
1336
1337void DepthMask(GLboolean flag)
1338{
1339 TRACE("(GLboolean flag = %d)", flag);
1340
Chris Forbes108f3e12018-08-30 19:41:59 -07001341 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001342
1343 if(context)
1344 {
1345 context->setDepthMask(flag != GL_FALSE);
1346 }
1347}
1348
1349void DepthRangef(GLclampf zNear, GLclampf zFar)
1350{
1351 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
1352
Chris Forbes108f3e12018-08-30 19:41:59 -07001353 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001354
1355 if(context)
1356 {
1357 context->setDepthRange(zNear, zFar);
1358 }
1359}
1360
1361void DetachShader(GLuint program, GLuint shader)
1362{
1363 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1364
Chris Forbes108f3e12018-08-30 19:41:59 -07001365 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001366
1367 if(context)
1368 {
1369
1370 es2::Program *programObject = context->getProgram(program);
1371 es2::Shader *shaderObject = context->getShader(shader);
1372
1373 if(!programObject)
1374 {
1375 es2::Shader *shaderByProgramHandle;
1376 shaderByProgramHandle = context->getShader(program);
1377 if(!shaderByProgramHandle)
1378 {
1379 return error(GL_INVALID_VALUE);
1380 }
1381 else
1382 {
1383 return error(GL_INVALID_OPERATION);
1384 }
1385 }
1386
1387 if(!shaderObject)
1388 {
1389 es2::Program *programByShaderHandle = context->getProgram(shader);
1390 if(!programByShaderHandle)
1391 {
1392 return error(GL_INVALID_VALUE);
1393 }
1394 else
1395 {
1396 return error(GL_INVALID_OPERATION);
1397 }
1398 }
1399
1400 if(!programObject->detachShader(shaderObject))
1401 {
1402 return error(GL_INVALID_OPERATION);
1403 }
1404 }
1405}
1406
1407void Disable(GLenum cap)
1408{
1409 TRACE("(GLenum cap = 0x%X)", cap);
1410
Chris Forbes108f3e12018-08-30 19:41:59 -07001411 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001412
1413 if(context)
1414 {
1415 switch(cap)
1416 {
1417 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1418 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1419 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1420 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1421 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1422 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1423 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1424 case GL_BLEND: context->setBlendEnabled(false); break;
1425 case GL_DITHER: context->setDitherEnabled(false); break;
1426 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1427 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1428 default:
1429 return error(GL_INVALID_ENUM);
1430 }
1431 }
1432}
1433
1434void DisableVertexAttribArray(GLuint index)
1435{
1436 TRACE("(GLuint index = %d)", index);
1437
1438 if(index >= es2::MAX_VERTEX_ATTRIBS)
1439 {
1440 return error(GL_INVALID_VALUE);
1441 }
1442
Chris Forbes108f3e12018-08-30 19:41:59 -07001443 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001444
1445 if(context)
1446 {
1447 context->setVertexAttribArrayEnabled(index, false);
1448 }
1449}
1450
1451void DrawArrays(GLenum mode, GLint first, GLsizei count)
1452{
1453 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1454
1455 switch(mode)
1456 {
1457 case GL_POINTS:
1458 case GL_LINES:
1459 case GL_LINE_LOOP:
1460 case GL_LINE_STRIP:
1461 case GL_TRIANGLES:
1462 case GL_TRIANGLE_FAN:
1463 case GL_TRIANGLE_STRIP:
1464 break;
1465 default:
1466 return error(GL_INVALID_ENUM);
1467 }
1468
1469 if(count < 0 || first < 0)
1470 {
1471 return error(GL_INVALID_VALUE);
1472 }
1473
Chris Forbes108f3e12018-08-30 19:41:59 -07001474 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001475
1476 if(context)
1477 {
1478 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1479 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1480 {
1481 return error(GL_INVALID_OPERATION);
1482 }
1483
1484 context->drawArrays(mode, first, count);
1485 }
1486}
1487
1488void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1489{
1490 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1491 mode, count, type, indices);
1492
1493 switch(mode)
1494 {
1495 case GL_POINTS:
1496 case GL_LINES:
1497 case GL_LINE_LOOP:
1498 case GL_LINE_STRIP:
1499 case GL_TRIANGLES:
1500 case GL_TRIANGLE_FAN:
1501 case GL_TRIANGLE_STRIP:
1502 break;
1503 default:
1504 return error(GL_INVALID_ENUM);
1505 }
1506
1507 if(count < 0)
1508 {
1509 return error(GL_INVALID_VALUE);
1510 }
1511
Chris Forbes108f3e12018-08-30 19:41:59 -07001512 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001513
1514 if(context)
1515 {
1516 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1517 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1518 {
1519 return error(GL_INVALID_OPERATION);
1520 }
1521
1522 switch(type)
1523 {
1524 case GL_UNSIGNED_BYTE:
1525 case GL_UNSIGNED_SHORT:
1526 case GL_UNSIGNED_INT:
1527 break;
1528 default:
1529 return error(GL_INVALID_ENUM);
1530 }
1531
1532 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1533 }
1534}
1535
1536void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1537{
1538 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1539 mode, first, count, instanceCount);
1540
1541 switch(mode)
1542 {
1543 case GL_POINTS:
1544 case GL_LINES:
1545 case GL_LINE_LOOP:
1546 case GL_LINE_STRIP:
1547 case GL_TRIANGLES:
1548 case GL_TRIANGLE_FAN:
1549 case GL_TRIANGLE_STRIP:
1550 break;
1551 default:
1552 return error(GL_INVALID_ENUM);
1553 }
1554
1555 if(count < 0 || instanceCount < 0)
1556 {
1557 return error(GL_INVALID_VALUE);
1558 }
1559
Chris Forbes108f3e12018-08-30 19:41:59 -07001560 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001561
1562 if(context)
1563 {
1564 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1565 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1566 {
1567 return error(GL_INVALID_OPERATION);
1568 }
1569
1570 context->drawArrays(mode, first, count, instanceCount);
1571 }
1572}
1573
1574void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1575{
1576 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1577 mode, count, type, indices, instanceCount);
1578
1579 switch(mode)
1580 {
1581 case GL_POINTS:
1582 case GL_LINES:
1583 case GL_LINE_LOOP:
1584 case GL_LINE_STRIP:
1585 case GL_TRIANGLES:
1586 case GL_TRIANGLE_FAN:
1587 case GL_TRIANGLE_STRIP:
1588 break;
1589 default:
1590 return error(GL_INVALID_ENUM);
1591 }
1592
1593 switch(type)
1594 {
1595 case GL_UNSIGNED_BYTE:
1596 case GL_UNSIGNED_SHORT:
1597 case GL_UNSIGNED_INT:
1598 break;
1599 default:
1600 return error(GL_INVALID_ENUM);
1601 }
1602
1603 if(count < 0 || instanceCount < 0)
1604 {
1605 return error(GL_INVALID_VALUE);
1606 }
1607
Chris Forbes108f3e12018-08-30 19:41:59 -07001608 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001609
1610 if(context)
1611 {
1612 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1613 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1614 {
1615 return error(GL_INVALID_OPERATION);
1616 }
1617
1618 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1619 }
1620}
1621
1622void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1623{
1624 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1625
Chris Forbes108f3e12018-08-30 19:41:59 -07001626 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001627
1628 if(context)
1629 {
1630 if(index >= es2::MAX_VERTEX_ATTRIBS)
1631 {
1632 return error(GL_INVALID_VALUE);
1633 }
1634
1635 context->setVertexAttribDivisor(index, divisor);
1636 }
1637}
1638
1639void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1640{
1641 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1642 mode, first, count, instanceCount);
1643
1644 switch(mode)
1645 {
1646 case GL_POINTS:
1647 case GL_LINES:
1648 case GL_LINE_LOOP:
1649 case GL_LINE_STRIP:
1650 case GL_TRIANGLES:
1651 case GL_TRIANGLE_FAN:
1652 case GL_TRIANGLE_STRIP:
1653 break;
1654 default:
1655 return error(GL_INVALID_ENUM);
1656 }
1657
1658 if(count < 0 || instanceCount < 0)
1659 {
1660 return error(GL_INVALID_VALUE);
1661 }
1662
Chris Forbes108f3e12018-08-30 19:41:59 -07001663 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001664
1665 if(context)
1666 {
1667 if(!context->hasZeroDivisor())
1668 {
1669 return error(GL_INVALID_OPERATION);
1670 }
1671
1672 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1673 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1674 {
1675 return error(GL_INVALID_OPERATION);
1676 }
1677
1678 context->drawArrays(mode, first, count, instanceCount);
1679 }
1680}
1681
1682void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1683{
1684 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1685 mode, count, type, indices, instanceCount);
1686
1687 switch(mode)
1688 {
1689 case GL_POINTS:
1690 case GL_LINES:
1691 case GL_LINE_LOOP:
1692 case GL_LINE_STRIP:
1693 case GL_TRIANGLES:
1694 case GL_TRIANGLE_FAN:
1695 case GL_TRIANGLE_STRIP:
1696 break;
1697 default:
1698 return error(GL_INVALID_ENUM);
1699 }
1700
1701 switch(type)
1702 {
1703 case GL_UNSIGNED_BYTE:
1704 case GL_UNSIGNED_SHORT:
1705 case GL_UNSIGNED_INT:
1706 break;
1707 default:
1708 return error(GL_INVALID_ENUM);
1709 }
1710
1711 if(count < 0 || instanceCount < 0)
1712 {
1713 return error(GL_INVALID_VALUE);
1714 }
1715
Chris Forbes108f3e12018-08-30 19:41:59 -07001716 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001717
1718 if(context)
1719 {
1720 if(!context->hasZeroDivisor())
1721 {
1722 return error(GL_INVALID_OPERATION);
1723 }
1724
1725 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1726 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1727 {
1728 return error(GL_INVALID_OPERATION);
1729 }
1730
1731 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1732 }
1733}
1734
1735void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1736{
1737 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1738
Chris Forbes108f3e12018-08-30 19:41:59 -07001739 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001740
1741 if(context)
1742 {
1743 if(index >= MAX_VERTEX_ATTRIBS)
1744 {
1745 return error(GL_INVALID_VALUE);
1746 }
1747
1748 context->setVertexAttribDivisor(index, divisor);
1749 }
1750}
1751
1752void Enable(GLenum cap)
1753{
1754 TRACE("(GLenum cap = 0x%X)", cap);
1755
Chris Forbes108f3e12018-08-30 19:41:59 -07001756 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001757
1758 if(context)
1759 {
1760 switch(cap)
1761 {
1762 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1763 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1764 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1765 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1766 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1767 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1768 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1769 case GL_BLEND: context->setBlendEnabled(true); break;
1770 case GL_DITHER: context->setDitherEnabled(true); break;
1771 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1772 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1773 default:
1774 return error(GL_INVALID_ENUM);
1775 }
1776 }
1777}
1778
1779void EnableVertexAttribArray(GLuint index)
1780{
1781 TRACE("(GLuint index = %d)", index);
1782
1783 if(index >= es2::MAX_VERTEX_ATTRIBS)
1784 {
1785 return error(GL_INVALID_VALUE);
1786 }
1787
Chris Forbes108f3e12018-08-30 19:41:59 -07001788 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001789
1790 if(context)
1791 {
1792 context->setVertexAttribArrayEnabled(index, true);
1793 }
1794}
1795
1796void EndQueryEXT(GLenum target)
1797{
1798 TRACE("GLenum target = 0x%X)", target);
1799
1800 switch(target)
1801 {
1802 case GL_ANY_SAMPLES_PASSED_EXT:
1803 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1804 break;
1805 default:
1806 return error(GL_INVALID_ENUM);
1807 }
1808
Chris Forbes108f3e12018-08-30 19:41:59 -07001809 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001810
1811 if(context)
1812 {
1813 context->endQuery(target);
1814 }
1815}
1816
1817void FinishFenceNV(GLuint fence)
1818{
1819 TRACE("(GLuint fence = %d)", fence);
1820
Chris Forbes108f3e12018-08-30 19:41:59 -07001821 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001822
1823 if(context)
1824 {
1825 es2::Fence *fenceObject = context->getFence(fence);
1826
1827 if(!fenceObject)
1828 {
1829 return error(GL_INVALID_OPERATION);
1830 }
1831
1832 fenceObject->finishFence();
1833 }
1834}
1835
1836void Finish(void)
1837{
1838 TRACE("()");
1839
Chris Forbes108f3e12018-08-30 19:41:59 -07001840 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001841
1842 if(context)
1843 {
1844 context->finish();
1845 }
1846}
1847
1848void Flush(void)
1849{
1850 TRACE("()");
1851
Chris Forbes108f3e12018-08-30 19:41:59 -07001852 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001853
1854 if(context)
1855 {
1856 context->flush();
1857 }
1858}
1859
1860void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1861{
1862 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1863 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1864
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001865 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001866 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1867 {
1868 return error(GL_INVALID_ENUM);
1869 }
1870
Chris Forbes108f3e12018-08-30 19:41:59 -07001871 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001872
1873 if(context)
1874 {
1875 es2::Framebuffer *framebuffer = nullptr;
1876 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001877 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001878 {
1879 framebuffer = context->getReadFramebuffer();
1880 framebufferName = context->getReadFramebufferName();
1881 }
1882 else
1883 {
1884 framebuffer = context->getDrawFramebuffer();
1885 framebufferName = context->getDrawFramebufferName();
1886 }
1887
1888 if(!framebuffer || framebufferName == 0)
1889 {
1890 return error(GL_INVALID_OPERATION);
1891 }
1892
1893 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1894 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1895 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1896 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1897 if(renderbuffer != 0)
1898 {
1899 if(!context->getRenderbuffer(renderbuffer))
1900 {
1901 return error(GL_INVALID_OPERATION);
1902 }
1903 }
1904
Nicolas Capens0bac2852016-05-07 06:09:58 -04001905 switch(attachment)
1906 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001907 case GL_DEPTH_ATTACHMENT:
1908 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1909 break;
1910 case GL_STENCIL_ATTACHMENT:
1911 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1912 break;
1913 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001914 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1915 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1916 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001917 default:
Nicolas Capens83463112018-06-12 23:55:16 -04001918 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1919 {
1920 return error(GL_INVALID_ENUM);
1921 }
1922 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1923 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001924 }
1925 }
1926}
1927
1928void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1929{
1930 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1931 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1932
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001933 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001934 {
1935 return error(GL_INVALID_ENUM);
1936 }
1937
Chris Forbes108f3e12018-08-30 19:41:59 -07001938 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001939
1940 if(context)
1941 {
1942 if(texture == 0)
1943 {
1944 textarget = GL_NONE;
1945 }
1946 else
1947 {
1948 es2::Texture *tex = context->getTexture(texture);
1949
1950 if(!tex)
1951 {
1952 return error(GL_INVALID_OPERATION);
1953 }
1954
1955 switch(textarget)
1956 {
1957 case GL_TEXTURE_2D:
1958 if(tex->getTarget() != GL_TEXTURE_2D)
1959 {
1960 return error(GL_INVALID_OPERATION);
1961 }
1962 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001963 case GL_TEXTURE_RECTANGLE_ARB:
1964 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1965 {
1966 return error(GL_INVALID_OPERATION);
1967 }
1968 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001969 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1970 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1971 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1972 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1973 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1974 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1975 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1976 {
1977 return error(GL_INVALID_OPERATION);
1978 }
1979 break;
1980 default:
1981 return error(GL_INVALID_ENUM);
1982 }
1983
Nicolas Capens83463112018-06-12 23:55:16 -04001984 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001985 {
1986 return error(GL_INVALID_VALUE);
1987 }
1988
1989 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1990 {
1991 return error(GL_INVALID_VALUE);
1992 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04001993
1994 if(tex->isCompressed(textarget, level))
1995 {
1996 return error(GL_INVALID_OPERATION);
1997 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001998 }
1999
2000 es2::Framebuffer *framebuffer = nullptr;
2001 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002002 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002003 {
2004 framebuffer = context->getReadFramebuffer();
2005 framebufferName = context->getReadFramebufferName();
2006 }
2007 else
2008 {
2009 framebuffer = context->getDrawFramebuffer();
2010 framebufferName = context->getDrawFramebufferName();
2011 }
2012
2013 if(framebufferName == 0 || !framebuffer)
2014 {
2015 return error(GL_INVALID_OPERATION);
2016 }
2017
2018 switch(attachment)
2019 {
Nicolas Capens83463112018-06-12 23:55:16 -04002020 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2021 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2022 case GL_DEPTH_STENCIL_ATTACHMENT:
2023 framebuffer->setDepthbuffer(textarget, texture, level);
2024 framebuffer->setStencilbuffer(textarget, texture, level);
2025 break;
2026 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002027 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2028 {
2029 return error(GL_INVALID_ENUM);
2030 }
2031 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2032 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002033 }
2034 }
2035}
2036
2037void FrontFace(GLenum mode)
2038{
2039 TRACE("(GLenum mode = 0x%X)", mode);
2040
2041 switch(mode)
2042 {
2043 case GL_CW:
2044 case GL_CCW:
2045 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002046 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002047
2048 if(context)
2049 {
2050 context->setFrontFace(mode);
2051 }
2052 }
2053 break;
2054 default:
2055 return error(GL_INVALID_ENUM);
2056 }
2057}
2058
2059void GenBuffers(GLsizei n, GLuint* buffers)
2060{
2061 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2062
2063 if(n < 0)
2064 {
2065 return error(GL_INVALID_VALUE);
2066 }
2067
Chris Forbes108f3e12018-08-30 19:41:59 -07002068 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002069
2070 if(context)
2071 {
2072 for(int i = 0; i < n; i++)
2073 {
2074 buffers[i] = context->createBuffer();
2075 }
2076 }
2077}
2078
2079void GenerateMipmap(GLenum target)
2080{
2081 TRACE("(GLenum target = 0x%X)", target);
2082
Chris Forbes108f3e12018-08-30 19:41:59 -07002083 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002084
2085 if(context)
2086 {
2087 es2::Texture *texture = nullptr;
2088
Nicolas Capens0bac2852016-05-07 06:09:58 -04002089 switch(target)
2090 {
2091 case GL_TEXTURE_2D:
2092 texture = context->getTexture2D();
2093 break;
2094 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002095 {
2096 TextureCubeMap *cube = context->getTextureCubeMap();
2097 texture = cube;
2098
2099 if(!cube->isCubeComplete())
2100 {
2101 return error(GL_INVALID_OPERATION);
2102 }
2103 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002104 break;
2105 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002106 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002107 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002108 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002109 texture = context->getTexture3D();
2110 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002111 case GL_TEXTURE_RECTANGLE_ARB:
2112 texture = context->getTexture2DRect();
2113 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002114 default:
2115 return error(GL_INVALID_ENUM);
2116 }
2117
Nicolas Capens83463112018-06-12 23:55:16 -04002118 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002119 {
2120 return error(GL_INVALID_OPERATION);
2121 }
2122
Nicolas Capens0bac2852016-05-07 06:09:58 -04002123 texture->generateMipmaps();
2124 }
2125}
2126
2127void GenFencesNV(GLsizei n, GLuint* fences)
2128{
2129 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2130
2131 if(n < 0)
2132 {
2133 return error(GL_INVALID_VALUE);
2134 }
2135
Chris Forbes108f3e12018-08-30 19:41:59 -07002136 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002137
2138 if(context)
2139 {
2140 for(int i = 0; i < n; i++)
2141 {
2142 fences[i] = context->createFence();
2143 }
2144 }
2145}
2146
2147void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2148{
2149 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2150
2151 if(n < 0)
2152 {
2153 return error(GL_INVALID_VALUE);
2154 }
2155
Chris Forbes108f3e12018-08-30 19:41:59 -07002156 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002157
2158 if(context)
2159 {
2160 for(int i = 0; i < n; i++)
2161 {
2162 framebuffers[i] = context->createFramebuffer();
2163 }
2164 }
2165}
2166
2167void GenQueriesEXT(GLsizei n, GLuint* ids)
2168{
2169 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2170
2171 if(n < 0)
2172 {
2173 return error(GL_INVALID_VALUE);
2174 }
2175
Chris Forbes108f3e12018-08-30 19:41:59 -07002176 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002177
2178 if(context)
2179 {
2180 for(int i = 0; i < n; i++)
2181 {
2182 ids[i] = context->createQuery();
2183 }
2184 }
2185}
2186
2187void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2188{
2189 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2190
2191 if(n < 0)
2192 {
2193 return error(GL_INVALID_VALUE);
2194 }
2195
Chris Forbes108f3e12018-08-30 19:41:59 -07002196 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002197
2198 if(context)
2199 {
2200 for(int i = 0; i < n; i++)
2201 {
2202 renderbuffers[i] = context->createRenderbuffer();
2203 }
2204 }
2205}
2206
2207void GenTextures(GLsizei n, GLuint* textures)
2208{
2209 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2210
2211 if(n < 0)
2212 {
2213 return error(GL_INVALID_VALUE);
2214 }
2215
Chris Forbes108f3e12018-08-30 19:41:59 -07002216 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002217
2218 if(context)
2219 {
2220 for(int i = 0; i < n; i++)
2221 {
2222 textures[i] = context->createTexture();
2223 }
2224 }
2225}
2226
2227void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2228{
2229 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2230 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2231 program, index, bufsize, length, size, type, name);
2232
2233 if(bufsize < 0)
2234 {
2235 return error(GL_INVALID_VALUE);
2236 }
2237
Chris Forbes108f3e12018-08-30 19:41:59 -07002238 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002239
2240 if(context)
2241 {
2242 es2::Program *programObject = context->getProgram(program);
2243
2244 if(!programObject)
2245 {
2246 if(context->getShader(program))
2247 {
2248 return error(GL_INVALID_OPERATION);
2249 }
2250 else
2251 {
2252 return error(GL_INVALID_VALUE);
2253 }
2254 }
2255
2256 if(index >= programObject->getActiveAttributeCount())
2257 {
2258 return error(GL_INVALID_VALUE);
2259 }
2260
2261 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2262 }
2263}
2264
2265void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2266{
2267 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2268 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2269 program, index, bufsize, length, size, type, name);
2270
2271 if(bufsize < 0)
2272 {
2273 return error(GL_INVALID_VALUE);
2274 }
2275
Chris Forbes108f3e12018-08-30 19:41:59 -07002276 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002277
2278 if(context)
2279 {
2280 es2::Program *programObject = context->getProgram(program);
2281
2282 if(!programObject)
2283 {
2284 if(context->getShader(program))
2285 {
2286 return error(GL_INVALID_OPERATION);
2287 }
2288 else
2289 {
2290 return error(GL_INVALID_VALUE);
2291 }
2292 }
2293
2294 if(index >= programObject->getActiveUniformCount())
2295 {
2296 return error(GL_INVALID_VALUE);
2297 }
2298
2299 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2300 }
2301}
2302
2303void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2304{
2305 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2306 program, maxcount, count, shaders);
2307
2308 if(maxcount < 0)
2309 {
2310 return error(GL_INVALID_VALUE);
2311 }
2312
Chris Forbes108f3e12018-08-30 19:41:59 -07002313 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002314
2315 if(context)
2316 {
2317 es2::Program *programObject = context->getProgram(program);
2318
2319 if(!programObject)
2320 {
2321 if(context->getShader(program))
2322 {
2323 return error(GL_INVALID_OPERATION);
2324 }
2325 else
2326 {
2327 return error(GL_INVALID_VALUE);
2328 }
2329 }
2330
2331 return programObject->getAttachedShaders(maxcount, count, shaders);
2332 }
2333}
2334
2335int GetAttribLocation(GLuint program, const GLchar* name)
2336{
2337 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2338
Chris Forbes108f3e12018-08-30 19:41:59 -07002339 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002340
2341 if(context)
2342 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002343 es2::Program *programObject = context->getProgram(program);
2344
2345 if(!programObject)
2346 {
2347 if(context->getShader(program))
2348 {
2349 return error(GL_INVALID_OPERATION, -1);
2350 }
2351 else
2352 {
2353 return error(GL_INVALID_VALUE, -1);
2354 }
2355 }
2356
2357 if(!programObject->isLinked())
2358 {
2359 return error(GL_INVALID_OPERATION, -1);
2360 }
2361
2362 return programObject->getAttributeLocation(name);
2363 }
2364
2365 return -1;
2366}
2367
2368void GetBooleanv(GLenum pname, GLboolean* params)
2369{
2370 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2371
Chris Forbes108f3e12018-08-30 19:41:59 -07002372 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002373
2374 if(context)
2375 {
2376 if(!(context->getBooleanv(pname, params)))
2377 {
2378 GLenum nativeType;
2379 unsigned int numParams = 0;
2380 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2381 return error(GL_INVALID_ENUM);
2382
2383 if(numParams == 0)
2384 return; // it is known that the pname is valid, but there are no parameters to return
2385
2386 if(nativeType == GL_FLOAT)
2387 {
2388 GLfloat *floatParams = nullptr;
2389 floatParams = new GLfloat[numParams];
2390
2391 context->getFloatv(pname, floatParams);
2392
2393 for(unsigned int i = 0; i < numParams; ++i)
2394 {
2395 if(floatParams[i] == 0.0f)
2396 params[i] = GL_FALSE;
2397 else
2398 params[i] = GL_TRUE;
2399 }
2400
2401 delete [] floatParams;
2402 }
2403 else if(nativeType == GL_INT)
2404 {
2405 GLint *intParams = nullptr;
2406 intParams = new GLint[numParams];
2407
2408 context->getIntegerv(pname, intParams);
2409
2410 for(unsigned int i = 0; i < numParams; ++i)
2411 {
2412 if(intParams[i] == 0)
2413 params[i] = GL_FALSE;
2414 else
2415 params[i] = GL_TRUE;
2416 }
2417
2418 delete [] intParams;
2419 }
2420 }
2421 }
2422}
2423
2424void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2425{
2426 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2427
Chris Forbes108f3e12018-08-30 19:41:59 -07002428 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002429
2430 if(context)
2431 {
2432 es2::Buffer *buffer;
2433 if(!context->getBuffer(target, &buffer))
2434 {
2435 return error(GL_INVALID_ENUM);
2436 }
2437
2438 if(!buffer)
2439 {
2440 // A null buffer means that "0" is bound to the requested buffer target
2441 return error(GL_INVALID_OPERATION);
2442 }
2443
Nicolas Capens0bac2852016-05-07 06:09:58 -04002444 switch(pname)
2445 {
2446 case GL_BUFFER_USAGE:
2447 *params = buffer->usage();
2448 break;
2449 case GL_BUFFER_SIZE:
2450 *params = (GLint)buffer->size();
2451 break;
2452 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002453 *params = buffer->access();
2454 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002455 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002456 *params = buffer->isMapped();
2457 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002458 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002459 *params = (GLint)buffer->length();
2460 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002461 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002462 *params = (GLint)buffer->offset();
2463 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002464 default:
2465 return error(GL_INVALID_ENUM);
2466 }
2467 }
2468}
2469
2470GLenum GetError(void)
2471{
2472 TRACE("()");
2473
Chris Forbes108f3e12018-08-30 19:41:59 -07002474 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002475
2476 if(context)
2477 {
2478 return context->getError();
2479 }
2480
2481 return GL_NO_ERROR;
2482}
2483
2484void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2485{
2486 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2487
Chris Forbes108f3e12018-08-30 19:41:59 -07002488 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002489
2490 if(context)
2491 {
2492 es2::Fence *fenceObject = context->getFence(fence);
2493
2494 if(!fenceObject)
2495 {
2496 return error(GL_INVALID_OPERATION);
2497 }
2498
2499 fenceObject->getFenceiv(pname, params);
2500 }
2501}
2502
2503void GetFloatv(GLenum pname, GLfloat* params)
2504{
2505 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2506
Chris Forbes108f3e12018-08-30 19:41:59 -07002507 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002508
2509 if(context)
2510 {
2511 if(!(context->getFloatv(pname, params)))
2512 {
2513 GLenum nativeType;
2514 unsigned int numParams = 0;
2515 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2516 return error(GL_INVALID_ENUM);
2517
2518 if(numParams == 0)
2519 return; // it is known that the pname is valid, but that there are no parameters to return.
2520
2521 if(nativeType == GL_BOOL)
2522 {
2523 GLboolean *boolParams = nullptr;
2524 boolParams = new GLboolean[numParams];
2525
2526 context->getBooleanv(pname, boolParams);
2527
2528 for(unsigned int i = 0; i < numParams; ++i)
2529 {
2530 if(boolParams[i] == GL_FALSE)
2531 params[i] = 0.0f;
2532 else
2533 params[i] = 1.0f;
2534 }
2535
2536 delete [] boolParams;
2537 }
2538 else if(nativeType == GL_INT)
2539 {
2540 GLint *intParams = nullptr;
2541 intParams = new GLint[numParams];
2542
2543 context->getIntegerv(pname, intParams);
2544
2545 for(unsigned int i = 0; i < numParams; ++i)
2546 {
2547 params[i] = (GLfloat)intParams[i];
2548 }
2549
2550 delete [] intParams;
2551 }
2552 }
2553 }
2554}
2555
2556void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2557{
2558 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2559 target, attachment, pname, params);
2560
Chris Forbes108f3e12018-08-30 19:41:59 -07002561 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002562
2563 if(context)
2564 {
2565 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2566 {
2567 return error(GL_INVALID_ENUM);
2568 }
2569
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002570 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002571
Nicolas Capens0bac2852016-05-07 06:09:58 -04002572 if(target == GL_READ_FRAMEBUFFER)
2573 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002574 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002575 }
2576 else
2577 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002578 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002579 }
2580
Nicolas Capens0bac2852016-05-07 06:09:58 -04002581 switch(attachment)
2582 {
2583 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002584 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002585 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002586 if(framebufferName != 0)
2587 {
2588 return error(GL_INVALID_OPERATION);
2589 }
2590 break;
2591 case GL_DEPTH_ATTACHMENT:
2592 case GL_STENCIL_ATTACHMENT:
2593 if(framebufferName == 0)
2594 {
2595 return error(GL_INVALID_OPERATION);
2596 }
2597 break;
2598 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002599 if(framebufferName == 0)
2600 {
2601 return error(GL_INVALID_OPERATION);
2602 }
2603 break;
2604 default:
2605 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2606 {
2607 if(framebufferName == 0)
2608 {
2609 return error(GL_INVALID_OPERATION);
2610 }
2611 }
2612 else return error(GL_INVALID_ENUM);
2613 }
2614
2615 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2616
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002617 if(!framebuffer)
2618 {
2619 return error(GL_INVALID_OPERATION);
2620 }
2621
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002622 GLenum attachmentType;
2623 GLuint attachmentHandle;
2624 GLint attachmentLayer;
2625 Renderbuffer *renderbuffer = nullptr;
2626 switch(attachment)
2627 {
2628 case GL_BACK:
2629 attachmentType = framebuffer->getColorbufferType(0);
2630 attachmentHandle = framebuffer->getColorbufferName(0);
2631 attachmentLayer = framebuffer->getColorbufferLayer(0);
2632 renderbuffer = framebuffer->getColorbuffer(0);
2633 break;
2634 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002635 case GL_DEPTH_ATTACHMENT:
2636 attachmentType = framebuffer->getDepthbufferType();
2637 attachmentHandle = framebuffer->getDepthbufferName();
2638 attachmentLayer = framebuffer->getDepthbufferLayer();
2639 renderbuffer = framebuffer->getDepthbuffer();
2640 break;
2641 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002642 case GL_STENCIL_ATTACHMENT:
2643 attachmentType = framebuffer->getStencilbufferType();
2644 attachmentHandle = framebuffer->getStencilbufferName();
2645 attachmentLayer = framebuffer->getStencilbufferLayer();
2646 renderbuffer = framebuffer->getStencilbuffer();
2647 break;
2648 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002649 attachmentType = framebuffer->getDepthbufferType();
2650 attachmentHandle = framebuffer->getDepthbufferName();
2651 attachmentLayer = framebuffer->getDepthbufferLayer();
2652 renderbuffer = framebuffer->getDepthbuffer();
2653
2654 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002655 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002656 // Different attachments to DEPTH and STENCIL, query fails
2657 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002658 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002659 break;
2660 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002661 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2662 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2663 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2664 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2665 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2666 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002667 }
2668
2669 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002670 if(framebufferName == 0)
2671 {
2672 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2673 }
2674 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002675 {
2676 attachmentObjectType = attachmentType;
2677 }
2678 else if(es2::IsTextureTarget(attachmentType))
2679 {
2680 attachmentObjectType = GL_TEXTURE;
2681 }
2682 else UNREACHABLE(attachmentType);
2683
2684 if(attachmentObjectType != GL_NONE)
2685 {
2686 switch(pname)
2687 {
2688 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2689 *params = attachmentObjectType;
2690 break;
2691 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002692 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002693 {
2694 *params = attachmentHandle;
2695 }
2696 else
2697 {
2698 return error(GL_INVALID_ENUM);
2699 }
2700 break;
2701 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2702 if(attachmentObjectType == GL_TEXTURE)
2703 {
Nicolas Capens83463112018-06-12 23:55:16 -04002704 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002705 }
2706 else
2707 {
2708 return error(GL_INVALID_ENUM);
2709 }
2710 break;
2711 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2712 if(attachmentObjectType == GL_TEXTURE)
2713 {
2714 if(es2::IsCubemapTextureTarget(attachmentType))
2715 {
2716 *params = attachmentType;
2717 }
2718 else
2719 {
2720 *params = 0;
2721 }
2722 }
2723 else
2724 {
2725 return error(GL_INVALID_ENUM);
2726 }
2727 break;
2728 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002729 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002730 break;
2731 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002732 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002733 break;
2734 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002735 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002736 break;
2737 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002738 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002739 break;
2740 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002741 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002742 break;
2743 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002744 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002745 break;
2746 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002747 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002748 break;
2749 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002750 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2751 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002752 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002753 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002754 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002755
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002756 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002757 break;
2758 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002759 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002760 break;
2761 default:
2762 return error(GL_INVALID_ENUM);
2763 }
2764 }
2765 else
2766 {
2767 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2768 // is NONE, then querying any other pname will generate INVALID_ENUM.
2769
2770 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2771 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2772 // INVALID_OPERATION for all other pnames
2773
2774 switch(pname)
2775 {
2776 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2777 *params = GL_NONE;
2778 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002779 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002780 *params = 0;
2781 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002782 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002783 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002784 }
2785 }
2786 }
2787}
2788
2789GLenum GetGraphicsResetStatusEXT(void)
2790{
2791 TRACE("()");
2792
2793 return GL_NO_ERROR;
2794}
2795
2796void GetIntegerv(GLenum pname, GLint* params)
2797{
2798 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2799
Chris Forbes108f3e12018-08-30 19:41:59 -07002800 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002801
2802 if(!context)
2803 {
2804 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002805 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002806
2807 // This is not spec compliant! When there is no current GL context, functions should
2808 // have no side effects. Google Maps queries these values before creating a context,
2809 // so we need this as a bug-compatible workaround.
2810 switch(pname)
2811 {
2812 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2813 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2814 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2815 case GL_STENCIL_BITS: *params = 8; return;
2816 case GL_ALIASED_LINE_WIDTH_RANGE:
2817 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2818 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2819 return;
2820 }
2821 }
2822
2823 if(context)
2824 {
2825 if(!(context->getIntegerv(pname, params)))
2826 {
2827 GLenum nativeType;
2828 unsigned int numParams = 0;
2829 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2830 return error(GL_INVALID_ENUM);
2831
2832 if(numParams == 0)
2833 return; // it is known that pname is valid, but there are no parameters to return
2834
2835 if(nativeType == GL_BOOL)
2836 {
2837 GLboolean *boolParams = nullptr;
2838 boolParams = new GLboolean[numParams];
2839
2840 context->getBooleanv(pname, boolParams);
2841
2842 for(unsigned int i = 0; i < numParams; ++i)
2843 {
2844 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2845 }
2846
2847 delete [] boolParams;
2848 }
2849 else if(nativeType == GL_FLOAT)
2850 {
2851 GLfloat *floatParams = nullptr;
2852 floatParams = new GLfloat[numParams];
2853
2854 context->getFloatv(pname, floatParams);
2855
2856 for(unsigned int i = 0; i < numParams; ++i)
2857 {
2858 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2859 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002860 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002861 }
2862 else
2863 {
2864 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2865 }
2866 }
2867
2868 delete [] floatParams;
2869 }
2870 }
2871 }
2872}
2873
2874void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2875{
2876 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2877
Chris Forbes108f3e12018-08-30 19:41:59 -07002878 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002879
2880 if(context)
2881 {
2882 es2::Program *programObject = context->getProgram(program);
2883
2884 if(!programObject)
2885 {
2886 if(context->getShader(program))
2887 {
2888 return error(GL_INVALID_OPERATION);
2889 }
2890 else
2891 {
2892 return error(GL_INVALID_VALUE);
2893 }
2894 }
2895
Nicolas Capens0bac2852016-05-07 06:09:58 -04002896 switch(pname)
2897 {
2898 case GL_DELETE_STATUS:
2899 *params = programObject->isFlaggedForDeletion();
2900 return;
2901 case GL_LINK_STATUS:
2902 *params = programObject->isLinked();
2903 return;
2904 case GL_VALIDATE_STATUS:
2905 *params = programObject->isValidated();
2906 return;
2907 case GL_INFO_LOG_LENGTH:
2908 *params = (GLint)programObject->getInfoLogLength();
2909 return;
2910 case GL_ATTACHED_SHADERS:
2911 *params = programObject->getAttachedShadersCount();
2912 return;
2913 case GL_ACTIVE_ATTRIBUTES:
2914 *params = (GLint)programObject->getActiveAttributeCount();
2915 return;
2916 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2917 *params = programObject->getActiveAttributeMaxLength();
2918 return;
2919 case GL_ACTIVE_UNIFORMS:
2920 *params = (GLint)programObject->getActiveUniformCount();
2921 return;
2922 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2923 *params = programObject->getActiveUniformMaxLength();
2924 return;
2925 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002926 *params = (GLint)programObject->getActiveUniformBlockCount();
2927 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002928 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002929 *params = programObject->getActiveUniformBlockMaxLength();
2930 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002931 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002932 *params = programObject->getTransformFeedbackBufferMode();
2933 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002934 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002935 *params = programObject->getTransformFeedbackVaryingCount();
2936 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002937 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002938 *params = programObject->getTransformFeedbackVaryingMaxLength();
2939 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002940 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002941 *params = programObject->getBinaryRetrievableHint();
2942 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002943 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002944 *params = programObject->getBinaryLength();
2945 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002946 default:
2947 return error(GL_INVALID_ENUM);
2948 }
2949 }
2950}
2951
2952void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2953{
2954 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2955 program, bufsize, length, infolog);
2956
2957 if(bufsize < 0)
2958 {
2959 return error(GL_INVALID_VALUE);
2960 }
2961
Chris Forbes108f3e12018-08-30 19:41:59 -07002962 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002963
2964 if(context)
2965 {
2966 es2::Program *programObject = context->getProgram(program);
2967
2968 if(!programObject)
2969 {
2970 if(context->getShader(program))
2971 {
2972 return error(GL_INVALID_OPERATION);
2973 }
2974 else
2975 {
2976 return error(GL_INVALID_VALUE);
2977 }
2978 }
2979
2980 programObject->getInfoLog(bufsize, length, infolog);
2981 }
2982}
2983
2984void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2985{
2986 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2987
2988 switch(pname)
2989 {
2990 case GL_CURRENT_QUERY_EXT:
2991 break;
2992 default:
2993 return error(GL_INVALID_ENUM);
2994 }
2995
Chris Forbes108f3e12018-08-30 19:41:59 -07002996 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002997
2998 if(context)
2999 {
3000 params[0] = context->getActiveQuery(target);
3001 }
3002}
3003
3004void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3005{
3006 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3007
3008 switch(pname)
3009 {
3010 case GL_QUERY_RESULT_EXT:
3011 case GL_QUERY_RESULT_AVAILABLE_EXT:
3012 break;
3013 default:
3014 return error(GL_INVALID_ENUM);
3015 }
3016
Chris Forbes108f3e12018-08-30 19:41:59 -07003017 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003018
3019 if(context)
3020 {
3021 es2::Query *queryObject = context->getQuery(name);
3022
3023 if(!queryObject)
3024 {
3025 return error(GL_INVALID_OPERATION);
3026 }
3027
3028 if(context->getActiveQuery(queryObject->getType()) == name)
3029 {
3030 return error(GL_INVALID_OPERATION);
3031 }
3032
3033 switch(pname)
3034 {
3035 case GL_QUERY_RESULT_EXT:
3036 params[0] = queryObject->getResult();
3037 break;
3038 case GL_QUERY_RESULT_AVAILABLE_EXT:
3039 params[0] = queryObject->isResultAvailable();
3040 break;
3041 default:
3042 ASSERT(false);
3043 }
3044 }
3045}
3046
3047void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3048{
3049 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3050
Chris Forbes108f3e12018-08-30 19:41:59 -07003051 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003052
3053 if(context)
3054 {
3055 if(target != GL_RENDERBUFFER)
3056 {
3057 return error(GL_INVALID_ENUM);
3058 }
3059
3060 if(context->getRenderbufferName() == 0)
3061 {
3062 return error(GL_INVALID_OPERATION);
3063 }
3064
3065 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3066
3067 switch(pname)
3068 {
3069 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3070 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003071 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3072 {
3073 GLint internalformat = renderbuffer->getFormat();
3074 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3075 }
3076 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003077 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3078 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3079 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3080 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3081 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3082 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003083 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003084 default:
3085 return error(GL_INVALID_ENUM);
3086 }
3087 }
3088}
3089
3090void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3091{
3092 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3093
Chris Forbes108f3e12018-08-30 19:41:59 -07003094 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003095
3096 if(context)
3097 {
3098 es2::Shader *shaderObject = context->getShader(shader);
3099
3100 if(!shaderObject)
3101 {
3102 if(context->getProgram(shader))
3103 {
3104 return error(GL_INVALID_OPERATION);
3105 }
3106 else
3107 {
3108 return error(GL_INVALID_VALUE);
3109 }
3110 }
3111
3112 switch(pname)
3113 {
3114 case GL_SHADER_TYPE:
3115 *params = shaderObject->getType();
3116 return;
3117 case GL_DELETE_STATUS:
3118 *params = shaderObject->isFlaggedForDeletion();
3119 return;
3120 case GL_COMPILE_STATUS:
3121 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3122 return;
3123 case GL_INFO_LOG_LENGTH:
3124 *params = (GLint)shaderObject->getInfoLogLength();
3125 return;
3126 case GL_SHADER_SOURCE_LENGTH:
3127 *params = (GLint)shaderObject->getSourceLength();
3128 return;
3129 default:
3130 return error(GL_INVALID_ENUM);
3131 }
3132 }
3133}
3134
3135void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3136{
3137 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3138 shader, bufsize, length, infolog);
3139
3140 if(bufsize < 0)
3141 {
3142 return error(GL_INVALID_VALUE);
3143 }
3144
Chris Forbes108f3e12018-08-30 19:41:59 -07003145 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003146
3147 if(context)
3148 {
3149 es2::Shader *shaderObject = context->getShader(shader);
3150
3151 if(!shaderObject)
3152 {
3153 if(context->getProgram(shader))
3154 {
3155 return error(GL_INVALID_OPERATION);
3156 }
3157 else
3158 {
3159 return error(GL_INVALID_VALUE);
3160 }
3161 }
3162
3163 shaderObject->getInfoLog(bufsize, length, infolog);
3164 }
3165}
3166
3167void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3168{
3169 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3170 shadertype, precisiontype, range, precision);
3171
3172 switch(shadertype)
3173 {
3174 case GL_VERTEX_SHADER:
3175 case GL_FRAGMENT_SHADER:
3176 break;
3177 default:
3178 return error(GL_INVALID_ENUM);
3179 }
3180
3181 switch(precisiontype)
3182 {
3183 case GL_LOW_FLOAT:
3184 case GL_MEDIUM_FLOAT:
3185 case GL_HIGH_FLOAT:
3186 // IEEE 754 single-precision
3187 range[0] = 127;
3188 range[1] = 127;
3189 *precision = 23;
3190 break;
3191 case GL_LOW_INT:
3192 case GL_MEDIUM_INT:
3193 case GL_HIGH_INT:
3194 // Full integer precision is supported
3195 range[0] = 31;
3196 range[1] = 30;
3197 *precision = 0;
3198 break;
3199 default:
3200 return error(GL_INVALID_ENUM);
3201 }
3202}
3203
3204void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3205{
3206 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3207 shader, bufsize, length, source);
3208
3209 if(bufsize < 0)
3210 {
3211 return error(GL_INVALID_VALUE);
3212 }
3213
Chris Forbes108f3e12018-08-30 19:41:59 -07003214 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003215
3216 if(context)
3217 {
3218 es2::Shader *shaderObject = context->getShader(shader);
3219
3220 if(!shaderObject)
3221 {
3222 if(context->getProgram(shader))
3223 {
3224 return error(GL_INVALID_OPERATION);
3225 }
3226 else
3227 {
3228 return error(GL_INVALID_VALUE);
3229 }
3230 }
3231
3232 shaderObject->getSource(bufsize, length, source);
3233 }
3234}
3235
3236const GLubyte* GetString(GLenum name)
3237{
3238 TRACE("(GLenum name = 0x%X)", name);
3239
3240 switch(name)
3241 {
3242 case GL_VENDOR:
3243 return (GLubyte*)"Google Inc.";
3244 case GL_RENDERER:
3245 return (GLubyte*)"Google SwiftShader";
3246 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003247 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003248 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003249 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003250 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003251 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003252 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003253 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3254 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003255 default:
3256 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3257 }
3258}
3259
3260void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3261{
3262 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3263
Chris Forbes108f3e12018-08-30 19:41:59 -07003264 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003265
3266 if(context)
3267 {
3268 es2::Texture *texture;
3269
Nicolas Capens0bac2852016-05-07 06:09:58 -04003270 switch(target)
3271 {
Nicolas Capens83463112018-06-12 23:55:16 -04003272 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3273 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3274 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3275 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3276 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3277 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003278 default:
3279 return error(GL_INVALID_ENUM);
3280 }
3281
3282 switch(pname)
3283 {
3284 case GL_TEXTURE_MAG_FILTER:
3285 *params = (GLfloat)texture->getMagFilter();
3286 break;
3287 case GL_TEXTURE_MIN_FILTER:
3288 *params = (GLfloat)texture->getMinFilter();
3289 break;
3290 case GL_TEXTURE_WRAP_S:
3291 *params = (GLfloat)texture->getWrapS();
3292 break;
3293 case GL_TEXTURE_WRAP_T:
3294 *params = (GLfloat)texture->getWrapT();
3295 break;
3296 case GL_TEXTURE_WRAP_R_OES:
3297 *params = (GLfloat)texture->getWrapR();
3298 break;
3299 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3300 *params = texture->getMaxAnisotropy();
3301 break;
3302 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3303 *params = (GLfloat)1;
3304 break;
3305 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003306 *params = (GLfloat)texture->getBaseLevel();
3307 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003308 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003309 *params = (GLfloat)texture->getCompareFunc();
3310 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003311 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003312 *params = (GLfloat)texture->getCompareMode();
3313 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003314 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003315 *params = (GLfloat)texture->getImmutableFormat();
3316 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003317 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003318 *params = (GLfloat)texture->getImmutableLevels();
3319 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003320 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003321 *params = (GLfloat)texture->getMaxLevel();
3322 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003323 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003324 *params = texture->getMaxLOD();
3325 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003326 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003327 *params = texture->getMinLOD();
3328 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003329 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003330 *params = (GLfloat)texture->getSwizzleR();
3331 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003332 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003333 *params = (GLfloat)texture->getSwizzleG();
3334 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003335 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003336 *params = (GLfloat)texture->getSwizzleB();
3337 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003338 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003339 *params = (GLfloat)texture->getSwizzleA();
3340 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003341 default:
3342 return error(GL_INVALID_ENUM);
3343 }
3344 }
3345}
3346
3347void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3348{
3349 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3350
Chris Forbes108f3e12018-08-30 19:41:59 -07003351 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003352
3353 if(context)
3354 {
3355 es2::Texture *texture;
3356
Nicolas Capens0bac2852016-05-07 06:09:58 -04003357 switch(target)
3358 {
Nicolas Capens83463112018-06-12 23:55:16 -04003359 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3360 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3361 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3362 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3363 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3364 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003365 default:
3366 return error(GL_INVALID_ENUM);
3367 }
3368
3369 switch(pname)
3370 {
3371 case GL_TEXTURE_MAG_FILTER:
3372 *params = texture->getMagFilter();
3373 break;
3374 case GL_TEXTURE_MIN_FILTER:
3375 *params = texture->getMinFilter();
3376 break;
3377 case GL_TEXTURE_WRAP_S:
3378 *params = texture->getWrapS();
3379 break;
3380 case GL_TEXTURE_WRAP_T:
3381 *params = texture->getWrapT();
3382 break;
3383 case GL_TEXTURE_WRAP_R_OES:
3384 *params = texture->getWrapR();
3385 break;
3386 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3387 *params = (GLint)texture->getMaxAnisotropy();
3388 break;
3389 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3390 *params = 1;
3391 break;
3392 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003393 *params = texture->getBaseLevel();
3394 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003395 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003396 *params = (GLint)texture->getCompareFunc();
3397 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003398 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003399 *params = (GLint)texture->getCompareMode();
3400 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003401 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003402 *params = (GLint)texture->getImmutableFormat();
3403 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003404 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003405 *params = (GLint)texture->getImmutableLevels();
3406 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003407 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003408 *params = texture->getMaxLevel();
3409 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003410 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003411 *params = (GLint)roundf(texture->getMaxLOD());
3412 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003413 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003414 *params = (GLint)roundf(texture->getMinLOD());
3415 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003416 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003417 *params = (GLint)texture->getSwizzleR();
3418 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003419 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003420 *params = (GLint)texture->getSwizzleG();
3421 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003422 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003423 *params = (GLint)texture->getSwizzleB();
3424 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003425 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003426 *params = (GLint)texture->getSwizzleA();
3427 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003428 default:
3429 return error(GL_INVALID_ENUM);
3430 }
3431 }
3432}
3433
3434void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3435{
3436 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3437 program, location, bufSize, params);
3438
3439 if(bufSize < 0)
3440 {
3441 return error(GL_INVALID_VALUE);
3442 }
3443
Chris Forbes108f3e12018-08-30 19:41:59 -07003444 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003445
3446 if(context)
3447 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003448 es2::Program *programObject = context->getProgram(program);
3449
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003450 if(!programObject)
3451 {
3452 if(context->getShader(program))
3453 {
3454 return error(GL_INVALID_OPERATION);
3455 }
3456 else
3457 {
3458 return error(GL_INVALID_VALUE);
3459 }
3460 }
3461
3462 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003463 {
3464 return error(GL_INVALID_OPERATION);
3465 }
3466
3467 if(!programObject->getUniformfv(location, &bufSize, params))
3468 {
3469 return error(GL_INVALID_OPERATION);
3470 }
3471 }
3472}
3473
3474void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3475{
3476 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3477
Chris Forbes108f3e12018-08-30 19:41:59 -07003478 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003479
3480 if(context)
3481 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003482 es2::Program *programObject = context->getProgram(program);
3483
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003484 if(!programObject)
3485 {
3486 if(context->getShader(program))
3487 {
3488 return error(GL_INVALID_OPERATION);
3489 }
3490 else
3491 {
3492 return error(GL_INVALID_VALUE);
3493 }
3494 }
3495
3496 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003497 {
3498 return error(GL_INVALID_OPERATION);
3499 }
3500
3501 if(!programObject->getUniformfv(location, nullptr, params))
3502 {
3503 return error(GL_INVALID_OPERATION);
3504 }
3505 }
3506}
3507
3508void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3509{
3510 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3511 program, location, bufSize, params);
3512
3513 if(bufSize < 0)
3514 {
3515 return error(GL_INVALID_VALUE);
3516 }
3517
Chris Forbes108f3e12018-08-30 19:41:59 -07003518 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003519
3520 if(context)
3521 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003522 es2::Program *programObject = context->getProgram(program);
3523
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003524 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003525 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003526 if(context->getShader(program))
3527 {
3528 return error(GL_INVALID_OPERATION);
3529 }
3530 else
3531 {
3532 return error(GL_INVALID_VALUE);
3533 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003534 }
3535
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003536 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003537 {
3538 return error(GL_INVALID_OPERATION);
3539 }
3540
3541 if(!programObject->getUniformiv(location, &bufSize, params))
3542 {
3543 return error(GL_INVALID_OPERATION);
3544 }
3545 }
3546}
3547
3548void GetUniformiv(GLuint program, GLint location, GLint* params)
3549{
3550 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3551
Chris Forbes108f3e12018-08-30 19:41:59 -07003552 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003553
3554 if(context)
3555 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003556 es2::Program *programObject = context->getProgram(program);
3557
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003558 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003559 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003560 if(context->getShader(program))
3561 {
3562 return error(GL_INVALID_OPERATION);
3563 }
3564 else
3565 {
3566 return error(GL_INVALID_VALUE);
3567 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003568 }
3569
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003570 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003571 {
3572 return error(GL_INVALID_OPERATION);
3573 }
3574
3575 if(!programObject->getUniformiv(location, nullptr, params))
3576 {
3577 return error(GL_INVALID_OPERATION);
3578 }
3579 }
3580}
3581
3582int GetUniformLocation(GLuint program, const GLchar* name)
3583{
3584 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3585
Chris Forbes108f3e12018-08-30 19:41:59 -07003586 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003587
3588 if(strstr(name, "gl_") == name)
3589 {
3590 return -1;
3591 }
3592
3593 if(context)
3594 {
3595 es2::Program *programObject = context->getProgram(program);
3596
3597 if(!programObject)
3598 {
3599 if(context->getShader(program))
3600 {
3601 return error(GL_INVALID_OPERATION, -1);
3602 }
3603 else
3604 {
3605 return error(GL_INVALID_VALUE, -1);
3606 }
3607 }
3608
3609 if(!programObject->isLinked())
3610 {
3611 return error(GL_INVALID_OPERATION, -1);
3612 }
3613
3614 return programObject->getUniformLocation(name);
3615 }
3616
3617 return -1;
3618}
3619
3620void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3621{
3622 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3623
Chris Forbes108f3e12018-08-30 19:41:59 -07003624 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003625
3626 if(context)
3627 {
3628 if(index >= es2::MAX_VERTEX_ATTRIBS)
3629 {
3630 return error(GL_INVALID_VALUE);
3631 }
3632
3633 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3634
Nicolas Capens0bac2852016-05-07 06:09:58 -04003635 switch(pname)
3636 {
3637 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3638 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3639 break;
3640 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3641 *params = (GLfloat)attribState.mSize;
3642 break;
3643 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3644 *params = (GLfloat)attribState.mStride;
3645 break;
3646 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3647 *params = (GLfloat)attribState.mType;
3648 break;
3649 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3650 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3651 break;
3652 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3653 *params = (GLfloat)attribState.mBoundBuffer.name();
3654 break;
3655 case GL_CURRENT_VERTEX_ATTRIB:
3656 {
3657 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3658 for(int i = 0; i < 4; ++i)
3659 {
3660 params[i] = attrib.getCurrentValueF(i);
3661 }
3662 }
3663 break;
3664 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003665 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3666 break;
3667 default:
3668 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003669 }
3670 }
3671}
3672
3673void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3674{
3675 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3676
Chris Forbes108f3e12018-08-30 19:41:59 -07003677 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003678
3679 if(context)
3680 {
3681 if(index >= es2::MAX_VERTEX_ATTRIBS)
3682 {
3683 return error(GL_INVALID_VALUE);
3684 }
3685
3686 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3687
Nicolas Capens0bac2852016-05-07 06:09:58 -04003688 switch(pname)
3689 {
3690 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3691 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3692 break;
3693 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3694 *params = attribState.mSize;
3695 break;
3696 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3697 *params = attribState.mStride;
3698 break;
3699 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3700 *params = attribState.mType;
3701 break;
3702 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3703 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3704 break;
3705 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3706 *params = attribState.mBoundBuffer.name();
3707 break;
3708 case GL_CURRENT_VERTEX_ATTRIB:
3709 {
3710 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3711 for(int i = 0; i < 4; ++i)
3712 {
3713 float currentValue = attrib.getCurrentValueF(i);
3714 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3715 }
3716 }
3717 break;
3718 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003719 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3720 break;
3721 default:
3722 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003723 }
3724 }
3725}
3726
3727void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3728{
3729 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3730
Chris Forbes108f3e12018-08-30 19:41:59 -07003731 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003732
3733 if(context)
3734 {
3735 if(index >= es2::MAX_VERTEX_ATTRIBS)
3736 {
3737 return error(GL_INVALID_VALUE);
3738 }
3739
3740 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3741 {
3742 return error(GL_INVALID_ENUM);
3743 }
3744
3745 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3746 }
3747}
3748
3749void Hint(GLenum target, GLenum mode)
3750{
3751 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3752
3753 switch(mode)
3754 {
3755 case GL_FASTEST:
3756 case GL_NICEST:
3757 case GL_DONT_CARE:
3758 break;
3759 default:
3760 return error(GL_INVALID_ENUM);
3761 }
3762
Chris Forbes108f3e12018-08-30 19:41:59 -07003763 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003764
3765 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003766 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003767 switch(target)
3768 {
3769 case GL_GENERATE_MIPMAP_HINT:
3770 context->setGenerateMipmapHint(mode);
3771 break;
3772 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3773 context->setFragmentShaderDerivativeHint(mode);
3774 break;
3775 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3776 context->setTextureFilteringHint(mode);
3777 break;
3778 default:
3779 return error(GL_INVALID_ENUM);
3780 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003781 }
3782}
3783
3784GLboolean IsBuffer(GLuint buffer)
3785{
3786 TRACE("(GLuint buffer = %d)", buffer);
3787
Chris Forbes108f3e12018-08-30 19:41:59 -07003788 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003789
3790 if(context && buffer)
3791 {
3792 es2::Buffer *bufferObject = context->getBuffer(buffer);
3793
3794 if(bufferObject)
3795 {
3796 return GL_TRUE;
3797 }
3798 }
3799
3800 return GL_FALSE;
3801}
3802
3803GLboolean IsEnabled(GLenum cap)
3804{
3805 TRACE("(GLenum cap = 0x%X)", cap);
3806
Chris Forbes108f3e12018-08-30 19:41:59 -07003807 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003808
3809 if(context)
3810 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003811 switch(cap)
3812 {
3813 case GL_CULL_FACE: return context->isCullFaceEnabled();
3814 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3815 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3816 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3817 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3818 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3819 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3820 case GL_BLEND: return context->isBlendEnabled();
3821 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003822 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3823 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003824 default:
3825 return error(GL_INVALID_ENUM, false);
3826 }
3827 }
3828
3829 return false;
3830}
3831
3832GLboolean IsFenceNV(GLuint fence)
3833{
3834 TRACE("(GLuint fence = %d)", fence);
3835
Chris Forbes108f3e12018-08-30 19:41:59 -07003836 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003837
3838 if(context)
3839 {
3840 es2::Fence *fenceObject = context->getFence(fence);
3841
3842 if(!fenceObject)
3843 {
3844 return GL_FALSE;
3845 }
3846
3847 return fenceObject->isFence();
3848 }
3849
3850 return GL_FALSE;
3851}
3852
3853GLboolean IsFramebuffer(GLuint framebuffer)
3854{
3855 TRACE("(GLuint framebuffer = %d)", framebuffer);
3856
Chris Forbes108f3e12018-08-30 19:41:59 -07003857 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003858
3859 if(context && framebuffer)
3860 {
3861 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3862
3863 if(framebufferObject)
3864 {
3865 return GL_TRUE;
3866 }
3867 }
3868
3869 return GL_FALSE;
3870}
3871
3872GLboolean IsProgram(GLuint program)
3873{
3874 TRACE("(GLuint program = %d)", program);
3875
Chris Forbes108f3e12018-08-30 19:41:59 -07003876 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003877
3878 if(context && program)
3879 {
3880 es2::Program *programObject = context->getProgram(program);
3881
3882 if(programObject)
3883 {
3884 return GL_TRUE;
3885 }
3886 }
3887
3888 return GL_FALSE;
3889}
3890
3891GLboolean IsQueryEXT(GLuint name)
3892{
3893 TRACE("(GLuint name = %d)", name);
3894
3895 if(name == 0)
3896 {
3897 return GL_FALSE;
3898 }
3899
Chris Forbes108f3e12018-08-30 19:41:59 -07003900 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003901
3902 if(context)
3903 {
3904 es2::Query *queryObject = context->getQuery(name);
3905
3906 if(queryObject)
3907 {
3908 return GL_TRUE;
3909 }
3910 }
3911
3912 return GL_FALSE;
3913}
3914
3915GLboolean IsRenderbuffer(GLuint renderbuffer)
3916{
3917 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3918
Chris Forbes108f3e12018-08-30 19:41:59 -07003919 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003920
3921 if(context && renderbuffer)
3922 {
3923 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3924
3925 if(renderbufferObject)
3926 {
3927 return GL_TRUE;
3928 }
3929 }
3930
3931 return GL_FALSE;
3932}
3933
3934GLboolean IsShader(GLuint shader)
3935{
3936 TRACE("(GLuint shader = %d)", shader);
3937
Chris Forbes108f3e12018-08-30 19:41:59 -07003938 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003939
3940 if(context && shader)
3941 {
3942 es2::Shader *shaderObject = context->getShader(shader);
3943
3944 if(shaderObject)
3945 {
3946 return GL_TRUE;
3947 }
3948 }
3949
3950 return GL_FALSE;
3951}
3952
3953GLboolean IsTexture(GLuint texture)
3954{
3955 TRACE("(GLuint texture = %d)", texture);
3956
Chris Forbes108f3e12018-08-30 19:41:59 -07003957 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003958
3959 if(context && texture)
3960 {
3961 es2::Texture *textureObject = context->getTexture(texture);
3962
3963 if(textureObject)
3964 {
3965 return GL_TRUE;
3966 }
3967 }
3968
3969 return GL_FALSE;
3970}
3971
3972void LineWidth(GLfloat width)
3973{
3974 TRACE("(GLfloat width = %f)", width);
3975
3976 if(width <= 0.0f)
3977 {
3978 return error(GL_INVALID_VALUE);
3979 }
3980
Chris Forbes108f3e12018-08-30 19:41:59 -07003981 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003982
3983 if(context)
3984 {
3985 context->setLineWidth(width);
3986 }
3987}
3988
3989void LinkProgram(GLuint program)
3990{
3991 TRACE("(GLuint program = %d)", program);
3992
Chris Forbes108f3e12018-08-30 19:41:59 -07003993 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003994
3995 if(context)
3996 {
3997 es2::Program *programObject = context->getProgram(program);
3998
3999 if(!programObject)
4000 {
4001 if(context->getShader(program))
4002 {
4003 return error(GL_INVALID_OPERATION);
4004 }
4005 else
4006 {
4007 return error(GL_INVALID_VALUE);
4008 }
4009 }
4010
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004011 if(programObject == context->getCurrentProgram())
4012 {
4013 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4014 if(transformFeedback && transformFeedback->isActive())
4015 {
4016 return error(GL_INVALID_OPERATION);
4017 }
4018 }
4019
Nicolas Capens0bac2852016-05-07 06:09:58 -04004020 programObject->link();
4021 }
4022}
4023
4024void PixelStorei(GLenum pname, GLint param)
4025{
4026 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4027
Chris Forbes108f3e12018-08-30 19:41:59 -07004028 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004029
4030 if(context)
4031 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004032 switch(pname)
4033 {
4034 case GL_UNPACK_ALIGNMENT:
4035 if(param != 1 && param != 2 && param != 4 && param != 8)
4036 {
4037 return error(GL_INVALID_VALUE);
4038 }
4039 context->setUnpackAlignment(param);
4040 break;
4041 case GL_PACK_ALIGNMENT:
4042 if(param != 1 && param != 2 && param != 4 && param != 8)
4043 {
4044 return error(GL_INVALID_VALUE);
4045 }
4046 context->setPackAlignment(param);
4047 break;
4048 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004049 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004050 {
Nicolas Capens83463112018-06-12 23:55:16 -04004051 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004052 }
Nicolas Capens83463112018-06-12 23:55:16 -04004053 context->setPackRowLength(param);
4054 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004055 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004056 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004057 {
Nicolas Capens83463112018-06-12 23:55:16 -04004058 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004059 }
Nicolas Capens83463112018-06-12 23:55:16 -04004060 context->setPackSkipPixels(param);
4061 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004062 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004063 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 {
Nicolas Capens83463112018-06-12 23:55:16 -04004065 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004066 }
Nicolas Capens83463112018-06-12 23:55:16 -04004067 context->setPackSkipRows(param);
4068 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004069 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004070 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 {
Nicolas Capens83463112018-06-12 23:55:16 -04004072 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004073 }
Nicolas Capens83463112018-06-12 23:55:16 -04004074 context->setUnpackRowLength(param);
4075 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004076 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004077 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 {
Nicolas Capens83463112018-06-12 23:55:16 -04004079 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004080 }
Nicolas Capens83463112018-06-12 23:55:16 -04004081 context->setUnpackImageHeight(param);
4082 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004084 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 {
Nicolas Capens83463112018-06-12 23:55:16 -04004086 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004087 }
Nicolas Capens83463112018-06-12 23:55:16 -04004088 context->setUnpackSkipPixels(param);
4089 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004091 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 {
Nicolas Capens83463112018-06-12 23:55:16 -04004093 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004094 }
Nicolas Capens83463112018-06-12 23:55:16 -04004095 context->setUnpackSkipRows(param);
4096 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004097 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004098 if(param < 0)
4099 {
4100 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004101 }
Nicolas Capens83463112018-06-12 23:55:16 -04004102 context->setUnpackSkipImages(param);
4103 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004104 default:
4105 return error(GL_INVALID_ENUM);
4106 }
4107 }
4108}
4109
4110void PolygonOffset(GLfloat factor, GLfloat units)
4111{
4112 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4113
Chris Forbes108f3e12018-08-30 19:41:59 -07004114 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004115
4116 if(context)
4117 {
4118 context->setPolygonOffsetParams(factor, units);
4119 }
4120}
4121
4122void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4123 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4124{
4125 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4126 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4127 x, y, width, height, format, type, bufSize, data);
4128
4129 if(width < 0 || height < 0 || bufSize < 0)
4130 {
4131 return error(GL_INVALID_VALUE);
4132 }
4133
Chris Forbes108f3e12018-08-30 19:41:59 -07004134 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004135
4136 if(context)
4137 {
4138 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4139 }
4140}
4141
4142void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4143{
4144 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4145 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4146 x, y, width, height, format, type, pixels);
4147
4148 if(width < 0 || height < 0)
4149 {
4150 return error(GL_INVALID_VALUE);
4151 }
4152
Chris Forbes108f3e12018-08-30 19:41:59 -07004153 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004154
4155 if(context)
4156 {
4157 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4158 }
4159}
4160
4161void ReleaseShaderCompiler(void)
4162{
4163 TRACE("()");
4164
4165 es2::Shader::releaseCompiler();
4166}
4167
Nicolas Capens400667e2017-03-29 14:40:14 -04004168void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004169{
4170 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4171 target, samples, internalformat, width, height);
4172
4173 switch(target)
4174 {
4175 case GL_RENDERBUFFER:
4176 break;
4177 default:
4178 return error(GL_INVALID_ENUM);
4179 }
4180
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004181 if(width < 0 || height < 0 || samples < 0 ||
4182 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4183 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004184 {
4185 return error(GL_INVALID_VALUE);
4186 }
4187
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004188 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004189 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004190 {
4191 return error(GL_INVALID_OPERATION);
4192 }
4193
Chris Forbes108f3e12018-08-30 19:41:59 -07004194 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004195
4196 if(context)
4197 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004198 GLuint handle = context->getRenderbufferName();
4199 if(handle == 0)
4200 {
4201 return error(GL_INVALID_OPERATION);
4202 }
4203
Nicolas Capens83463112018-06-12 23:55:16 -04004204 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004205 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004206 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004207 }
Nicolas Capens83463112018-06-12 23:55:16 -04004208 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004209 {
4210 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4211 }
Nicolas Capens83463112018-06-12 23:55:16 -04004212 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004213 {
4214 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4215 }
Nicolas Capens83463112018-06-12 23:55:16 -04004216 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004217 {
4218 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4219 }
4220 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004221 }
4222}
4223
Nicolas Capens400667e2017-03-29 14:40:14 -04004224void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4225{
4226 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4227}
4228
Nicolas Capens0bac2852016-05-07 06:09:58 -04004229void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4230{
Nicolas Capens400667e2017-03-29 14:40:14 -04004231 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004232}
4233
4234void SampleCoverage(GLclampf value, GLboolean invert)
4235{
4236 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4237
Chris Forbes108f3e12018-08-30 19:41:59 -07004238 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004239
4240 if(context)
4241 {
4242 context->setSampleCoverageParams(es2::clamp01(value), invert == GL_TRUE);
4243 }
4244}
4245
4246void SetFenceNV(GLuint fence, GLenum condition)
4247{
4248 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4249
4250 if(condition != GL_ALL_COMPLETED_NV)
4251 {
4252 return error(GL_INVALID_ENUM);
4253 }
4254
Chris Forbes108f3e12018-08-30 19:41:59 -07004255 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004256
4257 if(context)
4258 {
4259 es2::Fence *fenceObject = context->getFence(fence);
4260
4261 if(!fenceObject)
4262 {
4263 return error(GL_INVALID_OPERATION);
4264 }
4265
4266 fenceObject->setFence(condition);
4267 }
4268}
4269
4270void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4271{
4272 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4273
4274 if(width < 0 || height < 0)
4275 {
4276 return error(GL_INVALID_VALUE);
4277 }
4278
Chris Forbes108f3e12018-08-30 19:41:59 -07004279 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004280
4281 if(context)
4282 {
4283 context->setScissorParams(x, y, width, height);
4284 }
4285}
4286
4287void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4288{
4289 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4290 "const GLvoid* binary = %p, GLsizei length = %d)",
4291 n, shaders, binaryformat, binary, length);
4292
4293 // No binary shader formats are supported.
4294 return error(GL_INVALID_ENUM);
4295}
4296
4297void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4298{
4299 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4300 shader, count, string, length);
4301
4302 if(count < 0)
4303 {
4304 return error(GL_INVALID_VALUE);
4305 }
4306
Chris Forbes108f3e12018-08-30 19:41:59 -07004307 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004308
4309 if(context)
4310 {
4311 es2::Shader *shaderObject = context->getShader(shader);
4312
4313 if(!shaderObject)
4314 {
4315 if(context->getProgram(shader))
4316 {
4317 return error(GL_INVALID_OPERATION);
4318 }
4319 else
4320 {
4321 return error(GL_INVALID_VALUE);
4322 }
4323 }
4324
4325 shaderObject->setSource(count, string, length);
4326 }
4327}
4328
4329void StencilFunc(GLenum func, GLint ref, GLuint mask)
4330{
4331 glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
4332}
4333
4334void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4335{
4336 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4337
4338 switch(face)
4339 {
4340 case GL_FRONT:
4341 case GL_BACK:
4342 case GL_FRONT_AND_BACK:
4343 break;
4344 default:
4345 return error(GL_INVALID_ENUM);
4346 }
4347
4348 switch(func)
4349 {
4350 case GL_NEVER:
4351 case GL_ALWAYS:
4352 case GL_LESS:
4353 case GL_LEQUAL:
4354 case GL_EQUAL:
4355 case GL_GEQUAL:
4356 case GL_GREATER:
4357 case GL_NOTEQUAL:
4358 break;
4359 default:
4360 return error(GL_INVALID_ENUM);
4361 }
4362
Chris Forbes108f3e12018-08-30 19:41:59 -07004363 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004364
4365 if(context)
4366 {
4367 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4368 {
4369 context->setStencilParams(func, ref, mask);
4370 }
4371
4372 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4373 {
4374 context->setStencilBackParams(func, ref, mask);
4375 }
4376 }
4377}
4378
4379void StencilMask(GLuint mask)
4380{
4381 glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
4382}
4383
4384void StencilMaskSeparate(GLenum face, GLuint mask)
4385{
4386 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4387
4388 switch(face)
4389 {
4390 case GL_FRONT:
4391 case GL_BACK:
4392 case GL_FRONT_AND_BACK:
4393 break;
4394 default:
4395 return error(GL_INVALID_ENUM);
4396 }
4397
Chris Forbes108f3e12018-08-30 19:41:59 -07004398 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004399
4400 if(context)
4401 {
4402 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4403 {
4404 context->setStencilWritemask(mask);
4405 }
4406
4407 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4408 {
4409 context->setStencilBackWritemask(mask);
4410 }
4411 }
4412}
4413
4414void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4415{
4416 glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4417}
4418
4419void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4420{
4421 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4422 face, fail, zfail, zpass);
4423
4424 switch(face)
4425 {
4426 case GL_FRONT:
4427 case GL_BACK:
4428 case GL_FRONT_AND_BACK:
4429 break;
4430 default:
4431 return error(GL_INVALID_ENUM);
4432 }
4433
4434 switch(fail)
4435 {
4436 case GL_ZERO:
4437 case GL_KEEP:
4438 case GL_REPLACE:
4439 case GL_INCR:
4440 case GL_DECR:
4441 case GL_INVERT:
4442 case GL_INCR_WRAP:
4443 case GL_DECR_WRAP:
4444 break;
4445 default:
4446 return error(GL_INVALID_ENUM);
4447 }
4448
4449 switch(zfail)
4450 {
4451 case GL_ZERO:
4452 case GL_KEEP:
4453 case GL_REPLACE:
4454 case GL_INCR:
4455 case GL_DECR:
4456 case GL_INVERT:
4457 case GL_INCR_WRAP:
4458 case GL_DECR_WRAP:
4459 break;
4460 default:
4461 return error(GL_INVALID_ENUM);
4462 }
4463
4464 switch(zpass)
4465 {
4466 case GL_ZERO:
4467 case GL_KEEP:
4468 case GL_REPLACE:
4469 case GL_INCR:
4470 case GL_DECR:
4471 case GL_INVERT:
4472 case GL_INCR_WRAP:
4473 case GL_DECR_WRAP:
4474 break;
4475 default:
4476 return error(GL_INVALID_ENUM);
4477 }
4478
Chris Forbes108f3e12018-08-30 19:41:59 -07004479 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004480
4481 if(context)
4482 {
4483 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4484 {
4485 context->setStencilOperations(fail, zfail, zpass);
4486 }
4487
4488 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4489 {
4490 context->setStencilBackOperations(fail, zfail, zpass);
4491 }
4492 }
4493}
4494
4495GLboolean TestFenceNV(GLuint fence)
4496{
4497 TRACE("(GLuint fence = %d)", fence);
4498
Chris Forbes108f3e12018-08-30 19:41:59 -07004499 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004500
4501 if(context)
4502 {
4503 es2::Fence *fenceObject = context->getFence(fence);
4504
4505 if(!fenceObject)
4506 {
4507 return error(GL_INVALID_OPERATION, GL_TRUE);
4508 }
4509
4510 return fenceObject->testFence();
4511 }
4512
4513 return GL_TRUE;
4514}
4515
4516void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004517 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004518{
4519 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004520 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4521 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004522
4523 if(!validImageSize(level, width, height))
4524 {
4525 return error(GL_INVALID_VALUE);
4526 }
4527
Chris Forbes108f3e12018-08-30 19:41:59 -07004528 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004529
4530 if(context)
4531 {
Nicolas Capens83463112018-06-12 23:55:16 -04004532 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004533 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4534 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4535 {
4536 internalformat = GL_BGRA_EXT;
4537 }
4538
Nicolas Capens83463112018-06-12 23:55:16 -04004539 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004540 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004541 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004542 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004543 }
4544
4545 if(border != 0)
4546 {
4547 return error(GL_INVALID_VALUE);
4548 }
4549
4550 switch(target)
4551 {
Alexis Hetu46768622018-01-16 22:09:28 -05004552 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004553 if(level != 0)
4554 {
4555 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4556 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004557 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004558 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004559 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4560 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4561 {
4562 return error(GL_INVALID_VALUE);
4563 }
4564 break;
4565 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4566 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4567 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4569 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4570 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4571 if(width != height)
4572 {
4573 return error(GL_INVALID_VALUE);
4574 }
4575
4576 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4577 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4578 {
4579 return error(GL_INVALID_VALUE);
4580 }
4581 break;
4582 default:
4583 return error(GL_INVALID_ENUM);
4584 }
4585
Nicolas Capens5555af42017-12-14 13:14:03 -05004586 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004587 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004588 {
4589 return error(validationError);
4590 }
4591
Nicolas Capens894858a2018-03-22 00:55:23 -04004592 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4593
Alexis Hetu46768622018-01-16 22:09:28 -05004594 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004595 {
Alexis Hetu46768622018-01-16 22:09:28 -05004596 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004597
4598 if(!texture)
4599 {
4600 return error(GL_INVALID_OPERATION);
4601 }
4602
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004603 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004604 }
4605 else
4606 {
4607 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4608
4609 if(!texture)
4610 {
4611 return error(GL_INVALID_OPERATION);
4612 }
4613
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004614 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004615 }
4616 }
4617}
4618
4619void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4620{
4621 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4622
Chris Forbes108f3e12018-08-30 19:41:59 -07004623 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004624
4625 if(context)
4626 {
4627 es2::Texture *texture;
4628
Nicolas Capens0bac2852016-05-07 06:09:58 -04004629 switch(target)
4630 {
Nicolas Capens83463112018-06-12 23:55:16 -04004631 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4632 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4633 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4634 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4635 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4636 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004637 default:
4638 return error(GL_INVALID_ENUM);
4639 }
4640
4641 switch(pname)
4642 {
4643 case GL_TEXTURE_WRAP_S:
4644 if(!texture->setWrapS((GLenum)param))
4645 {
4646 return error(GL_INVALID_ENUM);
4647 }
4648 break;
4649 case GL_TEXTURE_WRAP_T:
4650 if(!texture->setWrapT((GLenum)param))
4651 {
4652 return error(GL_INVALID_ENUM);
4653 }
4654 break;
4655 case GL_TEXTURE_WRAP_R_OES:
4656 if(!texture->setWrapR((GLenum)param))
4657 {
4658 return error(GL_INVALID_ENUM);
4659 }
4660 break;
4661 case GL_TEXTURE_MIN_FILTER:
4662 if(!texture->setMinFilter((GLenum)param))
4663 {
4664 return error(GL_INVALID_ENUM);
4665 }
4666 break;
4667 case GL_TEXTURE_MAG_FILTER:
4668 if(!texture->setMagFilter((GLenum)param))
4669 {
4670 return error(GL_INVALID_ENUM);
4671 }
4672 break;
4673 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4674 if(!texture->setMaxAnisotropy(param))
4675 {
4676 return error(GL_INVALID_VALUE);
4677 }
4678 break;
4679 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004680 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004681 {
4682 return error(GL_INVALID_VALUE);
4683 }
4684 break;
4685 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004686 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004687 {
4688 return error(GL_INVALID_VALUE);
4689 }
4690 break;
4691 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004692 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004693 {
4694 return error(GL_INVALID_VALUE);
4695 }
4696 break;
4697 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004698 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004699 {
4700 return error(GL_INVALID_VALUE);
4701 }
4702 break;
4703 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004704 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004705 {
4706 return error(GL_INVALID_VALUE);
4707 }
4708 break;
4709 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004710 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004711 {
4712 return error(GL_INVALID_VALUE);
4713 }
4714 break;
4715 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004716 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004717 {
4718 return error(GL_INVALID_VALUE);
4719 }
4720 break;
4721 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004722 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004723 {
4724 return error(GL_INVALID_VALUE);
4725 }
4726 break;
4727 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004728 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004729 {
4730 return error(GL_INVALID_VALUE);
4731 }
4732 break;
4733 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004734 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004735 {
4736 return error(GL_INVALID_VALUE);
4737 }
4738 break;
4739 default:
4740 return error(GL_INVALID_ENUM);
4741 }
4742 }
4743}
4744
4745void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4746{
4747 glTexParameterf(target, pname, *params);
4748}
4749
4750void TexParameteri(GLenum target, GLenum pname, GLint param)
4751{
4752 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4753
Chris Forbes108f3e12018-08-30 19:41:59 -07004754 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004755
4756 if(context)
4757 {
4758 es2::Texture *texture;
4759
Nicolas Capens0bac2852016-05-07 06:09:58 -04004760 switch(target)
4761 {
Nicolas Capens83463112018-06-12 23:55:16 -04004762 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4763 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4764 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4765 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4766 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4767 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004768 default:
4769 return error(GL_INVALID_ENUM);
4770 }
4771
4772 switch(pname)
4773 {
4774 case GL_TEXTURE_WRAP_S:
4775 if(!texture->setWrapS((GLenum)param))
4776 {
4777 return error(GL_INVALID_ENUM);
4778 }
4779 break;
4780 case GL_TEXTURE_WRAP_T:
4781 if(!texture->setWrapT((GLenum)param))
4782 {
4783 return error(GL_INVALID_ENUM);
4784 }
4785 break;
4786 case GL_TEXTURE_WRAP_R_OES:
4787 if(!texture->setWrapR((GLenum)param))
4788 {
4789 return error(GL_INVALID_ENUM);
4790 }
4791 break;
4792 case GL_TEXTURE_MIN_FILTER:
4793 if(!texture->setMinFilter((GLenum)param))
4794 {
4795 return error(GL_INVALID_ENUM);
4796 }
4797 break;
4798 case GL_TEXTURE_MAG_FILTER:
4799 if(!texture->setMagFilter((GLenum)param))
4800 {
4801 return error(GL_INVALID_ENUM);
4802 }
4803 break;
4804 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4805 if(!texture->setMaxAnisotropy((GLfloat)param))
4806 {
4807 return error(GL_INVALID_VALUE);
4808 }
4809 break;
4810 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004811 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4812 {
4813 return error(GL_INVALID_OPERATION); // Base level has to be 0
4814 }
Nicolas Capens83463112018-06-12 23:55:16 -04004815 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004816 {
4817 return error(GL_INVALID_VALUE);
4818 }
4819 break;
4820 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004821 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004822 {
4823 return error(GL_INVALID_VALUE);
4824 }
4825 break;
4826 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004827 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004828 {
4829 return error(GL_INVALID_VALUE);
4830 }
4831 break;
4832 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004833 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004834 {
4835 return error(GL_INVALID_VALUE);
4836 }
4837 break;
4838 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004839 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004840 {
4841 return error(GL_INVALID_VALUE);
4842 }
4843 break;
4844 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004845 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004846 {
4847 return error(GL_INVALID_VALUE);
4848 }
4849 break;
4850 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004851 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004852 {
4853 return error(GL_INVALID_VALUE);
4854 }
4855 break;
4856 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004857 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004858 {
4859 return error(GL_INVALID_VALUE);
4860 }
4861 break;
4862 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004863 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004864 {
4865 return error(GL_INVALID_VALUE);
4866 }
4867 break;
4868 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004869 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004870 {
4871 return error(GL_INVALID_VALUE);
4872 }
4873 break;
4874 default:
4875 return error(GL_INVALID_ENUM);
4876 }
4877 }
4878}
4879
4880void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4881{
4882 glTexParameteri(target, pname, *params);
4883}
4884
4885void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004886 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004887{
4888 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4889 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004890 "const GLvoid* data = %p)",
4891 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004892
4893 if(!es2::IsTextureTarget(target))
4894 {
4895 return error(GL_INVALID_ENUM);
4896 }
4897
4898 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4899 {
4900 return error(GL_INVALID_VALUE);
4901 }
4902
4903 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4904 {
4905 return error(GL_INVALID_VALUE);
4906 }
4907
4908 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4909 {
4910 return error(GL_INVALID_VALUE);
4911 }
4912
Chris Forbes108f3e12018-08-30 19:41:59 -07004913 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004914
4915 if(context)
4916 {
Alexis Hetu46768622018-01-16 22:09:28 -05004917 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004918 {
Alexis Hetu46768622018-01-16 22:09:28 -05004919 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004920
Nicolas Capens83463112018-06-12 23:55:16 -04004921 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004922 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004923 {
4924 return error(validationError);
4925 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004926
Nicolas Capens5555af42017-12-14 13:14:03 -05004927 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004928 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004929 {
4930 return error(validationError);
4931 }
4932
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004933 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004934 }
4935 else if(es2::IsCubemapTextureTarget(target))
4936 {
4937 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4938
Nicolas Capens83463112018-06-12 23:55:16 -04004939 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004940 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004941 {
4942 return error(validationError);
4943 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004944
Nicolas Capens5555af42017-12-14 13:14:03 -05004945 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004946 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004947 {
4948 return error(validationError);
4949 }
4950
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004951 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004952 }
4953 else UNREACHABLE(target);
4954 }
4955}
4956
4957void Uniform1f(GLint location, GLfloat x)
4958{
4959 glUniform1fv(location, 1, &x);
4960}
4961
4962void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4963{
4964 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4965
4966 if(count < 0)
4967 {
4968 return error(GL_INVALID_VALUE);
4969 }
4970
Chris Forbes108f3e12018-08-30 19:41:59 -07004971 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004972
4973 if(context)
4974 {
4975 es2::Program *program = context->getCurrentProgram();
4976
4977 if(!program)
4978 {
4979 return error(GL_INVALID_OPERATION);
4980 }
4981
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004982 if(location == -1)
4983 {
4984 return;
4985 }
4986
Nicolas Capens0bac2852016-05-07 06:09:58 -04004987 if(!program->setUniform1fv(location, count, v))
4988 {
4989 return error(GL_INVALID_OPERATION);
4990 }
4991 }
4992}
4993
4994void Uniform1i(GLint location, GLint x)
4995{
4996 glUniform1iv(location, 1, &x);
4997}
4998
4999void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5000{
5001 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5002
5003 if(count < 0)
5004 {
5005 return error(GL_INVALID_VALUE);
5006 }
5007
Chris Forbes108f3e12018-08-30 19:41:59 -07005008 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005009
5010 if(context)
5011 {
5012 es2::Program *program = context->getCurrentProgram();
5013
5014 if(!program)
5015 {
5016 return error(GL_INVALID_OPERATION);
5017 }
5018
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005019 if(location == -1)
5020 {
5021 return;
5022 }
5023
Nicolas Capens0bac2852016-05-07 06:09:58 -04005024 if(!program->setUniform1iv(location, count, v))
5025 {
5026 return error(GL_INVALID_OPERATION);
5027 }
5028 }
5029}
5030
5031void Uniform2f(GLint location, GLfloat x, GLfloat y)
5032{
5033 GLfloat xy[2] = {x, y};
5034
5035 glUniform2fv(location, 1, (GLfloat*)&xy);
5036}
5037
5038void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5039{
5040 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5041
5042 if(count < 0)
5043 {
5044 return error(GL_INVALID_VALUE);
5045 }
5046
Chris Forbes108f3e12018-08-30 19:41:59 -07005047 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005048
5049 if(context)
5050 {
5051 es2::Program *program = context->getCurrentProgram();
5052
5053 if(!program)
5054 {
5055 return error(GL_INVALID_OPERATION);
5056 }
5057
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005058 if(location == -1)
5059 {
5060 return;
5061 }
5062
Nicolas Capens0bac2852016-05-07 06:09:58 -04005063 if(!program->setUniform2fv(location, count, v))
5064 {
5065 return error(GL_INVALID_OPERATION);
5066 }
5067 }
5068}
5069
5070void Uniform2i(GLint location, GLint x, GLint y)
5071{
5072 GLint xy[4] = {x, y};
5073
5074 glUniform2iv(location, 1, (GLint*)&xy);
5075}
5076
5077void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5078{
5079 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5080
5081 if(count < 0)
5082 {
5083 return error(GL_INVALID_VALUE);
5084 }
5085
Chris Forbes108f3e12018-08-30 19:41:59 -07005086 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005087
5088 if(context)
5089 {
5090 es2::Program *program = context->getCurrentProgram();
5091
5092 if(!program)
5093 {
5094 return error(GL_INVALID_OPERATION);
5095 }
5096
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005097 if(location == -1)
5098 {
5099 return;
5100 }
5101
Nicolas Capens0bac2852016-05-07 06:09:58 -04005102 if(!program->setUniform2iv(location, count, v))
5103 {
5104 return error(GL_INVALID_OPERATION);
5105 }
5106 }
5107}
5108
5109void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
5110{
5111 GLfloat xyz[3] = {x, y, z};
5112
5113 glUniform3fv(location, 1, (GLfloat*)&xyz);
5114}
5115
5116void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5117{
5118 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5119
5120 if(count < 0)
5121 {
5122 return error(GL_INVALID_VALUE);
5123 }
5124
Chris Forbes108f3e12018-08-30 19:41:59 -07005125 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005126
5127 if(context)
5128 {
5129 es2::Program *program = context->getCurrentProgram();
5130
5131 if(!program)
5132 {
5133 return error(GL_INVALID_OPERATION);
5134 }
5135
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005136 if(location == -1)
5137 {
5138 return;
5139 }
5140
Nicolas Capens0bac2852016-05-07 06:09:58 -04005141 if(!program->setUniform3fv(location, count, v))
5142 {
5143 return error(GL_INVALID_OPERATION);
5144 }
5145 }
5146}
5147
5148void Uniform3i(GLint location, GLint x, GLint y, GLint z)
5149{
5150 GLint xyz[3] = {x, y, z};
5151
5152 glUniform3iv(location, 1, (GLint*)&xyz);
5153}
5154
5155void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5156{
5157 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5158
5159 if(count < 0)
5160 {
5161 return error(GL_INVALID_VALUE);
5162 }
5163
Chris Forbes108f3e12018-08-30 19:41:59 -07005164 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005165
5166 if(context)
5167 {
5168 es2::Program *program = context->getCurrentProgram();
5169
5170 if(!program)
5171 {
5172 return error(GL_INVALID_OPERATION);
5173 }
5174
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005175 if(location == -1)
5176 {
5177 return;
5178 }
5179
Nicolas Capens0bac2852016-05-07 06:09:58 -04005180 if(!program->setUniform3iv(location, count, v))
5181 {
5182 return error(GL_INVALID_OPERATION);
5183 }
5184 }
5185}
5186
5187void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5188{
5189 GLfloat xyzw[4] = {x, y, z, w};
5190
5191 glUniform4fv(location, 1, (GLfloat*)&xyzw);
5192}
5193
5194void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5195{
5196 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5197
5198 if(count < 0)
5199 {
5200 return error(GL_INVALID_VALUE);
5201 }
5202
Chris Forbes108f3e12018-08-30 19:41:59 -07005203 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005204
5205 if(context)
5206 {
5207 es2::Program *program = context->getCurrentProgram();
5208
5209 if(!program)
5210 {
5211 return error(GL_INVALID_OPERATION);
5212 }
5213
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005214 if(location == -1)
5215 {
5216 return;
5217 }
5218
Nicolas Capens0bac2852016-05-07 06:09:58 -04005219 if(!program->setUniform4fv(location, count, v))
5220 {
5221 return error(GL_INVALID_OPERATION);
5222 }
5223 }
5224}
5225
5226void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5227{
5228 GLint xyzw[4] = {x, y, z, w};
5229
5230 glUniform4iv(location, 1, (GLint*)&xyzw);
5231}
5232
5233void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5234{
5235 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5236
5237 if(count < 0)
5238 {
5239 return error(GL_INVALID_VALUE);
5240 }
5241
Chris Forbes108f3e12018-08-30 19:41:59 -07005242 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005243
5244 if(context)
5245 {
5246 es2::Program *program = context->getCurrentProgram();
5247
5248 if(!program)
5249 {
5250 return error(GL_INVALID_OPERATION);
5251 }
5252
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005253 if(location == -1)
5254 {
5255 return;
5256 }
5257
Nicolas Capens0bac2852016-05-07 06:09:58 -04005258 if(!program->setUniform4iv(location, count, v))
5259 {
5260 return error(GL_INVALID_OPERATION);
5261 }
5262 }
5263}
5264
5265void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5266{
5267 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5268 location, count, transpose, value);
5269
5270 if(count < 0)
5271 {
5272 return error(GL_INVALID_VALUE);
5273 }
5274
Chris Forbes108f3e12018-08-30 19:41:59 -07005275 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005276
5277 if(context)
5278 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005279 es2::Program *program = context->getCurrentProgram();
5280
5281 if(!program)
5282 {
5283 return error(GL_INVALID_OPERATION);
5284 }
5285
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005286 if(location == -1)
5287 {
5288 return;
5289 }
5290
Nicolas Capens0bac2852016-05-07 06:09:58 -04005291 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5292 {
5293 return error(GL_INVALID_OPERATION);
5294 }
5295 }
5296}
5297
5298void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5299{
5300 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5301 location, count, transpose, value);
5302
5303 if(count < 0)
5304 {
5305 return error(GL_INVALID_VALUE);
5306 }
5307
Chris Forbes108f3e12018-08-30 19:41:59 -07005308 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005309
5310 if(context)
5311 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005312 es2::Program *program = context->getCurrentProgram();
5313
5314 if(!program)
5315 {
5316 return error(GL_INVALID_OPERATION);
5317 }
5318
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005319 if(location == -1)
5320 {
5321 return;
5322 }
5323
Nicolas Capens0bac2852016-05-07 06:09:58 -04005324 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5325 {
5326 return error(GL_INVALID_OPERATION);
5327 }
5328 }
5329}
5330
5331void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5332{
5333 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5334 location, count, transpose, value);
5335
5336 if(count < 0)
5337 {
5338 return error(GL_INVALID_VALUE);
5339 }
5340
Chris Forbes108f3e12018-08-30 19:41:59 -07005341 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005342
5343 if(context)
5344 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005345 es2::Program *program = context->getCurrentProgram();
5346
5347 if(!program)
5348 {
5349 return error(GL_INVALID_OPERATION);
5350 }
5351
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005352 if(location == -1)
5353 {
5354 return;
5355 }
5356
Nicolas Capens0bac2852016-05-07 06:09:58 -04005357 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5358 {
5359 return error(GL_INVALID_OPERATION);
5360 }
5361 }
5362}
5363
5364void UseProgram(GLuint program)
5365{
5366 TRACE("(GLuint program = %d)", program);
5367
Chris Forbes108f3e12018-08-30 19:41:59 -07005368 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005369
5370 if(context)
5371 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005372 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5373 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5374 {
5375 return error(GL_INVALID_OPERATION);
5376 }
5377
Nicolas Capens0bac2852016-05-07 06:09:58 -04005378 es2::Program *programObject = context->getProgram(program);
5379
5380 if(!programObject && program != 0)
5381 {
5382 if(context->getShader(program))
5383 {
5384 return error(GL_INVALID_OPERATION);
5385 }
5386 else
5387 {
5388 return error(GL_INVALID_VALUE);
5389 }
5390 }
5391
5392 if(program != 0 && !programObject->isLinked())
5393 {
5394 return error(GL_INVALID_OPERATION);
5395 }
5396
5397 context->useProgram(program);
5398 }
5399}
5400
5401void ValidateProgram(GLuint program)
5402{
5403 TRACE("(GLuint program = %d)", program);
5404
Chris Forbes108f3e12018-08-30 19:41:59 -07005405 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005406
5407 if(context)
5408 {
5409 es2::Program *programObject = context->getProgram(program);
5410
5411 if(!programObject)
5412 {
5413 if(context->getShader(program))
5414 {
5415 return error(GL_INVALID_OPERATION);
5416 }
5417 else
5418 {
5419 return error(GL_INVALID_VALUE);
5420 }
5421 }
5422
Ben Vanik1fd3b282017-07-10 14:08:12 -07005423 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005424 }
5425}
5426
5427void VertexAttrib1f(GLuint index, GLfloat x)
5428{
5429 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5430
5431 if(index >= es2::MAX_VERTEX_ATTRIBS)
5432 {
5433 return error(GL_INVALID_VALUE);
5434 }
5435
Chris Forbes108f3e12018-08-30 19:41:59 -07005436 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005437
5438 if(context)
5439 {
5440 GLfloat vals[4] = { x, 0, 0, 1 };
5441 context->setVertexAttrib(index, vals);
5442 }
5443}
5444
5445void VertexAttrib1fv(GLuint index, const GLfloat* values)
5446{
5447 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5448
5449 if(index >= es2::MAX_VERTEX_ATTRIBS)
5450 {
5451 return error(GL_INVALID_VALUE);
5452 }
5453
Chris Forbes108f3e12018-08-30 19:41:59 -07005454 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005455
5456 if(context)
5457 {
5458 GLfloat vals[4] = { values[0], 0, 0, 1 };
5459 context->setVertexAttrib(index, vals);
5460 }
5461}
5462
5463void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5464{
5465 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5466
5467 if(index >= es2::MAX_VERTEX_ATTRIBS)
5468 {
5469 return error(GL_INVALID_VALUE);
5470 }
5471
Chris Forbes108f3e12018-08-30 19:41:59 -07005472 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005473
5474 if(context)
5475 {
5476 GLfloat vals[4] = { x, y, 0, 1 };
5477 context->setVertexAttrib(index, vals);
5478 }
5479}
5480
5481void VertexAttrib2fv(GLuint index, const GLfloat* values)
5482{
5483 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5484
5485 if(index >= es2::MAX_VERTEX_ATTRIBS)
5486 {
5487 return error(GL_INVALID_VALUE);
5488 }
5489
Chris Forbes108f3e12018-08-30 19:41:59 -07005490 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005491
5492 if(context)
5493 {
5494 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5495 context->setVertexAttrib(index, vals);
5496 }
5497}
5498
5499void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5500{
5501 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5502
5503 if(index >= es2::MAX_VERTEX_ATTRIBS)
5504 {
5505 return error(GL_INVALID_VALUE);
5506 }
5507
Chris Forbes108f3e12018-08-30 19:41:59 -07005508 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005509
5510 if(context)
5511 {
5512 GLfloat vals[4] = { x, y, z, 1 };
5513 context->setVertexAttrib(index, vals);
5514 }
5515}
5516
5517void VertexAttrib3fv(GLuint index, const GLfloat* values)
5518{
5519 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5520
5521 if(index >= es2::MAX_VERTEX_ATTRIBS)
5522 {
5523 return error(GL_INVALID_VALUE);
5524 }
5525
Chris Forbes108f3e12018-08-30 19:41:59 -07005526 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005527
5528 if(context)
5529 {
5530 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5531 context->setVertexAttrib(index, vals);
5532 }
5533}
5534
5535void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5536{
5537 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5538
5539 if(index >= es2::MAX_VERTEX_ATTRIBS)
5540 {
5541 return error(GL_INVALID_VALUE);
5542 }
5543
Chris Forbes108f3e12018-08-30 19:41:59 -07005544 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005545
5546 if(context)
5547 {
5548 GLfloat vals[4] = { x, y, z, w };
5549 context->setVertexAttrib(index, vals);
5550 }
5551}
5552
5553void VertexAttrib4fv(GLuint index, const GLfloat* values)
5554{
5555 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5556
5557 if(index >= es2::MAX_VERTEX_ATTRIBS)
5558 {
5559 return error(GL_INVALID_VALUE);
5560 }
5561
Chris Forbes108f3e12018-08-30 19:41:59 -07005562 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005563
5564 if(context)
5565 {
5566 context->setVertexAttrib(index, values);
5567 }
5568}
5569
5570void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5571{
5572 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5573 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5574 index, size, type, normalized, stride, ptr);
5575
5576 if(index >= es2::MAX_VERTEX_ATTRIBS)
5577 {
5578 return error(GL_INVALID_VALUE);
5579 }
5580
5581 if(size < 1 || size > 4)
5582 {
5583 return error(GL_INVALID_VALUE);
5584 }
5585
Nicolas Capens0bac2852016-05-07 06:09:58 -04005586 switch(type)
5587 {
5588 case GL_BYTE:
5589 case GL_UNSIGNED_BYTE:
5590 case GL_SHORT:
5591 case GL_UNSIGNED_SHORT:
5592 case GL_FIXED:
5593 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005594 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005595 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005596 break;
5597 case GL_INT_2_10_10_10_REV:
5598 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005599 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005600 {
Nicolas Capens83463112018-06-12 23:55:16 -04005601 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005602 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005603 case GL_INT:
5604 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005605 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005606 default:
5607 return error(GL_INVALID_ENUM);
5608 }
5609
5610 if(stride < 0)
5611 {
5612 return error(GL_INVALID_VALUE);
5613 }
5614
Chris Forbes108f3e12018-08-30 19:41:59 -07005615 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005616
5617 if(context)
5618 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005619 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5620 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5621 {
5622 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5623 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5624 return error(GL_INVALID_OPERATION);
5625 }
5626
Alexis Hetu6f284032017-12-11 15:19:36 -05005627 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005628 }
5629}
5630
5631void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5632{
5633 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5634
5635 if(width < 0 || height < 0)
5636 {
5637 return error(GL_INVALID_VALUE);
5638 }
5639
Chris Forbes108f3e12018-08-30 19:41:59 -07005640 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005641
5642 if(context)
5643 {
5644 context->setViewportParams(x, y, width, height);
5645 }
5646}
5647
Alexis Hetub9dda642016-10-06 11:25:32 -04005648static 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 -04005649{
5650 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5651 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5652 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5653 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5654
5655 switch(filter)
5656 {
5657 case GL_NEAREST:
5658 break;
5659 default:
5660 return error(GL_INVALID_ENUM);
5661 }
5662
5663 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5664 {
5665 return error(GL_INVALID_VALUE);
5666 }
5667
Chris Forbes108f3e12018-08-30 19:41:59 -07005668 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005669
5670 if(context)
5671 {
5672 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5673 {
5674 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5675 return error(GL_INVALID_OPERATION);
5676 }
5677
Alexis Hetub9dda642016-10-06 11:25:32 -04005678 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005679 }
5680}
5681
Alexis Hetub9dda642016-10-06 11:25:32 -04005682void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5683{
5684 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
5685}
5686
Nicolas Capens0bac2852016-05-07 06:09:58 -04005687void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5688 GLbitfield mask, GLenum filter)
5689{
5690 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5691 {
5692 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5693 return error(GL_INVALID_OPERATION);
5694 }
5695
Alexis Hetub9dda642016-10-06 11:25:32 -04005696 BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005697}
5698
5699void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005700 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005701{
5702 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5703 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005704 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5705 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005706
5707 switch(target)
5708 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005709 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005710 switch(format)
5711 {
5712 case GL_DEPTH_COMPONENT:
5713 case GL_DEPTH_STENCIL_OES:
5714 return error(GL_INVALID_OPERATION);
5715 default:
5716 break;
5717 }
5718 break;
5719 default:
5720 return error(GL_INVALID_ENUM);
5721 }
5722
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005723 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005724 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005725 return error(GL_INVALID_OPERATION);
5726 }
5727
Nicolas Capens83463112018-06-12 23:55:16 -04005728 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005729 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005730 {
5731 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005732 }
5733
5734 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5735 {
5736 return error(GL_INVALID_VALUE);
5737 }
5738
Nicolas Capensefdf1032018-05-08 16:03:16 -04005739 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005740 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5741 {
5742 return error(GL_INVALID_VALUE);
5743 }
5744
5745 if(border != 0)
5746 {
5747 return error(GL_INVALID_VALUE);
5748 }
5749
Chris Forbes108f3e12018-08-30 19:41:59 -07005750 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005751
5752 if(context)
5753 {
5754 es2::Texture3D *texture = context->getTexture3D();
5755
5756 if(!texture)
5757 {
5758 return error(GL_INVALID_OPERATION);
5759 }
5760
Nicolas Capens2fc90512018-01-23 22:24:22 +00005761 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005762 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005763 {
5764 return error(validationError);
5765 }
5766
Nicolas Capens894858a2018-03-22 00:55:23 -04005767 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005768 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005769 }
5770}
5771
Alexis Hetu53f48092016-06-17 14:08:06 -04005772void 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 -04005773{
5774 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5775 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005776 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5777 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005778
5779 switch(target)
5780 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005781 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005782 break;
5783 default:
5784 return error(GL_INVALID_ENUM);
5785 }
5786
Nicolas Capens0bac2852016-05-07 06:09:58 -04005787 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5788 {
5789 return error(GL_INVALID_VALUE);
5790 }
5791
5792 if((width < 0) || (height < 0) || (depth < 0))
5793 {
5794 return error(GL_INVALID_VALUE);
5795 }
5796
Chris Forbes108f3e12018-08-30 19:41:59 -07005797 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005798
5799 if(context)
5800 {
5801 es2::Texture3D *texture = context->getTexture3D();
5802
Nicolas Capens83463112018-06-12 23:55:16 -04005803 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005804 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005805 {
5806 return error(validationError);
5807 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005808
Nicolas Capens5555af42017-12-14 13:14:03 -05005809 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005810 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005811 {
5812 return error(validationError);
5813 }
5814
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005815 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005816 }
5817}
5818
5819void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5820{
5821 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5822 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5823 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5824
5825 switch(target)
5826 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005827 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005828 break;
5829 default:
5830 return error(GL_INVALID_ENUM);
5831 }
5832
5833 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5834 {
5835 return error(GL_INVALID_VALUE);
5836 }
5837
Chris Forbes108f3e12018-08-30 19:41:59 -07005838 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005839
5840 if(context)
5841 {
5842 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5843
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005844 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005845 {
5846 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5847 }
5848
5849 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5850
5851 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5852 {
5853 return error(GL_INVALID_OPERATION);
5854 }
5855
5856 es2::Texture3D *texture = context->getTexture3D();
5857
Nicolas Capens83463112018-06-12 23:55:16 -04005858 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 -05005859 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005860 {
5861 return error(validationError);
5862 }
5863
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005864 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005865 }
5866}
5867
5868void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5869{
5870 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5871 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5872 target, level, internalformat, width, height, depth, border, imageSize, data);
5873
5874 switch(target)
5875 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005876 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005877 break;
5878 default:
5879 return error(GL_INVALID_ENUM);
5880 }
5881
5882 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5883 {
5884 return error(GL_INVALID_VALUE);
5885 }
5886
Nicolas Capensefdf1032018-05-08 16:03:16 -04005887 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005888 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5889 {
5890 return error(GL_INVALID_VALUE);
5891 }
5892
Nicolas Capens83463112018-06-12 23:55:16 -04005893 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005894 {
Nicolas Capens03589982018-02-01 17:28:32 -05005895 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005896 }
5897
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005898 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005899 {
5900 return error(GL_INVALID_VALUE);
5901 }
5902
Chris Forbes108f3e12018-08-30 19:41:59 -07005903 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005904
5905 if(context)
5906 {
5907 es2::Texture3D *texture = context->getTexture3D();
5908
5909 if(!texture)
5910 {
5911 return error(GL_INVALID_OPERATION);
5912 }
5913
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005914 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005915
Nicolas Capense65f5642018-02-26 17:47:06 -05005916 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005917 {
5918 return error(validationError);
5919 }
5920
Nicolas Capens0bac2852016-05-07 06:09:58 -04005921 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5922 }
5923}
5924
5925void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5926{
5927 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5928 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5929 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5930 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5931
5932 switch(target)
5933 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005934 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005935 break;
5936 default:
5937 return error(GL_INVALID_ENUM);
5938 }
5939
5940 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5941 {
5942 return error(GL_INVALID_VALUE);
5943 }
5944
5945 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5946 {
5947 return error(GL_INVALID_VALUE);
5948 }
5949
Nicolas Capens83463112018-06-12 23:55:16 -04005950 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005951 {
Nicolas Capens03589982018-02-01 17:28:32 -05005952 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005953 }
5954
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005955 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005956 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005957 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005958 }
5959
Chris Forbes108f3e12018-08-30 19:41:59 -07005960 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005961
5962 if(context)
5963 {
5964 es2::Texture3D *texture = context->getTexture3D();
5965
5966 if(!texture)
5967 {
5968 return error(GL_INVALID_OPERATION);
5969 }
5970
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005971 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005972 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005973 {
5974 return error(validationError);
5975 }
5976
5977 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005978 }
5979}
5980
5981void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5982{
5983 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5984 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5985
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005986 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005987 {
5988 return error(GL_INVALID_ENUM);
5989 }
5990
Chris Forbes108f3e12018-08-30 19:41:59 -07005991 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005992
5993 if(context)
5994 {
5995 if(texture == 0)
5996 {
5997 textarget = GL_NONE;
5998 }
5999 else
6000 {
6001 es2::Texture *tex = context->getTexture(texture);
6002
6003 if(!tex)
6004 {
6005 return error(GL_INVALID_OPERATION);
6006 }
6007
Nicolas Capens0bac2852016-05-07 06:09:58 -04006008 switch(textarget)
6009 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006010 case GL_TEXTURE_3D:
6011 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006012 {
6013 return error(GL_INVALID_OPERATION);
6014 }
6015 break;
6016 default:
6017 return error(GL_INVALID_ENUM);
6018 }
6019
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006020 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006021 {
6022 return error(GL_INVALID_VALUE);
6023 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006024
6025 if(tex->isCompressed(textarget, level))
6026 {
6027 return error(GL_INVALID_OPERATION);
6028 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006029 }
6030
6031 es2::Framebuffer *framebuffer = nullptr;
6032 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006033 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006034 {
6035 framebuffer = context->getReadFramebuffer();
6036 framebufferName = context->getReadFramebufferName();
6037 }
6038 else
6039 {
6040 framebuffer = context->getDrawFramebuffer();
6041 framebufferName = context->getDrawFramebufferName();
6042 }
6043
6044 if(framebufferName == 0 || !framebuffer)
6045 {
6046 return error(GL_INVALID_OPERATION);
6047 }
6048
Nicolas Capens0bac2852016-05-07 06:09:58 -04006049 switch(attachment)
6050 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006051 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6052 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006053 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006054 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6055 {
6056 return error(GL_INVALID_ENUM);
6057 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006058 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006059 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006060 }
6061 }
6062}
6063
6064void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6065{
6066 if(egl::getClientVersion() == 1)
6067 {
6068 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6069 }
6070
6071 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6072
6073 switch(target)
6074 {
6075 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006076 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006077 case GL_TEXTURE_EXTERNAL_OES:
6078 break;
6079 default:
6080 return error(GL_INVALID_ENUM);
6081 }
6082
Chris Forbes108f3e12018-08-30 19:41:59 -07006083 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006084
6085 if(context)
6086 {
Alexis Hetu46768622018-01-16 22:09:28 -05006087 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006088
6089 if(!texture)
6090 {
6091 return error(GL_INVALID_OPERATION);
6092 }
6093
Nicolas Capens58df2f62016-06-07 14:48:56 -04006094 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006095
Nicolas Capens58df2f62016-06-07 14:48:56 -04006096 if(!eglImage)
6097 {
6098 return error(GL_INVALID_OPERATION);
6099 }
6100
6101 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006102 }
6103}
6104
6105void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6106{
6107 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6108
6109 UNIMPLEMENTED();
6110}
6111
6112GLboolean IsRenderbufferOES(GLuint renderbuffer)
6113{
6114 return IsRenderbuffer(renderbuffer);
6115}
6116
6117void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6118{
6119 BindRenderbuffer(target, renderbuffer);
6120}
6121
6122void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6123{
6124 DeleteRenderbuffers(n, renderbuffers);
6125}
6126
6127void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6128{
6129 GenRenderbuffers(n, renderbuffers);
6130}
6131
6132void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6133{
6134 RenderbufferStorage(target, internalformat, width, height);
6135}
6136
6137void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6138{
6139 GetRenderbufferParameteriv(target, pname, params);
6140}
6141
6142GLboolean IsFramebufferOES(GLuint framebuffer)
6143{
6144 return IsFramebuffer(framebuffer);
6145}
6146
6147void BindFramebufferOES(GLenum target, GLuint framebuffer)
6148{
6149 BindFramebuffer(target, framebuffer);
6150}
6151
6152void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6153{
6154 DeleteFramebuffers(n, framebuffers);
6155}
6156
6157void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6158{
6159 GenFramebuffers(n, framebuffers);
6160}
6161
6162GLenum CheckFramebufferStatusOES(GLenum target)
6163{
6164 return CheckFramebufferStatus(target);
6165}
6166
6167void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6168{
6169 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6170}
6171
6172void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6173{
6174 FramebufferTexture2D(target, attachment, textarget, texture, level);
6175}
6176
6177void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6178{
6179 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6180}
6181
6182void GenerateMipmapOES(GLenum target)
6183{
6184 GenerateMipmap(target);
6185}
6186
6187void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6188{
6189 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6190
6191 if(n < 0 || n > MAX_DRAW_BUFFERS)
6192 {
6193 return error(GL_INVALID_VALUE);
6194 }
6195
Chris Forbes108f3e12018-08-30 19:41:59 -07006196 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006197
6198 if(context)
6199 {
6200 GLuint drawFramebufferName = context->getDrawFramebufferName();
6201
6202 if((drawFramebufferName == 0) && (n != 1))
6203 {
6204 return error(GL_INVALID_OPERATION);
6205 }
6206
6207 for(unsigned int i = 0; i < (unsigned)n; i++)
6208 {
6209 switch(bufs[i])
6210 {
6211 case GL_BACK:
6212 if(drawFramebufferName != 0)
6213 {
6214 return error(GL_INVALID_OPERATION);
6215 }
6216 break;
6217 case GL_NONE:
6218 break;
6219 case GL_COLOR_ATTACHMENT0_EXT:
6220 case GL_COLOR_ATTACHMENT1_EXT:
6221 case GL_COLOR_ATTACHMENT2_EXT:
6222 case GL_COLOR_ATTACHMENT3_EXT:
6223 case GL_COLOR_ATTACHMENT4_EXT:
6224 case GL_COLOR_ATTACHMENT5_EXT:
6225 case GL_COLOR_ATTACHMENT6_EXT:
6226 case GL_COLOR_ATTACHMENT7_EXT:
6227 case GL_COLOR_ATTACHMENT8_EXT:
6228 case GL_COLOR_ATTACHMENT9_EXT:
6229 case GL_COLOR_ATTACHMENT10_EXT:
6230 case GL_COLOR_ATTACHMENT11_EXT:
6231 case GL_COLOR_ATTACHMENT12_EXT:
6232 case GL_COLOR_ATTACHMENT13_EXT:
6233 case GL_COLOR_ATTACHMENT14_EXT:
6234 case GL_COLOR_ATTACHMENT15_EXT:
6235 {
6236 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6237
6238 if(index >= MAX_COLOR_ATTACHMENTS)
6239 {
6240 return error(GL_INVALID_OPERATION);
6241 }
6242
6243 if(index != i)
6244 {
6245 return error(GL_INVALID_OPERATION);
6246 }
6247
6248 if(drawFramebufferName == 0)
6249 {
6250 return error(GL_INVALID_OPERATION);
6251 }
6252 }
6253 break;
6254 default:
6255 return error(GL_INVALID_ENUM);
6256 }
6257 }
6258
6259 context->setFramebufferDrawBuffers(n, bufs);
6260 }
6261}
6262
6263}
6264
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006265extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006266{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006267 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006268 {
6269 const char *name;
6270 __eglMustCastToProperFunctionPointerType address;
6271 };
6272
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006273 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006274 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006275 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
6276
6277 FUNCTION(glActiveTexture),
6278 FUNCTION(glAttachShader),
6279 FUNCTION(glBeginQuery),
6280 FUNCTION(glBeginQueryEXT),
6281 FUNCTION(glBeginTransformFeedback),
6282 FUNCTION(glBindAttribLocation),
6283 FUNCTION(glBindBuffer),
6284 FUNCTION(glBindBufferBase),
6285 FUNCTION(glBindBufferRange),
6286 FUNCTION(glBindFramebuffer),
6287 FUNCTION(glBindFramebufferOES),
6288 FUNCTION(glBindRenderbuffer),
6289 FUNCTION(glBindRenderbufferOES),
6290 FUNCTION(glBindSampler),
6291 FUNCTION(glBindTexture),
6292 FUNCTION(glBindTransformFeedback),
6293 FUNCTION(glBindVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006294 FUNCTION(glBindVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006295 FUNCTION(glBlendColor),
6296 FUNCTION(glBlendEquation),
6297 FUNCTION(glBlendEquationSeparate),
6298 FUNCTION(glBlendFunc),
6299 FUNCTION(glBlendFuncSeparate),
6300 FUNCTION(glBlitFramebuffer),
6301 FUNCTION(glBlitFramebufferANGLE),
6302 FUNCTION(glBufferData),
6303 FUNCTION(glBufferSubData),
6304 FUNCTION(glCheckFramebufferStatus),
6305 FUNCTION(glCheckFramebufferStatusOES),
6306 FUNCTION(glClear),
6307 FUNCTION(glClearBufferfi),
6308 FUNCTION(glClearBufferfv),
6309 FUNCTION(glClearBufferiv),
6310 FUNCTION(glClearBufferuiv),
6311 FUNCTION(glClearColor),
6312 FUNCTION(glClearDepthf),
6313 FUNCTION(glClearStencil),
6314 FUNCTION(glClientWaitSync),
6315 FUNCTION(glColorMask),
6316 FUNCTION(glCompileShader),
6317 FUNCTION(glCompressedTexImage2D),
6318 FUNCTION(glCompressedTexImage3D),
6319 FUNCTION(glCompressedTexSubImage2D),
6320 FUNCTION(glCompressedTexSubImage3D),
6321 FUNCTION(glCopyBufferSubData),
6322 FUNCTION(glCopyTexImage2D),
6323 FUNCTION(glCopyTexSubImage2D),
6324 FUNCTION(glCopyTexSubImage3D),
6325 FUNCTION(glCreateProgram),
6326 FUNCTION(glCreateShader),
6327 FUNCTION(glCullFace),
6328 FUNCTION(glDeleteBuffers),
6329 FUNCTION(glDeleteFencesNV),
6330 FUNCTION(glDeleteFramebuffers),
6331 FUNCTION(glDeleteFramebuffersOES),
6332 FUNCTION(glDeleteProgram),
6333 FUNCTION(glDeleteQueries),
6334 FUNCTION(glDeleteQueriesEXT),
6335 FUNCTION(glDeleteRenderbuffers),
6336 FUNCTION(glDeleteRenderbuffersOES),
6337 FUNCTION(glDeleteSamplers),
6338 FUNCTION(glDeleteShader),
6339 FUNCTION(glDeleteSync),
6340 FUNCTION(glDeleteTextures),
6341 FUNCTION(glDeleteTransformFeedbacks),
6342 FUNCTION(glDeleteVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006343 FUNCTION(glDeleteVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006344 FUNCTION(glDepthFunc),
Nicolas Capens659d89e2018-06-22 13:57:37 -04006345 //FUNCTION(DepthFunc),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006346 FUNCTION(glDepthMask),
6347 FUNCTION(glDepthRangef),
6348 FUNCTION(glDetachShader),
6349 FUNCTION(glDisable),
6350 FUNCTION(glDisableVertexAttribArray),
6351 FUNCTION(glDrawArrays),
6352 FUNCTION(glDrawArraysInstanced),
6353 FUNCTION(glDrawBuffers),
6354 FUNCTION(glDrawBuffersEXT),
6355 FUNCTION(glDrawElements),
6356 FUNCTION(glDrawElementsInstanced),
6357 FUNCTION(glDrawRangeElements),
6358 FUNCTION(glEGLImageTargetRenderbufferStorageOES),
6359 FUNCTION(glEGLImageTargetTexture2DOES),
6360 FUNCTION(glEnable),
6361 FUNCTION(glEnableVertexAttribArray),
6362 FUNCTION(glEndQuery),
6363 FUNCTION(glEndQueryEXT),
6364 FUNCTION(glEndTransformFeedback),
6365 FUNCTION(glFenceSync),
6366 FUNCTION(glFinish),
6367 FUNCTION(glFinishFenceNV),
6368 FUNCTION(glFlush),
6369 FUNCTION(glFlushMappedBufferRange),
6370 FUNCTION(glFramebufferRenderbuffer),
6371 FUNCTION(glFramebufferRenderbufferOES),
6372 FUNCTION(glFramebufferTexture2D),
6373 FUNCTION(glFramebufferTexture2DOES),
6374 FUNCTION(glFramebufferTextureLayer),
6375 FUNCTION(glFrontFace),
6376 FUNCTION(glGenBuffers),
6377 FUNCTION(glGenFencesNV),
6378 FUNCTION(glGenFramebuffers),
6379 FUNCTION(glGenFramebuffersOES),
6380 FUNCTION(glGenQueries),
6381 FUNCTION(glGenQueriesEXT),
6382 FUNCTION(glGenRenderbuffers),
6383 FUNCTION(glGenRenderbuffersOES),
6384 FUNCTION(glGenSamplers),
6385 FUNCTION(glGenTextures),
6386 FUNCTION(glGenTransformFeedbacks),
6387 FUNCTION(glGenVertexArrays),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006388 FUNCTION(glGenVertexArraysOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006389 FUNCTION(glGenerateMipmap),
6390 FUNCTION(glGenerateMipmapOES),
6391 FUNCTION(glGetActiveAttrib),
6392 FUNCTION(glGetActiveUniform),
6393 FUNCTION(glGetActiveUniformBlockName),
6394 FUNCTION(glGetActiveUniformBlockiv),
6395 FUNCTION(glGetActiveUniformsiv),
6396 FUNCTION(glGetAttachedShaders),
6397 FUNCTION(glGetAttribLocation),
6398 FUNCTION(glGetBooleanv),
6399 FUNCTION(glGetBufferParameteri64v),
6400 FUNCTION(glGetBufferParameteriv),
6401 FUNCTION(glGetBufferPointerv),
6402 FUNCTION(glGetError),
6403 FUNCTION(glGetFenceivNV),
6404 FUNCTION(glGetFloatv),
6405 FUNCTION(glGetFragDataLocation),
6406 FUNCTION(glGetFramebufferAttachmentParameteriv),
6407 FUNCTION(glGetFramebufferAttachmentParameterivOES),
6408 FUNCTION(glGetGraphicsResetStatusEXT),
6409 FUNCTION(glGetInteger64i_v),
6410 FUNCTION(glGetInteger64v),
6411 FUNCTION(glGetIntegeri_v),
6412 FUNCTION(glGetIntegerv),
6413 FUNCTION(glGetInternalformativ),
6414 FUNCTION(glGetProgramBinary),
6415 FUNCTION(glGetProgramInfoLog),
6416 FUNCTION(glGetProgramiv),
6417 FUNCTION(glGetQueryObjectuiv),
6418 FUNCTION(glGetQueryObjectuivEXT),
6419 FUNCTION(glGetQueryiv),
6420 FUNCTION(glGetQueryivEXT),
6421 FUNCTION(glGetRenderbufferParameteriv),
6422 FUNCTION(glGetRenderbufferParameterivOES),
6423 FUNCTION(glGetSamplerParameterfv),
6424 FUNCTION(glGetSamplerParameteriv),
6425 FUNCTION(glGetShaderInfoLog),
6426 FUNCTION(glGetShaderPrecisionFormat),
6427 FUNCTION(glGetShaderSource),
6428 FUNCTION(glGetShaderiv),
6429 FUNCTION(glGetString),
6430 FUNCTION(glGetStringi),
6431 FUNCTION(glGetSynciv),
6432 FUNCTION(glGetTexParameterfv),
6433 FUNCTION(glGetTexParameteriv),
6434 FUNCTION(glGetTransformFeedbackVarying),
6435 FUNCTION(glGetUniformBlockIndex),
6436 FUNCTION(glGetUniformIndices),
6437 FUNCTION(glGetUniformLocation),
6438 FUNCTION(glGetUniformfv),
6439 FUNCTION(glGetUniformiv),
6440 FUNCTION(glGetUniformuiv),
6441 FUNCTION(glGetVertexAttribIiv),
6442 FUNCTION(glGetVertexAttribIuiv),
6443 FUNCTION(glGetVertexAttribPointerv),
6444 FUNCTION(glGetVertexAttribfv),
6445 FUNCTION(glGetVertexAttribiv),
6446 FUNCTION(glGetnUniformfvEXT),
6447 FUNCTION(glGetnUniformivEXT),
6448 FUNCTION(glHint),
6449 FUNCTION(glInvalidateFramebuffer),
6450 FUNCTION(glInvalidateSubFramebuffer),
6451 FUNCTION(glIsBuffer),
6452 FUNCTION(glIsEnabled),
6453 FUNCTION(glIsFenceNV),
6454 FUNCTION(glIsFramebuffer),
6455 FUNCTION(glIsFramebufferOES),
6456 FUNCTION(glIsProgram),
6457 FUNCTION(glIsQuery),
6458 FUNCTION(glIsQueryEXT),
6459 FUNCTION(glIsRenderbuffer),
6460 FUNCTION(glIsRenderbufferOES),
6461 FUNCTION(glIsSampler),
6462 FUNCTION(glIsShader),
6463 FUNCTION(glIsSync),
6464 FUNCTION(glIsTexture),
6465 FUNCTION(glIsTransformFeedback),
6466 FUNCTION(glIsVertexArray),
Krzysztof Kosińskie4756742018-05-10 21:55:05 -07006467 FUNCTION(glIsVertexArrayOES),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006468 FUNCTION(glLineWidth),
6469 FUNCTION(glLinkProgram),
6470 FUNCTION(glMapBufferRange),
6471 FUNCTION(glPauseTransformFeedback),
6472 FUNCTION(glPixelStorei),
6473 FUNCTION(glPolygonOffset),
6474 FUNCTION(glProgramBinary),
6475 FUNCTION(glProgramParameteri),
6476 FUNCTION(glReadBuffer),
6477 FUNCTION(glReadPixels),
6478 FUNCTION(glReadnPixelsEXT),
6479 FUNCTION(glReleaseShaderCompiler),
6480 FUNCTION(glRenderbufferStorage),
6481 FUNCTION(glRenderbufferStorageMultisample),
6482 FUNCTION(glRenderbufferStorageMultisampleANGLE),
6483 FUNCTION(glRenderbufferStorageOES),
6484 FUNCTION(glResumeTransformFeedback),
6485 FUNCTION(glSampleCoverage),
6486 FUNCTION(glSamplerParameterf),
6487 FUNCTION(glSamplerParameterfv),
6488 FUNCTION(glSamplerParameteri),
6489 FUNCTION(glSamplerParameteriv),
6490 FUNCTION(glScissor),
6491 FUNCTION(glSetFenceNV),
6492 FUNCTION(glShaderBinary),
6493 FUNCTION(glShaderSource),
6494 FUNCTION(glStencilFunc),
6495 FUNCTION(glStencilFuncSeparate),
6496 FUNCTION(glStencilMask),
6497 FUNCTION(glStencilMaskSeparate),
6498 FUNCTION(glStencilOp),
6499 FUNCTION(glStencilOpSeparate),
6500 FUNCTION(glTestFenceNV),
6501 FUNCTION(glTexImage2D),
6502 FUNCTION(glTexImage3D),
6503 FUNCTION(glTexImage3DOES),
6504 FUNCTION(glTexParameterf),
6505 FUNCTION(glTexParameterfv),
6506 FUNCTION(glTexParameteri),
6507 FUNCTION(glTexParameteriv),
6508 FUNCTION(glTexStorage2D),
6509 FUNCTION(glTexStorage3D),
6510 FUNCTION(glTexSubImage2D),
6511 FUNCTION(glTexSubImage3D),
6512 FUNCTION(glTransformFeedbackVaryings),
6513 FUNCTION(glUniform1f),
6514 FUNCTION(glUniform1fv),
6515 FUNCTION(glUniform1i),
6516 FUNCTION(glUniform1iv),
6517 FUNCTION(glUniform1ui),
6518 FUNCTION(glUniform1uiv),
6519 FUNCTION(glUniform2f),
6520 FUNCTION(glUniform2fv),
6521 FUNCTION(glUniform2i),
6522 FUNCTION(glUniform2iv),
6523 FUNCTION(glUniform2ui),
6524 FUNCTION(glUniform2uiv),
6525 FUNCTION(glUniform3f),
6526 FUNCTION(glUniform3fv),
6527 FUNCTION(glUniform3i),
6528 FUNCTION(glUniform3iv),
6529 FUNCTION(glUniform3ui),
6530 FUNCTION(glUniform3uiv),
6531 FUNCTION(glUniform4f),
6532 FUNCTION(glUniform4fv),
6533 FUNCTION(glUniform4i),
6534 FUNCTION(glUniform4iv),
6535 FUNCTION(glUniform4ui),
6536 FUNCTION(glUniform4uiv),
6537 FUNCTION(glUniformBlockBinding),
6538 FUNCTION(glUniformMatrix2fv),
6539 FUNCTION(glUniformMatrix2x3fv),
6540 FUNCTION(glUniformMatrix2x4fv),
6541 FUNCTION(glUniformMatrix3fv),
6542 FUNCTION(glUniformMatrix3x2fv),
6543 FUNCTION(glUniformMatrix3x4fv),
6544 FUNCTION(glUniformMatrix4fv),
6545 FUNCTION(glUniformMatrix4x2fv),
6546 FUNCTION(glUniformMatrix4x3fv),
6547 FUNCTION(glUnmapBuffer),
6548 FUNCTION(glUseProgram),
6549 FUNCTION(glValidateProgram),
6550 FUNCTION(glVertexAttrib1f),
6551 FUNCTION(glVertexAttrib1fv),
6552 FUNCTION(glVertexAttrib2f),
6553 FUNCTION(glVertexAttrib2fv),
6554 FUNCTION(glVertexAttrib3f),
6555 FUNCTION(glVertexAttrib3fv),
6556 FUNCTION(glVertexAttrib4f),
6557 FUNCTION(glVertexAttrib4fv),
6558 FUNCTION(glVertexAttribDivisor),
Adrienne Walker050ef942018-06-20 15:43:05 -07006559 FUNCTION(glVertexAttribDivisorANGLE),
6560 FUNCTION(glVertexAttribDivisorEXT),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006561 FUNCTION(glVertexAttribI4i),
6562 FUNCTION(glVertexAttribI4iv),
6563 FUNCTION(glVertexAttribI4ui),
6564 FUNCTION(glVertexAttribI4uiv),
6565 FUNCTION(glVertexAttribIPointer),
6566 FUNCTION(glVertexAttribPointer),
6567 FUNCTION(glViewport),
6568 FUNCTION(glWaitSync),
6569
6570 #undef FUNCTION
6571 };
6572
6573 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6574 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6575
Nicolas Capens48908cb2018-01-08 13:07:14 -05006576 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6577 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6578 #ifndef NDEBUG
6579 for(size_t i = 0; i < numFunctions - 1; i++)
6580 {
6581 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6582 }
6583 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006584
6585 if(procname && strncmp("gl", procname, 2) == 0)
6586 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006587 struct CompareFunctor
6588 {
6589 bool operator()(const Function &a, const Function &b) const
6590 {
6591 return strcmp(a.name, b.name) < 0;
6592 }
6593 };
6594
6595 Function needle;
6596 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006597 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006598
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006599 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006600 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006601 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006602 }
6603 }
6604
6605 return nullptr;
6606}