blob: fd856e58ddf7e4d2f255bd589d4e9545dce73355 [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{
Nicolas Capens805d7612018-08-02 13:56:32 -040045 if(level < 0 || level >= IMPLEMENTATION_MAX_TEXTURE_LEVELS || width < 0 || height < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -040046 {
47 return false;
48 }
49
50 return true;
51}
52
Nicolas Capens805d7612018-08-02 13:56:32 -040053}
54
55namespace gl
56{
57
58using namespace es2;
59
Nicolas Capens0bac2852016-05-07 06:09:58 -040060void ActiveTexture(GLenum texture)
61{
62 TRACE("(GLenum texture = 0x%X)", texture);
63
Chris Forbes108f3e12018-08-30 19:41:59 -070064 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040065
66 if(context)
67 {
68 if(texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1)
69 {
70 return error(GL_INVALID_ENUM);
71 }
72
73 context->setActiveSampler(texture - GL_TEXTURE0);
74 }
75}
76
77void AttachShader(GLuint program, GLuint shader)
78{
79 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
80
Chris Forbes108f3e12018-08-30 19:41:59 -070081 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -040082
83 if(context)
84 {
85 es2::Program *programObject = context->getProgram(program);
86 es2::Shader *shaderObject = context->getShader(shader);
87
88 if(!programObject)
89 {
90 if(context->getShader(program))
91 {
92 return error(GL_INVALID_OPERATION);
93 }
94 else
95 {
96 return error(GL_INVALID_VALUE);
97 }
98 }
99
100 if(!shaderObject)
101 {
102 if(context->getProgram(shader))
103 {
104 return error(GL_INVALID_OPERATION);
105 }
106 else
107 {
108 return error(GL_INVALID_VALUE);
109 }
110 }
111
112 if(!programObject->attachShader(shaderObject))
113 {
114 return error(GL_INVALID_OPERATION);
115 }
116 }
117}
118
119void BeginQueryEXT(GLenum target, GLuint name)
120{
121 TRACE("(GLenum target = 0x%X, GLuint name = %d)", target, name);
122
123 switch(target)
124 {
125 case GL_ANY_SAMPLES_PASSED_EXT:
126 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
127 break;
128 default:
129 return error(GL_INVALID_ENUM);
130 }
131
132 if(name == 0)
133 {
134 return error(GL_INVALID_OPERATION);
135 }
136
Chris Forbes108f3e12018-08-30 19:41:59 -0700137 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400138
139 if(context)
140 {
141 context->beginQuery(target, name);
142 }
143}
144
145void BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
146{
147 TRACE("(GLuint program = %d, GLuint index = %d, const GLchar* name = %s)", program, index, name);
148
149 if(index >= es2::MAX_VERTEX_ATTRIBS)
150 {
151 return error(GL_INVALID_VALUE);
152 }
153
Chris Forbes108f3e12018-08-30 19:41:59 -0700154 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400155
156 if(context)
157 {
158 es2::Program *programObject = context->getProgram(program);
159
160 if(!programObject)
161 {
162 if(context->getShader(program))
163 {
164 return error(GL_INVALID_OPERATION);
165 }
166 else
167 {
168 return error(GL_INVALID_VALUE);
169 }
170 }
171
172 if(strncmp(name, "gl_", 3) == 0)
173 {
174 return error(GL_INVALID_OPERATION);
175 }
176
177 programObject->bindAttributeLocation(index, name);
178 }
179}
180
181void BindBuffer(GLenum target, GLuint buffer)
182{
183 TRACE("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
184
Chris Forbes108f3e12018-08-30 19:41:59 -0700185 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400186
187 if(context)
188 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400189 switch(target)
190 {
191 case GL_ARRAY_BUFFER:
192 context->bindArrayBuffer(buffer);
193 return;
194 case GL_ELEMENT_ARRAY_BUFFER:
195 context->bindElementArrayBuffer(buffer);
196 return;
197 case GL_COPY_READ_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400198 context->bindCopyReadBuffer(buffer);
199 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400200 case GL_COPY_WRITE_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400201 context->bindCopyWriteBuffer(buffer);
202 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400203 case GL_PIXEL_PACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400204 context->bindPixelPackBuffer(buffer);
205 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 case GL_PIXEL_UNPACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400207 context->bindPixelUnpackBuffer(buffer);
208 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400209 case GL_TRANSFORM_FEEDBACK_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400210 context->bindTransformFeedbackBuffer(buffer);
211 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212 case GL_UNIFORM_BUFFER:
Nicolas Capens83463112018-06-12 23:55:16 -0400213 context->bindGenericUniformBuffer(buffer);
214 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400215 default:
216 return error(GL_INVALID_ENUM);
217 }
218 }
219}
220
221void BindFramebuffer(GLenum target, GLuint framebuffer)
222{
223 TRACE("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
224
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000225 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400226 {
227 return error(GL_INVALID_ENUM);
228 }
229
Chris Forbes108f3e12018-08-30 19:41:59 -0700230 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400231
232 if(context)
233 {
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000234 if(target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400235 {
236 context->bindReadFramebuffer(framebuffer);
237 }
238
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000239 if(target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400240 {
241 context->bindDrawFramebuffer(framebuffer);
242 }
243 }
244}
245
246void BindRenderbuffer(GLenum target, GLuint renderbuffer)
247{
248 TRACE("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
249
250 if(target != GL_RENDERBUFFER)
251 {
252 return error(GL_INVALID_ENUM);
253 }
254
Chris Forbes108f3e12018-08-30 19:41:59 -0700255 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400256
257 if(context)
258 {
259 // [OpenGL ES 2.0.25] Section 4.4.3 page 110
260 // [OpenGL ES 3.0.4] Section 4.4.2 page 204
261 // If renderbuffer is not zero, then the resulting renderbuffer object
262 // is a new state vector, initialized with a zero-sized memory buffer.
263 context->bindRenderbuffer(renderbuffer);
264 }
265}
266
267void BindTexture(GLenum target, GLuint texture)
268{
269 TRACE("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
270
Chris Forbes108f3e12018-08-30 19:41:59 -0700271 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400272
273 if(context)
274 {
275 es2::Texture *textureObject = context->getTexture(texture);
276
277 if(textureObject && textureObject->getTarget() != target && texture != 0)
278 {
279 return error(GL_INVALID_OPERATION);
280 }
281
Nicolas Capens0bac2852016-05-07 06:09:58 -0400282 switch(target)
283 {
284 case GL_TEXTURE_2D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500285 context->bindTexture(TEXTURE_2D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400286 break;
287 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500288 context->bindTexture(TEXTURE_CUBE, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400289 break;
290 case GL_TEXTURE_EXTERNAL_OES:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500291 context->bindTexture(TEXTURE_EXTERNAL, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400292 break;
293 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500294 context->bindTexture(TEXTURE_2D_ARRAY, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400295 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -0500296 case GL_TEXTURE_3D:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500297 context->bindTexture(TEXTURE_3D, texture);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400298 break;
Alexis Hetu46768622018-01-16 22:09:28 -0500299 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens2ce08b12018-03-02 12:37:47 -0500300 context->bindTexture(TEXTURE_2D_RECT, texture);
Alexis Hetu46768622018-01-16 22:09:28 -0500301 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400302 default:
303 return error(GL_INVALID_ENUM);
304 }
305 }
306}
307
308void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
309{
310 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
311 red, green, blue, alpha);
312
Chris Forbes108f3e12018-08-30 19:41:59 -0700313 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400314
315 if(context)
316 {
317 context->setBlendColor(es2::clamp01(red), es2::clamp01(green), es2::clamp01(blue), es2::clamp01(alpha));
318 }
319}
320
Nicolas Capens0bac2852016-05-07 06:09:58 -0400321void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
322{
323 TRACE("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
324
325 switch(modeRGB)
326 {
327 case GL_FUNC_ADD:
328 case GL_FUNC_SUBTRACT:
329 case GL_FUNC_REVERSE_SUBTRACT:
330 case GL_MIN_EXT:
331 case GL_MAX_EXT:
332 break;
333 default:
334 return error(GL_INVALID_ENUM);
335 }
336
337 switch(modeAlpha)
338 {
339 case GL_FUNC_ADD:
340 case GL_FUNC_SUBTRACT:
341 case GL_FUNC_REVERSE_SUBTRACT:
342 case GL_MIN_EXT:
343 case GL_MAX_EXT:
344 break;
345 default:
346 return error(GL_INVALID_ENUM);
347 }
348
Chris Forbes108f3e12018-08-30 19:41:59 -0700349 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400350
351 if(context)
352 {
353 context->setBlendEquation(modeRGB, modeAlpha);
354 }
355}
356
Nicolas Capens805d7612018-08-02 13:56:32 -0400357void BlendEquation(GLenum mode)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400358{
Nicolas Capens805d7612018-08-02 13:56:32 -0400359 BlendEquationSeparate(mode, mode);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400360}
361
362void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
363{
364 TRACE("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
365 srcRGB, dstRGB, srcAlpha, dstAlpha);
366
Nicolas Capens0bac2852016-05-07 06:09:58 -0400367 switch(srcRGB)
368 {
369 case GL_ZERO:
370 case GL_ONE:
371 case GL_SRC_COLOR:
372 case GL_ONE_MINUS_SRC_COLOR:
373 case GL_DST_COLOR:
374 case GL_ONE_MINUS_DST_COLOR:
375 case GL_SRC_ALPHA:
376 case GL_ONE_MINUS_SRC_ALPHA:
377 case GL_DST_ALPHA:
378 case GL_ONE_MINUS_DST_ALPHA:
379 case GL_CONSTANT_COLOR:
380 case GL_ONE_MINUS_CONSTANT_COLOR:
381 case GL_CONSTANT_ALPHA:
382 case GL_ONE_MINUS_CONSTANT_ALPHA:
383 case GL_SRC_ALPHA_SATURATE:
384 break;
385 default:
386 return error(GL_INVALID_ENUM);
387 }
388
389 switch(dstRGB)
390 {
391 case GL_ZERO:
392 case GL_ONE:
393 case GL_SRC_COLOR:
394 case GL_ONE_MINUS_SRC_COLOR:
395 case GL_DST_COLOR:
396 case GL_ONE_MINUS_DST_COLOR:
397 case GL_SRC_ALPHA:
398 case GL_ONE_MINUS_SRC_ALPHA:
399 case GL_DST_ALPHA:
400 case GL_ONE_MINUS_DST_ALPHA:
401 case GL_CONSTANT_COLOR:
402 case GL_ONE_MINUS_CONSTANT_COLOR:
403 case GL_CONSTANT_ALPHA:
404 case GL_ONE_MINUS_CONSTANT_ALPHA:
405 break;
406 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400407 break;
408 default:
409 return error(GL_INVALID_ENUM);
410 }
411
412 switch(srcAlpha)
413 {
414 case GL_ZERO:
415 case GL_ONE:
416 case GL_SRC_COLOR:
417 case GL_ONE_MINUS_SRC_COLOR:
418 case GL_DST_COLOR:
419 case GL_ONE_MINUS_DST_COLOR:
420 case GL_SRC_ALPHA:
421 case GL_ONE_MINUS_SRC_ALPHA:
422 case GL_DST_ALPHA:
423 case GL_ONE_MINUS_DST_ALPHA:
424 case GL_CONSTANT_COLOR:
425 case GL_ONE_MINUS_CONSTANT_COLOR:
426 case GL_CONSTANT_ALPHA:
427 case GL_ONE_MINUS_CONSTANT_ALPHA:
428 case GL_SRC_ALPHA_SATURATE:
429 break;
430 default:
431 return error(GL_INVALID_ENUM);
432 }
433
434 switch(dstAlpha)
435 {
436 case GL_ZERO:
437 case GL_ONE:
438 case GL_SRC_COLOR:
439 case GL_ONE_MINUS_SRC_COLOR:
440 case GL_DST_COLOR:
441 case GL_ONE_MINUS_DST_COLOR:
442 case GL_SRC_ALPHA:
443 case GL_ONE_MINUS_SRC_ALPHA:
444 case GL_DST_ALPHA:
445 case GL_ONE_MINUS_DST_ALPHA:
446 case GL_CONSTANT_COLOR:
447 case GL_ONE_MINUS_CONSTANT_COLOR:
448 case GL_CONSTANT_ALPHA:
449 case GL_ONE_MINUS_CONSTANT_ALPHA:
450 break;
451 case GL_SRC_ALPHA_SATURATE:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400452 break;
453 default:
454 return error(GL_INVALID_ENUM);
455 }
456
Chris Forbes108f3e12018-08-30 19:41:59 -0700457 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400458
459 if(context)
460 {
461 context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
462 }
463}
464
Nicolas Capens805d7612018-08-02 13:56:32 -0400465void BlendFunc(GLenum sfactor, GLenum dfactor)
466{
467 BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
468}
469
Nicolas Capens0bac2852016-05-07 06:09:58 -0400470void BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
471{
472 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
473
474 TRACE("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = %p, GLenum usage = %d)",
475 target, size, data, usage);
476
477 if(size < 0)
478 {
479 return error(GL_INVALID_VALUE);
480 }
481
Nicolas Capens0bac2852016-05-07 06:09:58 -0400482 switch(usage)
483 {
484 case GL_STREAM_DRAW:
485 case GL_STATIC_DRAW:
486 case GL_DYNAMIC_DRAW:
487 break;
488 case GL_STREAM_READ:
489 case GL_STREAM_COPY:
490 case GL_STATIC_READ:
491 case GL_STATIC_COPY:
492 case GL_DYNAMIC_READ:
493 case GL_DYNAMIC_COPY:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400494 break;
495 default:
496 return error(GL_INVALID_ENUM);
497 }
498
Chris Forbes108f3e12018-08-30 19:41:59 -0700499 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400500
501 if(context)
502 {
503 es2::Buffer *buffer = nullptr;
504 if(!context->getBuffer(target, &buffer))
505 {
506 return error(GL_INVALID_ENUM);
507 }
508
509 if(!buffer)
510 {
511 // A null buffer means that "0" is bound to the requested buffer target
512 return error(GL_INVALID_OPERATION);
513 }
514
515 buffer->bufferData(data, size, usage);
516 }
517}
518
519void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
520{
521 size = static_cast<GLint>(size); // Work around issues with some 64-bit applications
522 offset = static_cast<GLint>(offset);
523
524 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = %p)",
525 target, offset, size, data);
526
527 if(size < 0 || offset < 0)
528 {
529 return error(GL_INVALID_VALUE);
530 }
531
Chris Forbes108f3e12018-08-30 19:41:59 -0700532 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400533
534 if(context)
535 {
536 es2::Buffer *buffer = nullptr;
537 if(!context->getBuffer(target, &buffer))
538 {
539 return error(GL_INVALID_ENUM);
540 }
541
542 if(!buffer)
543 {
544 // A null buffer means that "0" is bound to the requested buffer target
545 return error(GL_INVALID_OPERATION);
546 }
547
Alexis Hetu6e864492017-11-14 15:27:00 -0500548 if(buffer->isMapped())
549 {
550 // It is an invalid operation to update an already mapped buffer
551 return error(GL_INVALID_OPERATION);
552 }
553
Nicolas Capens0bac2852016-05-07 06:09:58 -0400554 if((size_t)size + offset > buffer->size())
555 {
556 return error(GL_INVALID_VALUE);
557 }
558
559 buffer->bufferSubData(data, size, offset);
560 }
561}
562
563GLenum CheckFramebufferStatus(GLenum target)
564{
565 TRACE("(GLenum target = 0x%X)", target);
566
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000567 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400568 {
569 return error(GL_INVALID_ENUM, 0);
570 }
571
Chris Forbes108f3e12018-08-30 19:41:59 -0700572 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400573
574 if(context)
575 {
576 es2::Framebuffer *framebuffer = nullptr;
Nicolas Capens6c4564a2018-01-26 01:14:34 +0000577 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400578 {
579 framebuffer = context->getReadFramebuffer();
580 }
581 else
582 {
583 framebuffer = context->getDrawFramebuffer();
584 }
585
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400586 if(!framebuffer)
587 {
588 return GL_FRAMEBUFFER_UNDEFINED_OES;
589 }
590
Nicolas Capens0bac2852016-05-07 06:09:58 -0400591 return framebuffer->completeness();
592 }
593
594 return 0;
595}
596
597void Clear(GLbitfield mask)
598{
599 TRACE("(GLbitfield mask = %X)", mask);
600
601 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
602 {
603 return error(GL_INVALID_VALUE);
604 }
605
Chris Forbes108f3e12018-08-30 19:41:59 -0700606 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400607
608 if(context)
609 {
610 context->clear(mask);
611 }
612}
613
614void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
615{
616 TRACE("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
617 red, green, blue, alpha);
618
Chris Forbes108f3e12018-08-30 19:41:59 -0700619 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400620
621 if(context)
622 {
623 context->setClearColor(red, green, blue, alpha);
624 }
625}
626
627void ClearDepthf(GLclampf depth)
628{
629 TRACE("(GLclampf depth = %f)", depth);
630
Chris Forbes108f3e12018-08-30 19:41:59 -0700631 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400632
633 if(context)
634 {
635 context->setClearDepth(depth);
636 }
637}
638
639void ClearStencil(GLint s)
640{
641 TRACE("(GLint s = %d)", s);
642
Chris Forbes108f3e12018-08-30 19:41:59 -0700643 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400644
645 if(context)
646 {
647 context->setClearStencil(s);
648 }
649}
650
651void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
652{
653 TRACE("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)",
654 red, green, blue, alpha);
655
Chris Forbes108f3e12018-08-30 19:41:59 -0700656 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400657
658 if(context)
659 {
Nicolas Capens51814272018-10-15 13:01:22 -0400660 context->setColorMask(red != GL_FALSE, green != GL_FALSE, blue != GL_FALSE, alpha != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400661 }
662}
663
664void CompileShader(GLuint shader)
665{
666 TRACE("(GLuint shader = %d)", shader);
667
Chris Forbes108f3e12018-08-30 19:41:59 -0700668 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400669
670 if(context)
671 {
672 es2::Shader *shaderObject = context->getShader(shader);
673
674 if(!shaderObject)
675 {
676 if(context->getProgram(shader))
677 {
678 return error(GL_INVALID_OPERATION);
679 }
680 else
681 {
682 return error(GL_INVALID_VALUE);
683 }
684 }
685
686 shaderObject->compile();
687 }
688}
689
690void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
691 GLint border, GLsizei imageSize, const GLvoid* data)
692{
693 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
694 "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
695 target, level, internalformat, width, height, border, imageSize, data);
696
697 if(!validImageSize(level, width, height) || border != 0 || imageSize < 0)
698 {
699 return error(GL_INVALID_VALUE);
700 }
701
Nicolas Capens83463112018-06-12 23:55:16 -0400702 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400703 {
Nicolas Capens03589982018-02-01 17:28:32 -0500704 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400705 }
706
707 if(border != 0)
708 {
709 return error(GL_INVALID_VALUE);
710 }
711
Chris Forbes108f3e12018-08-30 19:41:59 -0700712 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400713
714 if(context)
715 {
716 if(level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
717 {
718 return error(GL_INVALID_VALUE);
719 }
720
721 switch(target)
722 {
723 case GL_TEXTURE_2D:
724 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
725 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
726 {
727 return error(GL_INVALID_VALUE);
728 }
729 break;
730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
736 if(width != height)
737 {
738 return error(GL_INVALID_VALUE);
739 }
740
741 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
742 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
743 {
744 return error(GL_INVALID_VALUE);
745 }
746 break;
Alexis Hetu0988fb82018-02-02 17:23:48 -0500747 case GL_TEXTURE_RECTANGLE_ARB: // Rectangle textures cannot be compressed
Nicolas Capens0bac2852016-05-07 06:09:58 -0400748 default:
749 return error(GL_INVALID_ENUM);
750 }
751
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500752 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400753 {
754 return error(GL_INVALID_VALUE);
755 }
756
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500757 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500758 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500759 {
760 return error(validationError);
761 }
762
Alexis Hetu46768622018-01-16 22:09:28 -0500763 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400764 {
Alexis Hetu46768622018-01-16 22:09:28 -0500765 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400766
767 if(!texture)
768 {
769 return error(GL_INVALID_OPERATION);
770 }
771
772 texture->setCompressedImage(level, internalformat, width, height, imageSize, data);
773 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500774 else if(es2::IsCubemapTextureTarget(target))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400775 {
776 es2::TextureCubeMap *texture = context->getTextureCubeMap();
777
778 if(!texture)
779 {
780 return error(GL_INVALID_OPERATION);
781 }
782
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500783 texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400784 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500785 else UNREACHABLE(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400786 }
787}
788
789void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
790 GLenum format, GLsizei imageSize, const GLvoid* data)
791{
792 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
793 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
794 "GLsizei imageSize = %d, const GLvoid* data = %p)",
795 target, level, xoffset, yoffset, width, height, format, imageSize, data);
796
797 if(!es2::IsTextureTarget(target))
798 {
799 return error(GL_INVALID_ENUM);
800 }
801
802 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
803 {
804 return error(GL_INVALID_VALUE);
805 }
806
807 if(xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0)
808 {
809 return error(GL_INVALID_VALUE);
810 }
811
Merck Hung9b768842018-10-16 14:28:26 +0900812 if(!IsCompressed(format))
813 {
814 return error(GL_INVALID_ENUM);
815 }
816
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500817 if(imageSize != gl::ComputeCompressedSize(width, height, format))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400818 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500819 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400820 }
821
Chris Forbes108f3e12018-08-30 19:41:59 -0700822 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400823
824 if(context)
825 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400826 if(xoffset % 4 != 0 || yoffset % 4 != 0)
827 {
828 // We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
829 return error(GL_INVALID_OPERATION);
830 }
831
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500832 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -0500833 if(validationError != GL_NO_ERROR)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500834 {
835 return error(validationError);
836 }
837
Alexis Hetu46768622018-01-16 22:09:28 -0500838 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400839 {
Alexis Hetu46768622018-01-16 22:09:28 -0500840 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400841
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(level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400849 }
850 else if(es2::IsCubemapTextureTarget(target))
851 {
852 es2::TextureCubeMap *texture = context->getTextureCubeMap();
853
Nicolas Capens83463112018-06-12 23:55:16 -0400854 GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -0500855 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400856 {
857 return error(validationError);
858 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -0500859
Nicolas Capenseab70762018-02-06 16:49:36 -0500860 texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400861 }
862 else UNREACHABLE(target);
863 }
864}
865
866void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
867{
868 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
869 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
870 target, level, internalformat, x, y, width, height, border);
871
872 if(!validImageSize(level, width, height))
873 {
874 return error(GL_INVALID_VALUE);
875 }
876
877 if(border != 0)
878 {
879 return error(GL_INVALID_VALUE);
880 }
881
Chris Forbes108f3e12018-08-30 19:41:59 -0700882 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400883
884 if(context)
885 {
886 switch(target)
887 {
Alexis Hetu46768622018-01-16 22:09:28 -0500888 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -0500889 if(level != 0)
890 {
891 return error(GL_INVALID_VALUE);
892 }
Nicolas Capens894858a2018-03-22 00:55:23 -0400893 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -0500894 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400895 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
896 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
897 {
898 return error(GL_INVALID_VALUE);
899 }
900 break;
901 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
902 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
903 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
904 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
905 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
907 if(width != height)
908 {
909 return error(GL_INVALID_VALUE);
910 }
911
912 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
913 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
914 {
915 return error(GL_INVALID_VALUE);
916 }
917 break;
918 default:
919 return error(GL_INVALID_ENUM);
920 }
921
922 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
923
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400924 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400925 {
926 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
927 }
928
929 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
930
931 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
932 {
933 return error(GL_INVALID_OPERATION);
934 }
935
936 GLenum colorbufferFormat = source->getFormat();
937
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500938 // Determine the sized internal format.
939 if(gl::IsUnsizedInternalFormat(internalformat))
940 {
Nicolas Capense1fa9ea2018-07-05 12:13:56 -0400941 if(colorbufferFormat == GL_RGB10_A2)
942 {
943 // Not supported with unsized internalformat.
944 // https://www.khronos.org/members/login/bugzilla/show_bug.cgi?id=9807#c56
945 return error(GL_INVALID_OPERATION);
946 }
947
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500948 if(gl::GetBaseInternalFormat(colorbufferFormat) == internalformat)
949 {
950 internalformat = colorbufferFormat;
951 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400952 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_NORMALIZED && GetRedSize(colorbufferFormat) <= 8)
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500953 {
Nicolas Capens667ab102018-03-22 13:22:20 -0400954 // TODO: Convert to the smallest format that fits all components.
955 // e.g. Copying RGBA4 to RGB should result in RGB565, not RGB8.
956
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500957 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_BYTE);
958 }
Nicolas Capens667ab102018-03-22 13:22:20 -0400959 else if(GetColorComponentType(colorbufferFormat) == GL_INT)
960 {
961 internalformat = gl::GetSizedInternalFormat(internalformat, GL_INT);
962 }
963 else if(GetColorComponentType(colorbufferFormat) == GL_UNSIGNED_INT)
964 {
965 internalformat = gl::GetSizedInternalFormat(internalformat, GL_UNSIGNED_INT);
966 }
967 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 16) // GL_EXT_color_buffer_half_float
968 {
969 internalformat = gl::GetSizedInternalFormat(internalformat, GL_HALF_FLOAT_OES);
970 }
Nicolas Capens659d89e2018-06-22 13:57:37 -0400971 else if(GetColorComponentType(colorbufferFormat) == GL_FLOAT && GetRedSize(colorbufferFormat) == 32) // GL_EXT_color_buffer_float
972 {
973 internalformat = gl::GetSizedInternalFormat(internalformat, GL_FLOAT);
974 }
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500975 else
976 {
Nicolas Capensa5dfd972018-09-28 15:27:08 -0400977 UNIMPLEMENTED("internalformat = %x, colorbufferFormat = %X", internalformat, colorbufferFormat);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -0500978
979 return error(GL_INVALID_OPERATION);
980 }
981 }
982
Nicolas Capens8f215a42018-02-02 13:25:53 -0500983 if(!ValidateCopyFormats(internalformat, colorbufferFormat))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400984 {
985 return;
986 }
987
Alexis Hetu46768622018-01-16 22:09:28 -0500988 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 {
Alexis Hetu46768622018-01-16 22:09:28 -0500990 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400991
992 if(!texture)
993 {
994 return error(GL_INVALID_OPERATION);
995 }
996
Nicolas Capens1529c2c2018-02-06 14:44:47 -0500997 texture->copyImage(level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400998 }
999 else if(es2::IsCubemapTextureTarget(target))
1000 {
1001 es2::TextureCubeMap *texture = context->getTextureCubeMap();
1002
1003 if(!texture)
1004 {
1005 return error(GL_INVALID_OPERATION);
1006 }
1007
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001008 texture->copyImage(target, level, internalformat, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001009 }
1010 else UNREACHABLE(target);
1011 }
1012}
1013
1014void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
1015{
1016 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
1017 "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
1018 target, level, xoffset, yoffset, x, y, width, height);
1019
1020 if(!es2::IsTextureTarget(target))
1021 {
1022 return error(GL_INVALID_ENUM);
1023 }
1024
1025 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
1026 {
1027 return error(GL_INVALID_VALUE);
1028 }
1029
1030 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
1031 {
1032 return error(GL_INVALID_VALUE);
1033 }
1034
1035 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1036 {
1037 return error(GL_INVALID_VALUE);
1038 }
1039
Chris Forbes108f3e12018-08-30 19:41:59 -07001040 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001041
1042 if(context)
1043 {
1044 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
1045
Alexis Hetu5cd502b2018-03-22 08:29:31 -04001046 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001047 {
1048 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1049 }
1050
1051 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
1052
1053 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
1054 {
1055 return error(GL_INVALID_OPERATION);
1056 }
1057
1058 es2::Texture *texture = nullptr;
1059
Alexis Hetu46768622018-01-16 22:09:28 -05001060 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001061 {
Alexis Hetu46768622018-01-16 22:09:28 -05001062 texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001063 }
1064 else if(es2::IsCubemapTextureTarget(target))
1065 {
1066 texture = context->getTextureCubeMap();
1067 }
1068 else UNREACHABLE(target);
1069
Nicolas Capens83463112018-06-12 23:55:16 -04001070 GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05001071 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001072 {
1073 return error(validationError);
1074 }
1075
Nicolas Capens1529c2c2018-02-06 14:44:47 -05001076 texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001077 }
1078}
1079
1080GLuint CreateProgram(void)
1081{
1082 TRACE("()");
1083
Chris Forbes108f3e12018-08-30 19:41:59 -07001084 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001085
1086 if(context)
1087 {
1088 return context->createProgram();
1089 }
1090
1091 return 0;
1092}
1093
1094GLuint CreateShader(GLenum type)
1095{
1096 TRACE("(GLenum type = 0x%X)", type);
1097
Chris Forbes108f3e12018-08-30 19:41:59 -07001098 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001099
1100 if(context)
1101 {
1102 switch(type)
1103 {
1104 case GL_FRAGMENT_SHADER:
1105 case GL_VERTEX_SHADER:
1106 return context->createShader(type);
1107 default:
1108 return error(GL_INVALID_ENUM, 0);
1109 }
1110 }
1111
1112 return 0;
1113}
1114
1115void CullFace(GLenum mode)
1116{
1117 TRACE("(GLenum mode = 0x%X)", mode);
1118
1119 switch(mode)
1120 {
1121 case GL_FRONT:
1122 case GL_BACK:
1123 case GL_FRONT_AND_BACK:
1124 {
Chris Forbes108f3e12018-08-30 19:41:59 -07001125 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001126
1127 if(context)
1128 {
1129 context->setCullMode(mode);
1130 }
1131 }
1132 break;
1133 default:
1134 return error(GL_INVALID_ENUM);
1135 }
1136}
1137
1138void DeleteBuffers(GLsizei n, const GLuint* buffers)
1139{
1140 TRACE("(GLsizei n = %d, const GLuint* buffers = %p)", n, buffers);
1141
1142 if(n < 0)
1143 {
1144 return error(GL_INVALID_VALUE);
1145 }
1146
Chris Forbes108f3e12018-08-30 19:41:59 -07001147 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001148
1149 if(context)
1150 {
1151 for(int i = 0; i < n; i++)
1152 {
1153 context->deleteBuffer(buffers[i]);
1154 }
1155 }
1156}
1157
1158void DeleteFencesNV(GLsizei n, const GLuint* fences)
1159{
1160 TRACE("(GLsizei n = %d, const GLuint* fences = %p)", n, fences);
1161
1162 if(n < 0)
1163 {
1164 return error(GL_INVALID_VALUE);
1165 }
1166
Chris Forbes108f3e12018-08-30 19:41:59 -07001167 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001168
1169 if(context)
1170 {
1171 for(int i = 0; i < n; i++)
1172 {
1173 context->deleteFence(fences[i]);
1174 }
1175 }
1176}
1177
1178void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
1179{
1180 TRACE("(GLsizei n = %d, const GLuint* framebuffers = %p)", n, framebuffers);
1181
1182 if(n < 0)
1183 {
1184 return error(GL_INVALID_VALUE);
1185 }
1186
Chris Forbes108f3e12018-08-30 19:41:59 -07001187 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001188
1189 if(context)
1190 {
1191 for(int i = 0; i < n; i++)
1192 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001193 if(framebuffers[i] != 0) // Attempts to delete default framebuffer silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001194 {
1195 context->deleteFramebuffer(framebuffers[i]);
1196 }
1197 }
1198 }
1199}
1200
1201void DeleteProgram(GLuint program)
1202{
1203 TRACE("(GLuint program = %d)", program);
1204
1205 if(program == 0)
1206 {
1207 return;
1208 }
1209
Chris Forbes108f3e12018-08-30 19:41:59 -07001210 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001211
1212 if(context)
1213 {
1214 if(!context->getProgram(program))
1215 {
1216 if(context->getShader(program))
1217 {
1218 return error(GL_INVALID_OPERATION);
1219 }
1220 else
1221 {
1222 return error(GL_INVALID_VALUE);
1223 }
1224 }
1225
1226 context->deleteProgram(program);
1227 }
1228}
1229
1230void DeleteQueriesEXT(GLsizei n, const GLuint *ids)
1231{
1232 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
1233
1234 if(n < 0)
1235 {
1236 return error(GL_INVALID_VALUE);
1237 }
1238
Chris Forbes108f3e12018-08-30 19:41:59 -07001239 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001240
1241 if(context)
1242 {
1243 for(int i = 0; i < n; i++)
1244 {
1245 context->deleteQuery(ids[i]);
1246 }
1247 }
1248}
1249
1250void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
1251{
1252 TRACE("(GLsizei n = %d, const GLuint* renderbuffers = %p)", n, renderbuffers);
1253
1254 if(n < 0)
1255 {
1256 return error(GL_INVALID_VALUE);
1257 }
1258
Chris Forbes108f3e12018-08-30 19:41:59 -07001259 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001260
1261 if(context)
1262 {
1263 for(int i = 0; i < n; i++)
1264 {
1265 context->deleteRenderbuffer(renderbuffers[i]);
1266 }
1267 }
1268}
1269
1270void DeleteShader(GLuint shader)
1271{
1272 TRACE("(GLuint shader = %d)", shader);
1273
1274 if(shader == 0)
1275 {
1276 return;
1277 }
1278
Chris Forbes108f3e12018-08-30 19:41:59 -07001279 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001280
1281 if(context)
1282 {
1283 if(!context->getShader(shader))
1284 {
1285 if(context->getProgram(shader))
1286 {
1287 return error(GL_INVALID_OPERATION);
1288 }
1289 else
1290 {
1291 return error(GL_INVALID_VALUE);
1292 }
1293 }
1294
1295 context->deleteShader(shader);
1296 }
1297}
1298
1299void DeleteTextures(GLsizei n, const GLuint* textures)
1300{
1301 TRACE("(GLsizei n = %d, const GLuint* textures = %p)", n, textures);
1302
1303 if(n < 0)
1304 {
1305 return error(GL_INVALID_VALUE);
1306 }
1307
Chris Forbes108f3e12018-08-30 19:41:59 -07001308 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001309
1310 if(context)
1311 {
1312 for(int i = 0; i < n; i++)
1313 {
Nicolas Capens56eacf02018-09-27 13:54:27 -04001314 if(textures[i] != 0) // Attempts to delete default texture silently ignored.
Nicolas Capens0bac2852016-05-07 06:09:58 -04001315 {
1316 context->deleteTexture(textures[i]);
1317 }
1318 }
1319 }
1320}
1321
1322void DepthFunc(GLenum func)
1323{
1324 TRACE("(GLenum func = 0x%X)", func);
1325
1326 switch(func)
1327 {
1328 case GL_NEVER:
1329 case GL_ALWAYS:
1330 case GL_LESS:
1331 case GL_LEQUAL:
1332 case GL_EQUAL:
1333 case GL_GREATER:
1334 case GL_GEQUAL:
1335 case GL_NOTEQUAL:
1336 break;
1337 default:
1338 return error(GL_INVALID_ENUM);
1339 }
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->setDepthFunc(func);
1346 }
1347}
1348
1349void DepthMask(GLboolean flag)
1350{
1351 TRACE("(GLboolean flag = %d)", flag);
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->setDepthMask(flag != GL_FALSE);
1358 }
1359}
1360
1361void DepthRangef(GLclampf zNear, GLclampf zFar)
1362{
1363 TRACE("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
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 context->setDepthRange(zNear, zFar);
1370 }
1371}
1372
1373void DetachShader(GLuint program, GLuint shader)
1374{
1375 TRACE("(GLuint program = %d, GLuint shader = %d)", program, shader);
1376
Chris Forbes108f3e12018-08-30 19:41:59 -07001377 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001378
1379 if(context)
1380 {
1381
1382 es2::Program *programObject = context->getProgram(program);
1383 es2::Shader *shaderObject = context->getShader(shader);
1384
1385 if(!programObject)
1386 {
1387 es2::Shader *shaderByProgramHandle;
1388 shaderByProgramHandle = context->getShader(program);
1389 if(!shaderByProgramHandle)
1390 {
1391 return error(GL_INVALID_VALUE);
1392 }
1393 else
1394 {
1395 return error(GL_INVALID_OPERATION);
1396 }
1397 }
1398
1399 if(!shaderObject)
1400 {
1401 es2::Program *programByShaderHandle = context->getProgram(shader);
1402 if(!programByShaderHandle)
1403 {
1404 return error(GL_INVALID_VALUE);
1405 }
1406 else
1407 {
1408 return error(GL_INVALID_OPERATION);
1409 }
1410 }
1411
1412 if(!programObject->detachShader(shaderObject))
1413 {
1414 return error(GL_INVALID_OPERATION);
1415 }
1416 }
1417}
1418
1419void Disable(GLenum cap)
1420{
1421 TRACE("(GLenum cap = 0x%X)", cap);
1422
Chris Forbes108f3e12018-08-30 19:41:59 -07001423 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001424
1425 if(context)
1426 {
1427 switch(cap)
1428 {
1429 case GL_CULL_FACE: context->setCullFaceEnabled(false); break;
1430 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(false); break;
1431 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(false); break;
1432 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(false); break;
1433 case GL_SCISSOR_TEST: context->setScissorTestEnabled(false); break;
1434 case GL_STENCIL_TEST: context->setStencilTestEnabled(false); break;
1435 case GL_DEPTH_TEST: context->setDepthTestEnabled(false); break;
1436 case GL_BLEND: context->setBlendEnabled(false); break;
1437 case GL_DITHER: context->setDitherEnabled(false); break;
1438 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(false); break;
1439 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(false); break;
1440 default:
1441 return error(GL_INVALID_ENUM);
1442 }
1443 }
1444}
1445
1446void DisableVertexAttribArray(GLuint index)
1447{
1448 TRACE("(GLuint index = %d)", index);
1449
1450 if(index >= es2::MAX_VERTEX_ATTRIBS)
1451 {
1452 return error(GL_INVALID_VALUE);
1453 }
1454
Chris Forbes108f3e12018-08-30 19:41:59 -07001455 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001456
1457 if(context)
1458 {
1459 context->setVertexAttribArrayEnabled(index, false);
1460 }
1461}
1462
1463void DrawArrays(GLenum mode, GLint first, GLsizei count)
1464{
1465 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
1466
1467 switch(mode)
1468 {
1469 case GL_POINTS:
1470 case GL_LINES:
1471 case GL_LINE_LOOP:
1472 case GL_LINE_STRIP:
1473 case GL_TRIANGLES:
1474 case GL_TRIANGLE_FAN:
1475 case GL_TRIANGLE_STRIP:
1476 break;
1477 default:
1478 return error(GL_INVALID_ENUM);
1479 }
1480
1481 if(count < 0 || first < 0)
1482 {
1483 return error(GL_INVALID_VALUE);
1484 }
1485
Chris Forbes108f3e12018-08-30 19:41:59 -07001486 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001487
1488 if(context)
1489 {
1490 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1491 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1492 {
1493 return error(GL_INVALID_OPERATION);
1494 }
1495
1496 context->drawArrays(mode, first, count);
1497 }
1498}
1499
1500void DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
1501{
1502 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = %p)",
1503 mode, count, type, indices);
1504
1505 switch(mode)
1506 {
1507 case GL_POINTS:
1508 case GL_LINES:
1509 case GL_LINE_LOOP:
1510 case GL_LINE_STRIP:
1511 case GL_TRIANGLES:
1512 case GL_TRIANGLE_FAN:
1513 case GL_TRIANGLE_STRIP:
1514 break;
1515 default:
1516 return error(GL_INVALID_ENUM);
1517 }
1518
1519 if(count < 0)
1520 {
1521 return error(GL_INVALID_VALUE);
1522 }
1523
Chris Forbes108f3e12018-08-30 19:41:59 -07001524 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001525
1526 if(context)
1527 {
1528 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1529 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1530 {
1531 return error(GL_INVALID_OPERATION);
1532 }
1533
1534 switch(type)
1535 {
1536 case GL_UNSIGNED_BYTE:
1537 case GL_UNSIGNED_SHORT:
1538 case GL_UNSIGNED_INT:
1539 break;
1540 default:
1541 return error(GL_INVALID_ENUM);
1542 }
1543
1544 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices);
1545 }
1546}
1547
1548void DrawArraysInstancedEXT(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1549{
1550 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1551 mode, first, count, instanceCount);
1552
1553 switch(mode)
1554 {
1555 case GL_POINTS:
1556 case GL_LINES:
1557 case GL_LINE_LOOP:
1558 case GL_LINE_STRIP:
1559 case GL_TRIANGLES:
1560 case GL_TRIANGLE_FAN:
1561 case GL_TRIANGLE_STRIP:
1562 break;
1563 default:
1564 return error(GL_INVALID_ENUM);
1565 }
1566
1567 if(count < 0 || instanceCount < 0)
1568 {
1569 return error(GL_INVALID_VALUE);
1570 }
1571
Chris Forbes108f3e12018-08-30 19:41:59 -07001572 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001573
1574 if(context)
1575 {
1576 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1577 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1578 {
1579 return error(GL_INVALID_OPERATION);
1580 }
1581
1582 context->drawArrays(mode, first, count, instanceCount);
1583 }
1584}
1585
1586void DrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1587{
1588 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1589 mode, count, type, indices, instanceCount);
1590
1591 switch(mode)
1592 {
1593 case GL_POINTS:
1594 case GL_LINES:
1595 case GL_LINE_LOOP:
1596 case GL_LINE_STRIP:
1597 case GL_TRIANGLES:
1598 case GL_TRIANGLE_FAN:
1599 case GL_TRIANGLE_STRIP:
1600 break;
1601 default:
1602 return error(GL_INVALID_ENUM);
1603 }
1604
1605 switch(type)
1606 {
1607 case GL_UNSIGNED_BYTE:
1608 case GL_UNSIGNED_SHORT:
1609 case GL_UNSIGNED_INT:
1610 break;
1611 default:
1612 return error(GL_INVALID_ENUM);
1613 }
1614
1615 if(count < 0 || instanceCount < 0)
1616 {
1617 return error(GL_INVALID_VALUE);
1618 }
1619
Chris Forbes108f3e12018-08-30 19:41:59 -07001620 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001621
1622 if(context)
1623 {
1624 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1625 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1626 {
1627 return error(GL_INVALID_OPERATION);
1628 }
1629
1630 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1631 }
1632}
1633
1634void VertexAttribDivisorEXT(GLuint index, GLuint divisor)
1635{
1636 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1637
Chris Forbes108f3e12018-08-30 19:41:59 -07001638 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001639
1640 if(context)
1641 {
1642 if(index >= es2::MAX_VERTEX_ATTRIBS)
1643 {
1644 return error(GL_INVALID_VALUE);
1645 }
1646
1647 context->setVertexAttribDivisor(index, divisor);
1648 }
1649}
1650
1651void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
1652{
1653 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
1654 mode, first, count, instanceCount);
1655
1656 switch(mode)
1657 {
1658 case GL_POINTS:
1659 case GL_LINES:
1660 case GL_LINE_LOOP:
1661 case GL_LINE_STRIP:
1662 case GL_TRIANGLES:
1663 case GL_TRIANGLE_FAN:
1664 case GL_TRIANGLE_STRIP:
1665 break;
1666 default:
1667 return error(GL_INVALID_ENUM);
1668 }
1669
1670 if(count < 0 || instanceCount < 0)
1671 {
1672 return error(GL_INVALID_VALUE);
1673 }
1674
Chris Forbes108f3e12018-08-30 19:41:59 -07001675 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001676
1677 if(context)
1678 {
1679 if(!context->hasZeroDivisor())
1680 {
1681 return error(GL_INVALID_OPERATION);
1682 }
1683
1684 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1685 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
1686 {
1687 return error(GL_INVALID_OPERATION);
1688 }
1689
1690 context->drawArrays(mode, first, count, instanceCount);
1691 }
1692}
1693
1694void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
1695{
1696 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
1697 mode, count, type, indices, instanceCount);
1698
1699 switch(mode)
1700 {
1701 case GL_POINTS:
1702 case GL_LINES:
1703 case GL_LINE_LOOP:
1704 case GL_LINE_STRIP:
1705 case GL_TRIANGLES:
1706 case GL_TRIANGLE_FAN:
1707 case GL_TRIANGLE_STRIP:
1708 break;
1709 default:
1710 return error(GL_INVALID_ENUM);
1711 }
1712
1713 switch(type)
1714 {
1715 case GL_UNSIGNED_BYTE:
1716 case GL_UNSIGNED_SHORT:
1717 case GL_UNSIGNED_INT:
1718 break;
1719 default:
1720 return error(GL_INVALID_ENUM);
1721 }
1722
1723 if(count < 0 || instanceCount < 0)
1724 {
1725 return error(GL_INVALID_VALUE);
1726 }
1727
Chris Forbes108f3e12018-08-30 19:41:59 -07001728 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001729
1730 if(context)
1731 {
1732 if(!context->hasZeroDivisor())
1733 {
1734 return error(GL_INVALID_OPERATION);
1735 }
1736
1737 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
1738 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
1739 {
1740 return error(GL_INVALID_OPERATION);
1741 }
1742
1743 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
1744 }
1745}
1746
1747void VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
1748{
1749 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
1750
Chris Forbes108f3e12018-08-30 19:41:59 -07001751 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001752
1753 if(context)
1754 {
1755 if(index >= MAX_VERTEX_ATTRIBS)
1756 {
1757 return error(GL_INVALID_VALUE);
1758 }
1759
1760 context->setVertexAttribDivisor(index, divisor);
1761 }
1762}
1763
1764void Enable(GLenum cap)
1765{
1766 TRACE("(GLenum cap = 0x%X)", cap);
1767
Chris Forbes108f3e12018-08-30 19:41:59 -07001768 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001769
1770 if(context)
1771 {
1772 switch(cap)
1773 {
1774 case GL_CULL_FACE: context->setCullFaceEnabled(true); break;
1775 case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFillEnabled(true); break;
1776 case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverageEnabled(true); break;
1777 case GL_SAMPLE_COVERAGE: context->setSampleCoverageEnabled(true); break;
1778 case GL_SCISSOR_TEST: context->setScissorTestEnabled(true); break;
1779 case GL_STENCIL_TEST: context->setStencilTestEnabled(true); break;
1780 case GL_DEPTH_TEST: context->setDepthTestEnabled(true); break;
1781 case GL_BLEND: context->setBlendEnabled(true); break;
1782 case GL_DITHER: context->setDitherEnabled(true); break;
1783 case GL_PRIMITIVE_RESTART_FIXED_INDEX: context->setPrimitiveRestartFixedIndexEnabled(true); break;
1784 case GL_RASTERIZER_DISCARD: context->setRasterizerDiscardEnabled(true); break;
1785 default:
1786 return error(GL_INVALID_ENUM);
1787 }
1788 }
1789}
1790
1791void EnableVertexAttribArray(GLuint index)
1792{
1793 TRACE("(GLuint index = %d)", index);
1794
1795 if(index >= es2::MAX_VERTEX_ATTRIBS)
1796 {
1797 return error(GL_INVALID_VALUE);
1798 }
1799
Chris Forbes108f3e12018-08-30 19:41:59 -07001800 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001801
1802 if(context)
1803 {
1804 context->setVertexAttribArrayEnabled(index, true);
1805 }
1806}
1807
1808void EndQueryEXT(GLenum target)
1809{
1810 TRACE("GLenum target = 0x%X)", target);
1811
1812 switch(target)
1813 {
1814 case GL_ANY_SAMPLES_PASSED_EXT:
1815 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1816 break;
1817 default:
1818 return error(GL_INVALID_ENUM);
1819 }
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 context->endQuery(target);
1826 }
1827}
1828
1829void FinishFenceNV(GLuint fence)
1830{
1831 TRACE("(GLuint fence = %d)", fence);
1832
Chris Forbes108f3e12018-08-30 19:41:59 -07001833 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001834
1835 if(context)
1836 {
1837 es2::Fence *fenceObject = context->getFence(fence);
1838
1839 if(!fenceObject)
1840 {
1841 return error(GL_INVALID_OPERATION);
1842 }
1843
1844 fenceObject->finishFence();
1845 }
1846}
1847
1848void Finish(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->finish();
1857 }
1858}
1859
1860void Flush(void)
1861{
1862 TRACE("()");
1863
Chris Forbes108f3e12018-08-30 19:41:59 -07001864 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001865
1866 if(context)
1867 {
1868 context->flush();
1869 }
1870}
1871
1872void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
1873{
1874 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
1875 "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
1876
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001877 if((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER) ||
Nicolas Capens0bac2852016-05-07 06:09:58 -04001878 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
1879 {
1880 return error(GL_INVALID_ENUM);
1881 }
1882
Chris Forbes108f3e12018-08-30 19:41:59 -07001883 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001884
1885 if(context)
1886 {
1887 es2::Framebuffer *framebuffer = nullptr;
1888 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001889 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001890 {
1891 framebuffer = context->getReadFramebuffer();
1892 framebufferName = context->getReadFramebufferName();
1893 }
1894 else
1895 {
1896 framebuffer = context->getDrawFramebuffer();
1897 framebufferName = context->getDrawFramebufferName();
1898 }
1899
1900 if(!framebuffer || framebufferName == 0)
1901 {
1902 return error(GL_INVALID_OPERATION);
1903 }
1904
1905 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1906 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1907 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1908 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1909 if(renderbuffer != 0)
1910 {
1911 if(!context->getRenderbuffer(renderbuffer))
1912 {
1913 return error(GL_INVALID_OPERATION);
1914 }
1915 }
1916
Nicolas Capens0bac2852016-05-07 06:09:58 -04001917 switch(attachment)
1918 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001919 case GL_DEPTH_ATTACHMENT:
1920 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1921 break;
1922 case GL_STENCIL_ATTACHMENT:
1923 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1924 break;
1925 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capens83463112018-06-12 23:55:16 -04001926 framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer);
1927 framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer);
1928 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001929 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04001930 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens83463112018-06-12 23:55:16 -04001931 {
1932 return error(GL_INVALID_ENUM);
1933 }
Nicolas Capens4e344192018-10-24 21:01:17 -04001934
1935 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1936 {
1937 return error(GL_INVALID_OPERATION);
1938 }
1939
Nicolas Capens83463112018-06-12 23:55:16 -04001940 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1941 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001942 }
1943 }
1944}
1945
1946void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1947{
1948 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1949 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1950
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001951 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001952 {
1953 return error(GL_INVALID_ENUM);
1954 }
1955
Chris Forbes108f3e12018-08-30 19:41:59 -07001956 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001957
1958 if(context)
1959 {
1960 if(texture == 0)
1961 {
1962 textarget = GL_NONE;
1963 }
1964 else
1965 {
1966 es2::Texture *tex = context->getTexture(texture);
1967
1968 if(!tex)
1969 {
1970 return error(GL_INVALID_OPERATION);
1971 }
1972
1973 switch(textarget)
1974 {
1975 case GL_TEXTURE_2D:
1976 if(tex->getTarget() != GL_TEXTURE_2D)
1977 {
1978 return error(GL_INVALID_OPERATION);
1979 }
1980 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001981 case GL_TEXTURE_RECTANGLE_ARB:
1982 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1983 {
1984 return error(GL_INVALID_OPERATION);
1985 }
1986 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001987 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1988 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1989 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1990 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1991 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1992 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1993 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1994 {
1995 return error(GL_INVALID_OPERATION);
1996 }
1997 break;
1998 default:
1999 return error(GL_INVALID_ENUM);
2000 }
2001
Nicolas Capens83463112018-06-12 23:55:16 -04002002 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002003 {
2004 return error(GL_INVALID_VALUE);
2005 }
2006
2007 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2008 {
2009 return error(GL_INVALID_VALUE);
2010 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002011
2012 if(tex->isCompressed(textarget, level))
2013 {
2014 return error(GL_INVALID_OPERATION);
2015 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002016 }
2017
2018 es2::Framebuffer *framebuffer = nullptr;
2019 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002020 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002021 {
2022 framebuffer = context->getReadFramebuffer();
2023 framebufferName = context->getReadFramebufferName();
2024 }
2025 else
2026 {
2027 framebuffer = context->getDrawFramebuffer();
2028 framebufferName = context->getDrawFramebufferName();
2029 }
2030
2031 if(framebufferName == 0 || !framebuffer)
2032 {
2033 return error(GL_INVALID_OPERATION);
2034 }
2035
2036 switch(attachment)
2037 {
Nicolas Capens83463112018-06-12 23:55:16 -04002038 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2039 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2040 case GL_DEPTH_STENCIL_ATTACHMENT:
2041 framebuffer->setDepthbuffer(textarget, texture, level);
2042 framebuffer->setStencilbuffer(textarget, texture, level);
2043 break;
2044 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04002045 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002046 {
2047 return error(GL_INVALID_ENUM);
2048 }
Nicolas Capens4e344192018-10-24 21:01:17 -04002049
2050 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2051 {
2052 return error(GL_INVALID_OPERATION);
2053 }
2054
Nicolas Capens0bac2852016-05-07 06:09:58 -04002055 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2056 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002057 }
2058 }
2059}
2060
2061void FrontFace(GLenum mode)
2062{
2063 TRACE("(GLenum mode = 0x%X)", mode);
2064
2065 switch(mode)
2066 {
2067 case GL_CW:
2068 case GL_CCW:
2069 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002070 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002071
2072 if(context)
2073 {
2074 context->setFrontFace(mode);
2075 }
2076 }
2077 break;
2078 default:
2079 return error(GL_INVALID_ENUM);
2080 }
2081}
2082
2083void GenBuffers(GLsizei n, GLuint* buffers)
2084{
2085 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2086
2087 if(n < 0)
2088 {
2089 return error(GL_INVALID_VALUE);
2090 }
2091
Chris Forbes108f3e12018-08-30 19:41:59 -07002092 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002093
2094 if(context)
2095 {
2096 for(int i = 0; i < n; i++)
2097 {
2098 buffers[i] = context->createBuffer();
2099 }
2100 }
2101}
2102
2103void GenerateMipmap(GLenum target)
2104{
2105 TRACE("(GLenum target = 0x%X)", target);
2106
Chris Forbes108f3e12018-08-30 19:41:59 -07002107 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002108
2109 if(context)
2110 {
2111 es2::Texture *texture = nullptr;
2112
Nicolas Capens0bac2852016-05-07 06:09:58 -04002113 switch(target)
2114 {
2115 case GL_TEXTURE_2D:
2116 texture = context->getTexture2D();
2117 break;
2118 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002119 {
2120 TextureCubeMap *cube = context->getTextureCubeMap();
2121 texture = cube;
2122
2123 if(!cube->isCubeComplete())
2124 {
2125 return error(GL_INVALID_OPERATION);
2126 }
2127 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002128 break;
2129 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002130 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002131 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002132 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002133 texture = context->getTexture3D();
2134 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002135 case GL_TEXTURE_RECTANGLE_ARB:
2136 texture = context->getTexture2DRect();
2137 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002138 default:
2139 return error(GL_INVALID_ENUM);
2140 }
2141
Nicolas Capens83463112018-06-12 23:55:16 -04002142 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002143 {
2144 return error(GL_INVALID_OPERATION);
2145 }
2146
Nicolas Capens0bac2852016-05-07 06:09:58 -04002147 texture->generateMipmaps();
2148 }
2149}
2150
2151void GenFencesNV(GLsizei n, GLuint* fences)
2152{
2153 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2154
2155 if(n < 0)
2156 {
2157 return error(GL_INVALID_VALUE);
2158 }
2159
Chris Forbes108f3e12018-08-30 19:41:59 -07002160 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002161
2162 if(context)
2163 {
2164 for(int i = 0; i < n; i++)
2165 {
2166 fences[i] = context->createFence();
2167 }
2168 }
2169}
2170
2171void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2172{
2173 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2174
2175 if(n < 0)
2176 {
2177 return error(GL_INVALID_VALUE);
2178 }
2179
Chris Forbes108f3e12018-08-30 19:41:59 -07002180 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002181
2182 if(context)
2183 {
2184 for(int i = 0; i < n; i++)
2185 {
2186 framebuffers[i] = context->createFramebuffer();
2187 }
2188 }
2189}
2190
2191void GenQueriesEXT(GLsizei n, GLuint* ids)
2192{
2193 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2194
2195 if(n < 0)
2196 {
2197 return error(GL_INVALID_VALUE);
2198 }
2199
Chris Forbes108f3e12018-08-30 19:41:59 -07002200 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002201
2202 if(context)
2203 {
2204 for(int i = 0; i < n; i++)
2205 {
2206 ids[i] = context->createQuery();
2207 }
2208 }
2209}
2210
2211void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2212{
2213 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2214
2215 if(n < 0)
2216 {
2217 return error(GL_INVALID_VALUE);
2218 }
2219
Chris Forbes108f3e12018-08-30 19:41:59 -07002220 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002221
2222 if(context)
2223 {
2224 for(int i = 0; i < n; i++)
2225 {
2226 renderbuffers[i] = context->createRenderbuffer();
2227 }
2228 }
2229}
2230
2231void GenTextures(GLsizei n, GLuint* textures)
2232{
2233 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2234
2235 if(n < 0)
2236 {
2237 return error(GL_INVALID_VALUE);
2238 }
2239
Chris Forbes108f3e12018-08-30 19:41:59 -07002240 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002241
2242 if(context)
2243 {
2244 for(int i = 0; i < n; i++)
2245 {
2246 textures[i] = context->createTexture();
2247 }
2248 }
2249}
2250
2251void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2252{
2253 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2254 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2255 program, index, bufsize, length, size, type, name);
2256
2257 if(bufsize < 0)
2258 {
2259 return error(GL_INVALID_VALUE);
2260 }
2261
Chris Forbes108f3e12018-08-30 19:41:59 -07002262 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002263
2264 if(context)
2265 {
2266 es2::Program *programObject = context->getProgram(program);
2267
2268 if(!programObject)
2269 {
2270 if(context->getShader(program))
2271 {
2272 return error(GL_INVALID_OPERATION);
2273 }
2274 else
2275 {
2276 return error(GL_INVALID_VALUE);
2277 }
2278 }
2279
2280 if(index >= programObject->getActiveAttributeCount())
2281 {
2282 return error(GL_INVALID_VALUE);
2283 }
2284
2285 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2286 }
2287}
2288
2289void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2290{
2291 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2292 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2293 program, index, bufsize, length, size, type, name);
2294
2295 if(bufsize < 0)
2296 {
2297 return error(GL_INVALID_VALUE);
2298 }
2299
Chris Forbes108f3e12018-08-30 19:41:59 -07002300 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002301
2302 if(context)
2303 {
2304 es2::Program *programObject = context->getProgram(program);
2305
2306 if(!programObject)
2307 {
2308 if(context->getShader(program))
2309 {
2310 return error(GL_INVALID_OPERATION);
2311 }
2312 else
2313 {
2314 return error(GL_INVALID_VALUE);
2315 }
2316 }
2317
2318 if(index >= programObject->getActiveUniformCount())
2319 {
2320 return error(GL_INVALID_VALUE);
2321 }
2322
2323 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2324 }
2325}
2326
2327void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2328{
2329 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2330 program, maxcount, count, shaders);
2331
2332 if(maxcount < 0)
2333 {
2334 return error(GL_INVALID_VALUE);
2335 }
2336
Chris Forbes108f3e12018-08-30 19:41:59 -07002337 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002338
2339 if(context)
2340 {
2341 es2::Program *programObject = context->getProgram(program);
2342
2343 if(!programObject)
2344 {
2345 if(context->getShader(program))
2346 {
2347 return error(GL_INVALID_OPERATION);
2348 }
2349 else
2350 {
2351 return error(GL_INVALID_VALUE);
2352 }
2353 }
2354
2355 return programObject->getAttachedShaders(maxcount, count, shaders);
2356 }
2357}
2358
2359int GetAttribLocation(GLuint program, const GLchar* name)
2360{
2361 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2362
Chris Forbes108f3e12018-08-30 19:41:59 -07002363 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002364
2365 if(context)
2366 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002367 es2::Program *programObject = context->getProgram(program);
2368
2369 if(!programObject)
2370 {
2371 if(context->getShader(program))
2372 {
2373 return error(GL_INVALID_OPERATION, -1);
2374 }
2375 else
2376 {
2377 return error(GL_INVALID_VALUE, -1);
2378 }
2379 }
2380
2381 if(!programObject->isLinked())
2382 {
2383 return error(GL_INVALID_OPERATION, -1);
2384 }
2385
2386 return programObject->getAttributeLocation(name);
2387 }
2388
2389 return -1;
2390}
2391
2392void GetBooleanv(GLenum pname, GLboolean* params)
2393{
2394 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2395
Chris Forbes108f3e12018-08-30 19:41:59 -07002396 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002397
2398 if(context)
2399 {
2400 if(!(context->getBooleanv(pname, params)))
2401 {
2402 GLenum nativeType;
2403 unsigned int numParams = 0;
2404 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2405 return error(GL_INVALID_ENUM);
2406
2407 if(numParams == 0)
2408 return; // it is known that the pname is valid, but there are no parameters to return
2409
2410 if(nativeType == GL_FLOAT)
2411 {
2412 GLfloat *floatParams = nullptr;
2413 floatParams = new GLfloat[numParams];
2414
2415 context->getFloatv(pname, floatParams);
2416
2417 for(unsigned int i = 0; i < numParams; ++i)
2418 {
2419 if(floatParams[i] == 0.0f)
2420 params[i] = GL_FALSE;
2421 else
2422 params[i] = GL_TRUE;
2423 }
2424
2425 delete [] floatParams;
2426 }
2427 else if(nativeType == GL_INT)
2428 {
2429 GLint *intParams = nullptr;
2430 intParams = new GLint[numParams];
2431
2432 context->getIntegerv(pname, intParams);
2433
2434 for(unsigned int i = 0; i < numParams; ++i)
2435 {
2436 if(intParams[i] == 0)
2437 params[i] = GL_FALSE;
2438 else
2439 params[i] = GL_TRUE;
2440 }
2441
2442 delete [] intParams;
2443 }
2444 }
2445 }
2446}
2447
2448void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2449{
2450 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2451
Chris Forbes108f3e12018-08-30 19:41:59 -07002452 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002453
2454 if(context)
2455 {
2456 es2::Buffer *buffer;
2457 if(!context->getBuffer(target, &buffer))
2458 {
2459 return error(GL_INVALID_ENUM);
2460 }
2461
2462 if(!buffer)
2463 {
2464 // A null buffer means that "0" is bound to the requested buffer target
2465 return error(GL_INVALID_OPERATION);
2466 }
2467
Nicolas Capens0bac2852016-05-07 06:09:58 -04002468 switch(pname)
2469 {
2470 case GL_BUFFER_USAGE:
2471 *params = buffer->usage();
2472 break;
2473 case GL_BUFFER_SIZE:
2474 *params = (GLint)buffer->size();
2475 break;
2476 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002477 *params = buffer->access();
2478 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002479 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002480 *params = buffer->isMapped();
2481 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002482 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002483 *params = (GLint)buffer->length();
2484 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002485 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002486 *params = (GLint)buffer->offset();
2487 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002488 default:
2489 return error(GL_INVALID_ENUM);
2490 }
2491 }
2492}
2493
2494GLenum GetError(void)
2495{
2496 TRACE("()");
2497
Chris Forbes108f3e12018-08-30 19:41:59 -07002498 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002499
2500 if(context)
2501 {
2502 return context->getError();
2503 }
2504
2505 return GL_NO_ERROR;
2506}
2507
2508void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2509{
2510 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2511
Chris Forbes108f3e12018-08-30 19:41:59 -07002512 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002513
2514 if(context)
2515 {
2516 es2::Fence *fenceObject = context->getFence(fence);
2517
2518 if(!fenceObject)
2519 {
2520 return error(GL_INVALID_OPERATION);
2521 }
2522
2523 fenceObject->getFenceiv(pname, params);
2524 }
2525}
2526
2527void GetFloatv(GLenum pname, GLfloat* params)
2528{
2529 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2530
Chris Forbes108f3e12018-08-30 19:41:59 -07002531 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002532
2533 if(context)
2534 {
2535 if(!(context->getFloatv(pname, params)))
2536 {
2537 GLenum nativeType;
2538 unsigned int numParams = 0;
2539 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2540 return error(GL_INVALID_ENUM);
2541
2542 if(numParams == 0)
2543 return; // it is known that the pname is valid, but that there are no parameters to return.
2544
2545 if(nativeType == GL_BOOL)
2546 {
2547 GLboolean *boolParams = nullptr;
2548 boolParams = new GLboolean[numParams];
2549
2550 context->getBooleanv(pname, boolParams);
2551
2552 for(unsigned int i = 0; i < numParams; ++i)
2553 {
2554 if(boolParams[i] == GL_FALSE)
2555 params[i] = 0.0f;
2556 else
2557 params[i] = 1.0f;
2558 }
2559
2560 delete [] boolParams;
2561 }
2562 else if(nativeType == GL_INT)
2563 {
2564 GLint *intParams = nullptr;
2565 intParams = new GLint[numParams];
2566
2567 context->getIntegerv(pname, intParams);
2568
2569 for(unsigned int i = 0; i < numParams; ++i)
2570 {
2571 params[i] = (GLfloat)intParams[i];
2572 }
2573
2574 delete [] intParams;
2575 }
2576 }
2577 }
2578}
2579
2580void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2581{
2582 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2583 target, attachment, pname, params);
2584
Chris Forbes108f3e12018-08-30 19:41:59 -07002585 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002586
2587 if(context)
2588 {
2589 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2590 {
2591 return error(GL_INVALID_ENUM);
2592 }
2593
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002594 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002595
Nicolas Capens0bac2852016-05-07 06:09:58 -04002596 if(target == GL_READ_FRAMEBUFFER)
2597 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002598 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002599 }
2600 else
2601 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002602 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002603 }
2604
Nicolas Capens0bac2852016-05-07 06:09:58 -04002605 switch(attachment)
2606 {
2607 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002608 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002609 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002610 if(framebufferName != 0)
2611 {
2612 return error(GL_INVALID_OPERATION);
2613 }
2614 break;
2615 case GL_DEPTH_ATTACHMENT:
2616 case GL_STENCIL_ATTACHMENT:
2617 if(framebufferName == 0)
2618 {
2619 return error(GL_INVALID_OPERATION);
2620 }
2621 break;
2622 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002623 if(framebufferName == 0)
2624 {
2625 return error(GL_INVALID_OPERATION);
2626 }
2627 break;
2628 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04002629 if(framebufferName == 0)
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002630 {
Nicolas Capens4e344192018-10-24 21:01:17 -04002631 return error(GL_INVALID_OPERATION);
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002632 }
Nicolas Capens4e344192018-10-24 21:01:17 -04002633
2634 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
2635 {
2636 return error(GL_INVALID_ENUM);
2637 }
2638
2639 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2640 {
2641 return error(GL_INVALID_OPERATION);
2642 }
2643 break;
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002644 }
2645
2646 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2647
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002648 if(!framebuffer)
2649 {
2650 return error(GL_INVALID_OPERATION);
2651 }
2652
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002653 GLenum attachmentType;
2654 GLuint attachmentHandle;
2655 GLint attachmentLayer;
2656 Renderbuffer *renderbuffer = nullptr;
2657 switch(attachment)
2658 {
2659 case GL_BACK:
2660 attachmentType = framebuffer->getColorbufferType(0);
2661 attachmentHandle = framebuffer->getColorbufferName(0);
2662 attachmentLayer = framebuffer->getColorbufferLayer(0);
2663 renderbuffer = framebuffer->getColorbuffer(0);
2664 break;
2665 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002666 case GL_DEPTH_ATTACHMENT:
2667 attachmentType = framebuffer->getDepthbufferType();
2668 attachmentHandle = framebuffer->getDepthbufferName();
2669 attachmentLayer = framebuffer->getDepthbufferLayer();
2670 renderbuffer = framebuffer->getDepthbuffer();
2671 break;
2672 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002673 case GL_STENCIL_ATTACHMENT:
2674 attachmentType = framebuffer->getStencilbufferType();
2675 attachmentHandle = framebuffer->getStencilbufferName();
2676 attachmentLayer = framebuffer->getStencilbufferLayer();
2677 renderbuffer = framebuffer->getStencilbuffer();
2678 break;
2679 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002680 attachmentType = framebuffer->getDepthbufferType();
2681 attachmentHandle = framebuffer->getDepthbufferName();
2682 attachmentLayer = framebuffer->getDepthbufferLayer();
2683 renderbuffer = framebuffer->getDepthbuffer();
2684
2685 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002686 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002687 // Different attachments to DEPTH and STENCIL, query fails
2688 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002689 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002690 break;
2691 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002692 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2693 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2694 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2695 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2696 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2697 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002698 }
2699
2700 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002701 if(framebufferName == 0)
2702 {
2703 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2704 }
2705 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002706 {
2707 attachmentObjectType = attachmentType;
2708 }
2709 else if(es2::IsTextureTarget(attachmentType))
2710 {
2711 attachmentObjectType = GL_TEXTURE;
2712 }
2713 else UNREACHABLE(attachmentType);
2714
2715 if(attachmentObjectType != GL_NONE)
2716 {
2717 switch(pname)
2718 {
2719 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2720 *params = attachmentObjectType;
2721 break;
2722 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002723 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002724 {
2725 *params = attachmentHandle;
2726 }
2727 else
2728 {
2729 return error(GL_INVALID_ENUM);
2730 }
2731 break;
2732 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2733 if(attachmentObjectType == GL_TEXTURE)
2734 {
Nicolas Capens83463112018-06-12 23:55:16 -04002735 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002736 }
2737 else
2738 {
2739 return error(GL_INVALID_ENUM);
2740 }
2741 break;
2742 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2743 if(attachmentObjectType == GL_TEXTURE)
2744 {
2745 if(es2::IsCubemapTextureTarget(attachmentType))
2746 {
2747 *params = attachmentType;
2748 }
2749 else
2750 {
2751 *params = 0;
2752 }
2753 }
2754 else
2755 {
2756 return error(GL_INVALID_ENUM);
2757 }
2758 break;
2759 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002760 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002761 break;
2762 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002763 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002764 break;
2765 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002766 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002767 break;
2768 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002769 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002770 break;
2771 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002772 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002773 break;
2774 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002775 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002776 break;
2777 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002778 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002779 break;
2780 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002781 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2782 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002783 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002784 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002785 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002786
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002787 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002788 break;
2789 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002790 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002791 break;
2792 default:
2793 return error(GL_INVALID_ENUM);
2794 }
2795 }
2796 else
2797 {
2798 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2799 // is NONE, then querying any other pname will generate INVALID_ENUM.
2800
2801 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2802 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2803 // INVALID_OPERATION for all other pnames
2804
2805 switch(pname)
2806 {
2807 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2808 *params = GL_NONE;
2809 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002810 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002811 *params = 0;
2812 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002813 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002814 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002815 }
2816 }
2817 }
2818}
2819
2820GLenum GetGraphicsResetStatusEXT(void)
2821{
2822 TRACE("()");
2823
2824 return GL_NO_ERROR;
2825}
2826
2827void GetIntegerv(GLenum pname, GLint* params)
2828{
2829 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2830
Chris Forbes108f3e12018-08-30 19:41:59 -07002831 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002832
2833 if(!context)
2834 {
2835 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002836 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002837
2838 // This is not spec compliant! When there is no current GL context, functions should
2839 // have no side effects. Google Maps queries these values before creating a context,
2840 // so we need this as a bug-compatible workaround.
2841 switch(pname)
2842 {
2843 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2844 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2845 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2846 case GL_STENCIL_BITS: *params = 8; return;
2847 case GL_ALIASED_LINE_WIDTH_RANGE:
2848 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2849 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2850 return;
2851 }
2852 }
2853
2854 if(context)
2855 {
2856 if(!(context->getIntegerv(pname, params)))
2857 {
2858 GLenum nativeType;
2859 unsigned int numParams = 0;
2860 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2861 return error(GL_INVALID_ENUM);
2862
2863 if(numParams == 0)
2864 return; // it is known that pname is valid, but there are no parameters to return
2865
2866 if(nativeType == GL_BOOL)
2867 {
2868 GLboolean *boolParams = nullptr;
2869 boolParams = new GLboolean[numParams];
2870
2871 context->getBooleanv(pname, boolParams);
2872
2873 for(unsigned int i = 0; i < numParams; ++i)
2874 {
2875 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2876 }
2877
2878 delete [] boolParams;
2879 }
2880 else if(nativeType == GL_FLOAT)
2881 {
2882 GLfloat *floatParams = nullptr;
2883 floatParams = new GLfloat[numParams];
2884
2885 context->getFloatv(pname, floatParams);
2886
2887 for(unsigned int i = 0; i < numParams; ++i)
2888 {
2889 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2890 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002891 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002892 }
2893 else
2894 {
2895 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2896 }
2897 }
2898
2899 delete [] floatParams;
2900 }
2901 }
2902 }
2903}
2904
2905void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2906{
2907 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2908
Chris Forbes108f3e12018-08-30 19:41:59 -07002909 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002910
2911 if(context)
2912 {
2913 es2::Program *programObject = context->getProgram(program);
2914
2915 if(!programObject)
2916 {
2917 if(context->getShader(program))
2918 {
2919 return error(GL_INVALID_OPERATION);
2920 }
2921 else
2922 {
2923 return error(GL_INVALID_VALUE);
2924 }
2925 }
2926
Nicolas Capens0bac2852016-05-07 06:09:58 -04002927 switch(pname)
2928 {
2929 case GL_DELETE_STATUS:
2930 *params = programObject->isFlaggedForDeletion();
2931 return;
2932 case GL_LINK_STATUS:
2933 *params = programObject->isLinked();
2934 return;
2935 case GL_VALIDATE_STATUS:
2936 *params = programObject->isValidated();
2937 return;
2938 case GL_INFO_LOG_LENGTH:
2939 *params = (GLint)programObject->getInfoLogLength();
2940 return;
2941 case GL_ATTACHED_SHADERS:
2942 *params = programObject->getAttachedShadersCount();
2943 return;
2944 case GL_ACTIVE_ATTRIBUTES:
2945 *params = (GLint)programObject->getActiveAttributeCount();
2946 return;
2947 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2948 *params = programObject->getActiveAttributeMaxLength();
2949 return;
2950 case GL_ACTIVE_UNIFORMS:
2951 *params = (GLint)programObject->getActiveUniformCount();
2952 return;
2953 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2954 *params = programObject->getActiveUniformMaxLength();
2955 return;
2956 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002957 *params = (GLint)programObject->getActiveUniformBlockCount();
2958 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002959 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002960 *params = programObject->getActiveUniformBlockMaxLength();
2961 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002962 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002963 *params = programObject->getTransformFeedbackBufferMode();
2964 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002965 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002966 *params = programObject->getTransformFeedbackVaryingCount();
2967 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002968 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002969 *params = programObject->getTransformFeedbackVaryingMaxLength();
2970 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002971 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002972 *params = programObject->getBinaryRetrievableHint();
2973 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002974 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002975 *params = programObject->getBinaryLength();
2976 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002977 default:
2978 return error(GL_INVALID_ENUM);
2979 }
2980 }
2981}
2982
2983void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2984{
2985 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2986 program, bufsize, length, infolog);
2987
2988 if(bufsize < 0)
2989 {
2990 return error(GL_INVALID_VALUE);
2991 }
2992
Chris Forbes108f3e12018-08-30 19:41:59 -07002993 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002994
2995 if(context)
2996 {
2997 es2::Program *programObject = context->getProgram(program);
2998
2999 if(!programObject)
3000 {
3001 if(context->getShader(program))
3002 {
3003 return error(GL_INVALID_OPERATION);
3004 }
3005 else
3006 {
3007 return error(GL_INVALID_VALUE);
3008 }
3009 }
3010
3011 programObject->getInfoLog(bufsize, length, infolog);
3012 }
3013}
3014
3015void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
3016{
3017 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
3018
3019 switch(pname)
3020 {
3021 case GL_CURRENT_QUERY_EXT:
3022 break;
3023 default:
3024 return error(GL_INVALID_ENUM);
3025 }
3026
Chris Forbes108f3e12018-08-30 19:41:59 -07003027 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003028
3029 if(context)
3030 {
3031 params[0] = context->getActiveQuery(target);
3032 }
3033}
3034
3035void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3036{
3037 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3038
3039 switch(pname)
3040 {
3041 case GL_QUERY_RESULT_EXT:
3042 case GL_QUERY_RESULT_AVAILABLE_EXT:
3043 break;
3044 default:
3045 return error(GL_INVALID_ENUM);
3046 }
3047
Chris Forbes108f3e12018-08-30 19:41:59 -07003048 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003049
3050 if(context)
3051 {
3052 es2::Query *queryObject = context->getQuery(name);
3053
3054 if(!queryObject)
3055 {
3056 return error(GL_INVALID_OPERATION);
3057 }
3058
3059 if(context->getActiveQuery(queryObject->getType()) == name)
3060 {
3061 return error(GL_INVALID_OPERATION);
3062 }
3063
3064 switch(pname)
3065 {
3066 case GL_QUERY_RESULT_EXT:
3067 params[0] = queryObject->getResult();
3068 break;
3069 case GL_QUERY_RESULT_AVAILABLE_EXT:
3070 params[0] = queryObject->isResultAvailable();
3071 break;
3072 default:
3073 ASSERT(false);
3074 }
3075 }
3076}
3077
3078void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3079{
3080 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3081
Chris Forbes108f3e12018-08-30 19:41:59 -07003082 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003083
3084 if(context)
3085 {
3086 if(target != GL_RENDERBUFFER)
3087 {
3088 return error(GL_INVALID_ENUM);
3089 }
3090
3091 if(context->getRenderbufferName() == 0)
3092 {
3093 return error(GL_INVALID_OPERATION);
3094 }
3095
3096 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3097
3098 switch(pname)
3099 {
3100 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3101 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003102 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3103 {
3104 GLint internalformat = renderbuffer->getFormat();
3105 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3106 }
3107 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003108 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3109 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3110 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3111 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3112 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3113 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003114 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003115 default:
3116 return error(GL_INVALID_ENUM);
3117 }
3118 }
3119}
3120
3121void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3122{
3123 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3124
Chris Forbes108f3e12018-08-30 19:41:59 -07003125 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003126
3127 if(context)
3128 {
3129 es2::Shader *shaderObject = context->getShader(shader);
3130
3131 if(!shaderObject)
3132 {
3133 if(context->getProgram(shader))
3134 {
3135 return error(GL_INVALID_OPERATION);
3136 }
3137 else
3138 {
3139 return error(GL_INVALID_VALUE);
3140 }
3141 }
3142
3143 switch(pname)
3144 {
3145 case GL_SHADER_TYPE:
3146 *params = shaderObject->getType();
3147 return;
3148 case GL_DELETE_STATUS:
3149 *params = shaderObject->isFlaggedForDeletion();
3150 return;
3151 case GL_COMPILE_STATUS:
3152 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3153 return;
3154 case GL_INFO_LOG_LENGTH:
3155 *params = (GLint)shaderObject->getInfoLogLength();
3156 return;
3157 case GL_SHADER_SOURCE_LENGTH:
3158 *params = (GLint)shaderObject->getSourceLength();
3159 return;
3160 default:
3161 return error(GL_INVALID_ENUM);
3162 }
3163 }
3164}
3165
3166void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3167{
3168 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3169 shader, bufsize, length, infolog);
3170
3171 if(bufsize < 0)
3172 {
3173 return error(GL_INVALID_VALUE);
3174 }
3175
Chris Forbes108f3e12018-08-30 19:41:59 -07003176 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003177
3178 if(context)
3179 {
3180 es2::Shader *shaderObject = context->getShader(shader);
3181
3182 if(!shaderObject)
3183 {
3184 if(context->getProgram(shader))
3185 {
3186 return error(GL_INVALID_OPERATION);
3187 }
3188 else
3189 {
3190 return error(GL_INVALID_VALUE);
3191 }
3192 }
3193
3194 shaderObject->getInfoLog(bufsize, length, infolog);
3195 }
3196}
3197
3198void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3199{
3200 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3201 shadertype, precisiontype, range, precision);
3202
3203 switch(shadertype)
3204 {
3205 case GL_VERTEX_SHADER:
3206 case GL_FRAGMENT_SHADER:
3207 break;
3208 default:
3209 return error(GL_INVALID_ENUM);
3210 }
3211
3212 switch(precisiontype)
3213 {
3214 case GL_LOW_FLOAT:
3215 case GL_MEDIUM_FLOAT:
3216 case GL_HIGH_FLOAT:
3217 // IEEE 754 single-precision
3218 range[0] = 127;
3219 range[1] = 127;
3220 *precision = 23;
3221 break;
3222 case GL_LOW_INT:
3223 case GL_MEDIUM_INT:
3224 case GL_HIGH_INT:
3225 // Full integer precision is supported
3226 range[0] = 31;
3227 range[1] = 30;
3228 *precision = 0;
3229 break;
3230 default:
3231 return error(GL_INVALID_ENUM);
3232 }
3233}
3234
3235void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3236{
3237 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3238 shader, bufsize, length, source);
3239
3240 if(bufsize < 0)
3241 {
3242 return error(GL_INVALID_VALUE);
3243 }
3244
Chris Forbes108f3e12018-08-30 19:41:59 -07003245 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003246
3247 if(context)
3248 {
3249 es2::Shader *shaderObject = context->getShader(shader);
3250
3251 if(!shaderObject)
3252 {
3253 if(context->getProgram(shader))
3254 {
3255 return error(GL_INVALID_OPERATION);
3256 }
3257 else
3258 {
3259 return error(GL_INVALID_VALUE);
3260 }
3261 }
3262
3263 shaderObject->getSource(bufsize, length, source);
3264 }
3265}
3266
3267const GLubyte* GetString(GLenum name)
3268{
3269 TRACE("(GLenum name = 0x%X)", name);
3270
3271 switch(name)
3272 {
3273 case GL_VENDOR:
3274 return (GLubyte*)"Google Inc.";
3275 case GL_RENDERER:
3276 return (GLubyte*)"Google SwiftShader";
3277 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003278 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003279 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003280 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003281 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003282 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003283 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003284 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3285 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003286 default:
3287 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3288 }
3289}
3290
3291void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3292{
3293 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3294
Chris Forbes108f3e12018-08-30 19:41:59 -07003295 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003296
3297 if(context)
3298 {
3299 es2::Texture *texture;
3300
Nicolas Capens0bac2852016-05-07 06:09:58 -04003301 switch(target)
3302 {
Nicolas Capens83463112018-06-12 23:55:16 -04003303 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3304 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3305 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3306 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3307 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3308 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003309 default:
3310 return error(GL_INVALID_ENUM);
3311 }
3312
3313 switch(pname)
3314 {
3315 case GL_TEXTURE_MAG_FILTER:
3316 *params = (GLfloat)texture->getMagFilter();
3317 break;
3318 case GL_TEXTURE_MIN_FILTER:
3319 *params = (GLfloat)texture->getMinFilter();
3320 break;
3321 case GL_TEXTURE_WRAP_S:
3322 *params = (GLfloat)texture->getWrapS();
3323 break;
3324 case GL_TEXTURE_WRAP_T:
3325 *params = (GLfloat)texture->getWrapT();
3326 break;
3327 case GL_TEXTURE_WRAP_R_OES:
3328 *params = (GLfloat)texture->getWrapR();
3329 break;
3330 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3331 *params = texture->getMaxAnisotropy();
3332 break;
3333 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3334 *params = (GLfloat)1;
3335 break;
3336 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003337 *params = (GLfloat)texture->getBaseLevel();
3338 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003339 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003340 *params = (GLfloat)texture->getCompareFunc();
3341 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003342 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003343 *params = (GLfloat)texture->getCompareMode();
3344 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003345 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003346 *params = (GLfloat)texture->getImmutableFormat();
3347 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003348 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003349 *params = (GLfloat)texture->getImmutableLevels();
3350 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003351 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003352 *params = (GLfloat)texture->getMaxLevel();
3353 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003354 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003355 *params = texture->getMaxLOD();
3356 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003357 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003358 *params = texture->getMinLOD();
3359 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003360 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003361 *params = (GLfloat)texture->getSwizzleR();
3362 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003363 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003364 *params = (GLfloat)texture->getSwizzleG();
3365 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003366 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003367 *params = (GLfloat)texture->getSwizzleB();
3368 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003369 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003370 *params = (GLfloat)texture->getSwizzleA();
3371 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003372 default:
3373 return error(GL_INVALID_ENUM);
3374 }
3375 }
3376}
3377
3378void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3379{
3380 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3381
Chris Forbes108f3e12018-08-30 19:41:59 -07003382 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003383
3384 if(context)
3385 {
3386 es2::Texture *texture;
3387
Nicolas Capens0bac2852016-05-07 06:09:58 -04003388 switch(target)
3389 {
Nicolas Capens83463112018-06-12 23:55:16 -04003390 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3391 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3392 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3393 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3394 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3395 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003396 default:
3397 return error(GL_INVALID_ENUM);
3398 }
3399
3400 switch(pname)
3401 {
3402 case GL_TEXTURE_MAG_FILTER:
3403 *params = texture->getMagFilter();
3404 break;
3405 case GL_TEXTURE_MIN_FILTER:
3406 *params = texture->getMinFilter();
3407 break;
3408 case GL_TEXTURE_WRAP_S:
3409 *params = texture->getWrapS();
3410 break;
3411 case GL_TEXTURE_WRAP_T:
3412 *params = texture->getWrapT();
3413 break;
3414 case GL_TEXTURE_WRAP_R_OES:
3415 *params = texture->getWrapR();
3416 break;
3417 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3418 *params = (GLint)texture->getMaxAnisotropy();
3419 break;
3420 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3421 *params = 1;
3422 break;
3423 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003424 *params = texture->getBaseLevel();
3425 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003426 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003427 *params = (GLint)texture->getCompareFunc();
3428 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003429 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003430 *params = (GLint)texture->getCompareMode();
3431 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003432 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003433 *params = (GLint)texture->getImmutableFormat();
3434 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003435 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003436 *params = (GLint)texture->getImmutableLevels();
3437 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003438 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003439 *params = texture->getMaxLevel();
3440 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003441 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003442 *params = (GLint)roundf(texture->getMaxLOD());
3443 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003444 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003445 *params = (GLint)roundf(texture->getMinLOD());
3446 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003447 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003448 *params = (GLint)texture->getSwizzleR();
3449 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003450 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003451 *params = (GLint)texture->getSwizzleG();
3452 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003453 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003454 *params = (GLint)texture->getSwizzleB();
3455 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003456 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003457 *params = (GLint)texture->getSwizzleA();
3458 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003459 default:
3460 return error(GL_INVALID_ENUM);
3461 }
3462 }
3463}
3464
3465void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3466{
3467 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3468 program, location, bufSize, params);
3469
3470 if(bufSize < 0)
3471 {
3472 return error(GL_INVALID_VALUE);
3473 }
3474
Chris Forbes108f3e12018-08-30 19:41:59 -07003475 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003476
3477 if(context)
3478 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003479 es2::Program *programObject = context->getProgram(program);
3480
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003481 if(!programObject)
3482 {
3483 if(context->getShader(program))
3484 {
3485 return error(GL_INVALID_OPERATION);
3486 }
3487 else
3488 {
3489 return error(GL_INVALID_VALUE);
3490 }
3491 }
3492
3493 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003494 {
3495 return error(GL_INVALID_OPERATION);
3496 }
3497
3498 if(!programObject->getUniformfv(location, &bufSize, params))
3499 {
3500 return error(GL_INVALID_OPERATION);
3501 }
3502 }
3503}
3504
3505void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3506{
3507 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3508
Chris Forbes108f3e12018-08-30 19:41:59 -07003509 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003510
3511 if(context)
3512 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003513 es2::Program *programObject = context->getProgram(program);
3514
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003515 if(!programObject)
3516 {
3517 if(context->getShader(program))
3518 {
3519 return error(GL_INVALID_OPERATION);
3520 }
3521 else
3522 {
3523 return error(GL_INVALID_VALUE);
3524 }
3525 }
3526
3527 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003528 {
3529 return error(GL_INVALID_OPERATION);
3530 }
3531
3532 if(!programObject->getUniformfv(location, nullptr, params))
3533 {
3534 return error(GL_INVALID_OPERATION);
3535 }
3536 }
3537}
3538
3539void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3540{
3541 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3542 program, location, bufSize, params);
3543
3544 if(bufSize < 0)
3545 {
3546 return error(GL_INVALID_VALUE);
3547 }
3548
Chris Forbes108f3e12018-08-30 19:41:59 -07003549 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003550
3551 if(context)
3552 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003553 es2::Program *programObject = context->getProgram(program);
3554
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003555 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003556 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003557 if(context->getShader(program))
3558 {
3559 return error(GL_INVALID_OPERATION);
3560 }
3561 else
3562 {
3563 return error(GL_INVALID_VALUE);
3564 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003565 }
3566
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003567 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003568 {
3569 return error(GL_INVALID_OPERATION);
3570 }
3571
3572 if(!programObject->getUniformiv(location, &bufSize, params))
3573 {
3574 return error(GL_INVALID_OPERATION);
3575 }
3576 }
3577}
3578
3579void GetUniformiv(GLuint program, GLint location, GLint* params)
3580{
3581 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3582
Chris Forbes108f3e12018-08-30 19:41:59 -07003583 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003584
3585 if(context)
3586 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003587 es2::Program *programObject = context->getProgram(program);
3588
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003589 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003590 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003591 if(context->getShader(program))
3592 {
3593 return error(GL_INVALID_OPERATION);
3594 }
3595 else
3596 {
3597 return error(GL_INVALID_VALUE);
3598 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003599 }
3600
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003601 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003602 {
3603 return error(GL_INVALID_OPERATION);
3604 }
3605
3606 if(!programObject->getUniformiv(location, nullptr, params))
3607 {
3608 return error(GL_INVALID_OPERATION);
3609 }
3610 }
3611}
3612
3613int GetUniformLocation(GLuint program, const GLchar* name)
3614{
3615 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3616
Chris Forbes108f3e12018-08-30 19:41:59 -07003617 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003618
3619 if(strstr(name, "gl_") == name)
3620 {
3621 return -1;
3622 }
3623
3624 if(context)
3625 {
3626 es2::Program *programObject = context->getProgram(program);
3627
3628 if(!programObject)
3629 {
3630 if(context->getShader(program))
3631 {
3632 return error(GL_INVALID_OPERATION, -1);
3633 }
3634 else
3635 {
3636 return error(GL_INVALID_VALUE, -1);
3637 }
3638 }
3639
3640 if(!programObject->isLinked())
3641 {
3642 return error(GL_INVALID_OPERATION, -1);
3643 }
3644
3645 return programObject->getUniformLocation(name);
3646 }
3647
3648 return -1;
3649}
3650
3651void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3652{
3653 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3654
Chris Forbes108f3e12018-08-30 19:41:59 -07003655 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003656
3657 if(context)
3658 {
3659 if(index >= es2::MAX_VERTEX_ATTRIBS)
3660 {
3661 return error(GL_INVALID_VALUE);
3662 }
3663
3664 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3665
Nicolas Capens0bac2852016-05-07 06:09:58 -04003666 switch(pname)
3667 {
3668 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3669 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3670 break;
3671 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3672 *params = (GLfloat)attribState.mSize;
3673 break;
3674 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3675 *params = (GLfloat)attribState.mStride;
3676 break;
3677 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3678 *params = (GLfloat)attribState.mType;
3679 break;
3680 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3681 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3682 break;
3683 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3684 *params = (GLfloat)attribState.mBoundBuffer.name();
3685 break;
3686 case GL_CURRENT_VERTEX_ATTRIB:
3687 {
3688 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3689 for(int i = 0; i < 4; ++i)
3690 {
3691 params[i] = attrib.getCurrentValueF(i);
3692 }
3693 }
3694 break;
3695 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003696 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3697 break;
3698 default:
3699 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003700 }
3701 }
3702}
3703
3704void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3705{
3706 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3707
Chris Forbes108f3e12018-08-30 19:41:59 -07003708 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003709
3710 if(context)
3711 {
3712 if(index >= es2::MAX_VERTEX_ATTRIBS)
3713 {
3714 return error(GL_INVALID_VALUE);
3715 }
3716
3717 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3718
Nicolas Capens0bac2852016-05-07 06:09:58 -04003719 switch(pname)
3720 {
3721 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3722 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3723 break;
3724 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3725 *params = attribState.mSize;
3726 break;
3727 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3728 *params = attribState.mStride;
3729 break;
3730 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3731 *params = attribState.mType;
3732 break;
3733 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3734 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3735 break;
3736 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3737 *params = attribState.mBoundBuffer.name();
3738 break;
3739 case GL_CURRENT_VERTEX_ATTRIB:
3740 {
3741 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3742 for(int i = 0; i < 4; ++i)
3743 {
3744 float currentValue = attrib.getCurrentValueF(i);
3745 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3746 }
3747 }
3748 break;
3749 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003750 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3751 break;
3752 default:
3753 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003754 }
3755 }
3756}
3757
3758void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3759{
3760 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3761
Chris Forbes108f3e12018-08-30 19:41:59 -07003762 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003763
3764 if(context)
3765 {
3766 if(index >= es2::MAX_VERTEX_ATTRIBS)
3767 {
3768 return error(GL_INVALID_VALUE);
3769 }
3770
3771 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3772 {
3773 return error(GL_INVALID_ENUM);
3774 }
3775
3776 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3777 }
3778}
3779
3780void Hint(GLenum target, GLenum mode)
3781{
3782 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3783
3784 switch(mode)
3785 {
3786 case GL_FASTEST:
3787 case GL_NICEST:
3788 case GL_DONT_CARE:
3789 break;
3790 default:
3791 return error(GL_INVALID_ENUM);
3792 }
3793
Chris Forbes108f3e12018-08-30 19:41:59 -07003794 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003795
3796 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003797 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003798 switch(target)
3799 {
3800 case GL_GENERATE_MIPMAP_HINT:
3801 context->setGenerateMipmapHint(mode);
3802 break;
3803 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3804 context->setFragmentShaderDerivativeHint(mode);
3805 break;
3806 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3807 context->setTextureFilteringHint(mode);
3808 break;
3809 default:
3810 return error(GL_INVALID_ENUM);
3811 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003812 }
3813}
3814
3815GLboolean IsBuffer(GLuint buffer)
3816{
3817 TRACE("(GLuint buffer = %d)", buffer);
3818
Chris Forbes108f3e12018-08-30 19:41:59 -07003819 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003820
3821 if(context && buffer)
3822 {
3823 es2::Buffer *bufferObject = context->getBuffer(buffer);
3824
3825 if(bufferObject)
3826 {
3827 return GL_TRUE;
3828 }
3829 }
3830
3831 return GL_FALSE;
3832}
3833
3834GLboolean IsEnabled(GLenum cap)
3835{
3836 TRACE("(GLenum cap = 0x%X)", cap);
3837
Chris Forbes108f3e12018-08-30 19:41:59 -07003838 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003839
3840 if(context)
3841 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003842 switch(cap)
3843 {
3844 case GL_CULL_FACE: return context->isCullFaceEnabled();
3845 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3846 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3847 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3848 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3849 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3850 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3851 case GL_BLEND: return context->isBlendEnabled();
3852 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003853 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3854 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003855 default:
3856 return error(GL_INVALID_ENUM, false);
3857 }
3858 }
3859
3860 return false;
3861}
3862
3863GLboolean IsFenceNV(GLuint fence)
3864{
3865 TRACE("(GLuint fence = %d)", fence);
3866
Chris Forbes108f3e12018-08-30 19:41:59 -07003867 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003868
3869 if(context)
3870 {
3871 es2::Fence *fenceObject = context->getFence(fence);
3872
3873 if(!fenceObject)
3874 {
3875 return GL_FALSE;
3876 }
3877
3878 return fenceObject->isFence();
3879 }
3880
3881 return GL_FALSE;
3882}
3883
3884GLboolean IsFramebuffer(GLuint framebuffer)
3885{
3886 TRACE("(GLuint framebuffer = %d)", framebuffer);
3887
Chris Forbes108f3e12018-08-30 19:41:59 -07003888 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003889
3890 if(context && framebuffer)
3891 {
3892 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3893
3894 if(framebufferObject)
3895 {
3896 return GL_TRUE;
3897 }
3898 }
3899
3900 return GL_FALSE;
3901}
3902
3903GLboolean IsProgram(GLuint program)
3904{
3905 TRACE("(GLuint program = %d)", program);
3906
Chris Forbes108f3e12018-08-30 19:41:59 -07003907 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003908
3909 if(context && program)
3910 {
3911 es2::Program *programObject = context->getProgram(program);
3912
3913 if(programObject)
3914 {
3915 return GL_TRUE;
3916 }
3917 }
3918
3919 return GL_FALSE;
3920}
3921
3922GLboolean IsQueryEXT(GLuint name)
3923{
3924 TRACE("(GLuint name = %d)", name);
3925
3926 if(name == 0)
3927 {
3928 return GL_FALSE;
3929 }
3930
Chris Forbes108f3e12018-08-30 19:41:59 -07003931 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003932
3933 if(context)
3934 {
3935 es2::Query *queryObject = context->getQuery(name);
3936
3937 if(queryObject)
3938 {
3939 return GL_TRUE;
3940 }
3941 }
3942
3943 return GL_FALSE;
3944}
3945
3946GLboolean IsRenderbuffer(GLuint renderbuffer)
3947{
3948 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3949
Chris Forbes108f3e12018-08-30 19:41:59 -07003950 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003951
3952 if(context && renderbuffer)
3953 {
3954 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3955
3956 if(renderbufferObject)
3957 {
3958 return GL_TRUE;
3959 }
3960 }
3961
3962 return GL_FALSE;
3963}
3964
3965GLboolean IsShader(GLuint shader)
3966{
3967 TRACE("(GLuint shader = %d)", shader);
3968
Chris Forbes108f3e12018-08-30 19:41:59 -07003969 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003970
3971 if(context && shader)
3972 {
3973 es2::Shader *shaderObject = context->getShader(shader);
3974
3975 if(shaderObject)
3976 {
3977 return GL_TRUE;
3978 }
3979 }
3980
3981 return GL_FALSE;
3982}
3983
3984GLboolean IsTexture(GLuint texture)
3985{
3986 TRACE("(GLuint texture = %d)", texture);
3987
Chris Forbes108f3e12018-08-30 19:41:59 -07003988 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003989
3990 if(context && texture)
3991 {
3992 es2::Texture *textureObject = context->getTexture(texture);
3993
3994 if(textureObject)
3995 {
3996 return GL_TRUE;
3997 }
3998 }
3999
4000 return GL_FALSE;
4001}
4002
4003void LineWidth(GLfloat width)
4004{
4005 TRACE("(GLfloat width = %f)", width);
4006
4007 if(width <= 0.0f)
4008 {
4009 return error(GL_INVALID_VALUE);
4010 }
4011
Chris Forbes108f3e12018-08-30 19:41:59 -07004012 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004013
4014 if(context)
4015 {
4016 context->setLineWidth(width);
4017 }
4018}
4019
4020void LinkProgram(GLuint program)
4021{
4022 TRACE("(GLuint program = %d)", program);
4023
Chris Forbes108f3e12018-08-30 19:41:59 -07004024 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004025
4026 if(context)
4027 {
4028 es2::Program *programObject = context->getProgram(program);
4029
4030 if(!programObject)
4031 {
4032 if(context->getShader(program))
4033 {
4034 return error(GL_INVALID_OPERATION);
4035 }
4036 else
4037 {
4038 return error(GL_INVALID_VALUE);
4039 }
4040 }
4041
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004042 if(programObject == context->getCurrentProgram())
4043 {
4044 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4045 if(transformFeedback && transformFeedback->isActive())
4046 {
4047 return error(GL_INVALID_OPERATION);
4048 }
4049 }
4050
Nicolas Capens0bac2852016-05-07 06:09:58 -04004051 programObject->link();
4052 }
4053}
4054
4055void PixelStorei(GLenum pname, GLint param)
4056{
4057 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4058
Chris Forbes108f3e12018-08-30 19:41:59 -07004059 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004060
4061 if(context)
4062 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004063 switch(pname)
4064 {
4065 case GL_UNPACK_ALIGNMENT:
4066 if(param != 1 && param != 2 && param != 4 && param != 8)
4067 {
4068 return error(GL_INVALID_VALUE);
4069 }
4070 context->setUnpackAlignment(param);
4071 break;
4072 case GL_PACK_ALIGNMENT:
4073 if(param != 1 && param != 2 && param != 4 && param != 8)
4074 {
4075 return error(GL_INVALID_VALUE);
4076 }
4077 context->setPackAlignment(param);
4078 break;
4079 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004080 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 {
Nicolas Capens83463112018-06-12 23:55:16 -04004082 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 }
Nicolas Capens83463112018-06-12 23:55:16 -04004084 context->setPackRowLength(param);
4085 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004086 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004087 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 {
Nicolas Capens83463112018-06-12 23:55:16 -04004089 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 }
Nicolas Capens83463112018-06-12 23:55:16 -04004091 context->setPackSkipPixels(param);
4092 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004093 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004094 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 {
Nicolas Capens83463112018-06-12 23:55:16 -04004096 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004097 }
Nicolas Capens83463112018-06-12 23:55:16 -04004098 context->setPackSkipRows(param);
4099 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004100 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004101 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 {
Nicolas Capens83463112018-06-12 23:55:16 -04004103 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004104 }
Nicolas Capens83463112018-06-12 23:55:16 -04004105 context->setUnpackRowLength(param);
4106 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004107 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004108 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004109 {
Nicolas Capens83463112018-06-12 23:55:16 -04004110 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004111 }
Nicolas Capens83463112018-06-12 23:55:16 -04004112 context->setUnpackImageHeight(param);
4113 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004114 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004115 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004116 {
Nicolas Capens83463112018-06-12 23:55:16 -04004117 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004118 }
Nicolas Capens83463112018-06-12 23:55:16 -04004119 context->setUnpackSkipPixels(param);
4120 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004121 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004122 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004123 {
Nicolas Capens83463112018-06-12 23:55:16 -04004124 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004125 }
Nicolas Capens83463112018-06-12 23:55:16 -04004126 context->setUnpackSkipRows(param);
4127 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004128 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004129 if(param < 0)
4130 {
4131 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004132 }
Nicolas Capens83463112018-06-12 23:55:16 -04004133 context->setUnpackSkipImages(param);
4134 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004135 default:
4136 return error(GL_INVALID_ENUM);
4137 }
4138 }
4139}
4140
4141void PolygonOffset(GLfloat factor, GLfloat units)
4142{
4143 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4144
Chris Forbes108f3e12018-08-30 19:41:59 -07004145 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004146
4147 if(context)
4148 {
4149 context->setPolygonOffsetParams(factor, units);
4150 }
4151}
4152
4153void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4154 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4155{
4156 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4157 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4158 x, y, width, height, format, type, bufSize, data);
4159
4160 if(width < 0 || height < 0 || bufSize < 0)
4161 {
4162 return error(GL_INVALID_VALUE);
4163 }
4164
Chris Forbes108f3e12018-08-30 19:41:59 -07004165 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004166
4167 if(context)
4168 {
4169 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4170 }
4171}
4172
4173void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4174{
4175 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4176 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4177 x, y, width, height, format, type, pixels);
4178
4179 if(width < 0 || height < 0)
4180 {
4181 return error(GL_INVALID_VALUE);
4182 }
4183
Chris Forbes108f3e12018-08-30 19:41:59 -07004184 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004185
4186 if(context)
4187 {
4188 context->readPixels(x, y, width, height, format, type, nullptr, pixels);
4189 }
4190}
4191
4192void ReleaseShaderCompiler(void)
4193{
4194 TRACE("()");
4195
4196 es2::Shader::releaseCompiler();
4197}
4198
Nicolas Capens400667e2017-03-29 14:40:14 -04004199void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004200{
4201 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4202 target, samples, internalformat, width, height);
4203
4204 switch(target)
4205 {
4206 case GL_RENDERBUFFER:
4207 break;
4208 default:
4209 return error(GL_INVALID_ENUM);
4210 }
4211
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004212 if(width < 0 || height < 0 || samples < 0 ||
4213 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4214 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004215 {
4216 return error(GL_INVALID_VALUE);
4217 }
4218
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004219 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004220 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004221 {
4222 return error(GL_INVALID_OPERATION);
4223 }
4224
Chris Forbes108f3e12018-08-30 19:41:59 -07004225 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004226
4227 if(context)
4228 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004229 GLuint handle = context->getRenderbufferName();
4230 if(handle == 0)
4231 {
4232 return error(GL_INVALID_OPERATION);
4233 }
4234
Nicolas Capens83463112018-06-12 23:55:16 -04004235 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004236 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004237 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004238 }
Nicolas Capens83463112018-06-12 23:55:16 -04004239 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004240 {
4241 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4242 }
Nicolas Capens83463112018-06-12 23:55:16 -04004243 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004244 {
4245 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4246 }
Nicolas Capens83463112018-06-12 23:55:16 -04004247 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004248 {
4249 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4250 }
4251 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004252 }
4253}
4254
Nicolas Capens400667e2017-03-29 14:40:14 -04004255void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4256{
4257 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4258}
4259
Nicolas Capens0bac2852016-05-07 06:09:58 -04004260void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4261{
Nicolas Capens400667e2017-03-29 14:40:14 -04004262 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004263}
4264
4265void SampleCoverage(GLclampf value, GLboolean invert)
4266{
4267 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4268
Chris Forbes108f3e12018-08-30 19:41:59 -07004269 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004270
4271 if(context)
4272 {
Nicolas Capens51814272018-10-15 13:01:22 -04004273 context->setSampleCoverageParams(es2::clamp01(value), invert != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004274 }
4275}
4276
4277void SetFenceNV(GLuint fence, GLenum condition)
4278{
4279 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4280
4281 if(condition != GL_ALL_COMPLETED_NV)
4282 {
4283 return error(GL_INVALID_ENUM);
4284 }
4285
Chris Forbes108f3e12018-08-30 19:41:59 -07004286 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004287
4288 if(context)
4289 {
4290 es2::Fence *fenceObject = context->getFence(fence);
4291
4292 if(!fenceObject)
4293 {
4294 return error(GL_INVALID_OPERATION);
4295 }
4296
4297 fenceObject->setFence(condition);
4298 }
4299}
4300
4301void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4302{
4303 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4304
4305 if(width < 0 || height < 0)
4306 {
4307 return error(GL_INVALID_VALUE);
4308 }
4309
Chris Forbes108f3e12018-08-30 19:41:59 -07004310 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004311
4312 if(context)
4313 {
4314 context->setScissorParams(x, y, width, height);
4315 }
4316}
4317
4318void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4319{
4320 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4321 "const GLvoid* binary = %p, GLsizei length = %d)",
4322 n, shaders, binaryformat, binary, length);
4323
4324 // No binary shader formats are supported.
4325 return error(GL_INVALID_ENUM);
4326}
4327
4328void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4329{
4330 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4331 shader, count, string, length);
4332
4333 if(count < 0)
4334 {
4335 return error(GL_INVALID_VALUE);
4336 }
4337
Chris Forbes108f3e12018-08-30 19:41:59 -07004338 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004339
4340 if(context)
4341 {
4342 es2::Shader *shaderObject = context->getShader(shader);
4343
4344 if(!shaderObject)
4345 {
4346 if(context->getProgram(shader))
4347 {
4348 return error(GL_INVALID_OPERATION);
4349 }
4350 else
4351 {
4352 return error(GL_INVALID_VALUE);
4353 }
4354 }
4355
4356 shaderObject->setSource(count, string, length);
4357 }
4358}
4359
Nicolas Capens0bac2852016-05-07 06:09:58 -04004360void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4361{
4362 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4363
4364 switch(face)
4365 {
4366 case GL_FRONT:
4367 case GL_BACK:
4368 case GL_FRONT_AND_BACK:
4369 break;
4370 default:
4371 return error(GL_INVALID_ENUM);
4372 }
4373
4374 switch(func)
4375 {
4376 case GL_NEVER:
4377 case GL_ALWAYS:
4378 case GL_LESS:
4379 case GL_LEQUAL:
4380 case GL_EQUAL:
4381 case GL_GEQUAL:
4382 case GL_GREATER:
4383 case GL_NOTEQUAL:
4384 break;
4385 default:
4386 return error(GL_INVALID_ENUM);
4387 }
4388
Chris Forbes108f3e12018-08-30 19:41:59 -07004389 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004390
4391 if(context)
4392 {
4393 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4394 {
4395 context->setStencilParams(func, ref, mask);
4396 }
4397
4398 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4399 {
4400 context->setStencilBackParams(func, ref, mask);
4401 }
4402 }
4403}
4404
Nicolas Capens805d7612018-08-02 13:56:32 -04004405void StencilFunc(GLenum func, GLint ref, GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004406{
Nicolas Capens805d7612018-08-02 13:56:32 -04004407 StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004408}
4409
4410void StencilMaskSeparate(GLenum face, GLuint mask)
4411{
4412 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4413
4414 switch(face)
4415 {
4416 case GL_FRONT:
4417 case GL_BACK:
4418 case GL_FRONT_AND_BACK:
4419 break;
4420 default:
4421 return error(GL_INVALID_ENUM);
4422 }
4423
Chris Forbes108f3e12018-08-30 19:41:59 -07004424 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004425
4426 if(context)
4427 {
4428 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4429 {
4430 context->setStencilWritemask(mask);
4431 }
4432
4433 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4434 {
4435 context->setStencilBackWritemask(mask);
4436 }
4437 }
4438}
4439
Nicolas Capens805d7612018-08-02 13:56:32 -04004440void StencilMask(GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004441{
Nicolas Capens805d7612018-08-02 13:56:32 -04004442 StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004443}
4444
4445void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4446{
4447 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4448 face, fail, zfail, zpass);
4449
4450 switch(face)
4451 {
4452 case GL_FRONT:
4453 case GL_BACK:
4454 case GL_FRONT_AND_BACK:
4455 break;
4456 default:
4457 return error(GL_INVALID_ENUM);
4458 }
4459
4460 switch(fail)
4461 {
4462 case GL_ZERO:
4463 case GL_KEEP:
4464 case GL_REPLACE:
4465 case GL_INCR:
4466 case GL_DECR:
4467 case GL_INVERT:
4468 case GL_INCR_WRAP:
4469 case GL_DECR_WRAP:
4470 break;
4471 default:
4472 return error(GL_INVALID_ENUM);
4473 }
4474
4475 switch(zfail)
4476 {
4477 case GL_ZERO:
4478 case GL_KEEP:
4479 case GL_REPLACE:
4480 case GL_INCR:
4481 case GL_DECR:
4482 case GL_INVERT:
4483 case GL_INCR_WRAP:
4484 case GL_DECR_WRAP:
4485 break;
4486 default:
4487 return error(GL_INVALID_ENUM);
4488 }
4489
4490 switch(zpass)
4491 {
4492 case GL_ZERO:
4493 case GL_KEEP:
4494 case GL_REPLACE:
4495 case GL_INCR:
4496 case GL_DECR:
4497 case GL_INVERT:
4498 case GL_INCR_WRAP:
4499 case GL_DECR_WRAP:
4500 break;
4501 default:
4502 return error(GL_INVALID_ENUM);
4503 }
4504
Chris Forbes108f3e12018-08-30 19:41:59 -07004505 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004506
4507 if(context)
4508 {
4509 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4510 {
4511 context->setStencilOperations(fail, zfail, zpass);
4512 }
4513
4514 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4515 {
4516 context->setStencilBackOperations(fail, zfail, zpass);
4517 }
4518 }
4519}
4520
Nicolas Capens805d7612018-08-02 13:56:32 -04004521void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4522{
4523 StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4524}
4525
Nicolas Capens0bac2852016-05-07 06:09:58 -04004526GLboolean TestFenceNV(GLuint fence)
4527{
4528 TRACE("(GLuint fence = %d)", fence);
4529
Chris Forbes108f3e12018-08-30 19:41:59 -07004530 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004531
4532 if(context)
4533 {
4534 es2::Fence *fenceObject = context->getFence(fence);
4535
4536 if(!fenceObject)
4537 {
4538 return error(GL_INVALID_OPERATION, GL_TRUE);
4539 }
4540
4541 return fenceObject->testFence();
4542 }
4543
4544 return GL_TRUE;
4545}
4546
4547void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004548 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004549{
4550 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004551 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4552 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004553
4554 if(!validImageSize(level, width, height))
4555 {
4556 return error(GL_INVALID_VALUE);
4557 }
4558
Chris Forbes108f3e12018-08-30 19:41:59 -07004559 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004560
4561 if(context)
4562 {
Nicolas Capens83463112018-06-12 23:55:16 -04004563 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004564 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4565 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4566 {
4567 internalformat = GL_BGRA_EXT;
4568 }
4569
Nicolas Capens83463112018-06-12 23:55:16 -04004570 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004571 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004572 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004573 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004574 }
4575
4576 if(border != 0)
4577 {
4578 return error(GL_INVALID_VALUE);
4579 }
4580
4581 switch(target)
4582 {
Alexis Hetu46768622018-01-16 22:09:28 -05004583 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004584 if(level != 0)
4585 {
4586 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4587 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004588 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004589 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004590 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4591 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4592 {
4593 return error(GL_INVALID_VALUE);
4594 }
4595 break;
4596 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4597 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4598 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4599 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4600 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4601 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4602 if(width != height)
4603 {
4604 return error(GL_INVALID_VALUE);
4605 }
4606
4607 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4608 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4609 {
4610 return error(GL_INVALID_VALUE);
4611 }
4612 break;
4613 default:
4614 return error(GL_INVALID_ENUM);
4615 }
4616
Nicolas Capens5555af42017-12-14 13:14:03 -05004617 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004618 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004619 {
4620 return error(validationError);
4621 }
4622
Nicolas Capens894858a2018-03-22 00:55:23 -04004623 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4624
Alexis Hetu46768622018-01-16 22:09:28 -05004625 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004626 {
Alexis Hetu46768622018-01-16 22:09:28 -05004627 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004628
4629 if(!texture)
4630 {
4631 return error(GL_INVALID_OPERATION);
4632 }
4633
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004634 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004635 }
4636 else
4637 {
4638 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4639
4640 if(!texture)
4641 {
4642 return error(GL_INVALID_OPERATION);
4643 }
4644
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004645 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004646 }
4647 }
4648}
4649
4650void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4651{
4652 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4653
Chris Forbes108f3e12018-08-30 19:41:59 -07004654 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004655
4656 if(context)
4657 {
4658 es2::Texture *texture;
4659
Nicolas Capens0bac2852016-05-07 06:09:58 -04004660 switch(target)
4661 {
Nicolas Capens83463112018-06-12 23:55:16 -04004662 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4663 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4664 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4665 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4666 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4667 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004668 default:
4669 return error(GL_INVALID_ENUM);
4670 }
4671
4672 switch(pname)
4673 {
4674 case GL_TEXTURE_WRAP_S:
4675 if(!texture->setWrapS((GLenum)param))
4676 {
4677 return error(GL_INVALID_ENUM);
4678 }
4679 break;
4680 case GL_TEXTURE_WRAP_T:
4681 if(!texture->setWrapT((GLenum)param))
4682 {
4683 return error(GL_INVALID_ENUM);
4684 }
4685 break;
4686 case GL_TEXTURE_WRAP_R_OES:
4687 if(!texture->setWrapR((GLenum)param))
4688 {
4689 return error(GL_INVALID_ENUM);
4690 }
4691 break;
4692 case GL_TEXTURE_MIN_FILTER:
4693 if(!texture->setMinFilter((GLenum)param))
4694 {
4695 return error(GL_INVALID_ENUM);
4696 }
4697 break;
4698 case GL_TEXTURE_MAG_FILTER:
4699 if(!texture->setMagFilter((GLenum)param))
4700 {
4701 return error(GL_INVALID_ENUM);
4702 }
4703 break;
4704 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4705 if(!texture->setMaxAnisotropy(param))
4706 {
4707 return error(GL_INVALID_VALUE);
4708 }
4709 break;
4710 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004711 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004712 {
4713 return error(GL_INVALID_VALUE);
4714 }
4715 break;
4716 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004717 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004718 {
4719 return error(GL_INVALID_VALUE);
4720 }
4721 break;
4722 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004723 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004724 {
4725 return error(GL_INVALID_VALUE);
4726 }
4727 break;
4728 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004729 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004730 {
4731 return error(GL_INVALID_VALUE);
4732 }
4733 break;
4734 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004735 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004736 {
4737 return error(GL_INVALID_VALUE);
4738 }
4739 break;
4740 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004741 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004742 {
4743 return error(GL_INVALID_VALUE);
4744 }
4745 break;
4746 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004747 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004748 {
4749 return error(GL_INVALID_VALUE);
4750 }
4751 break;
4752 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004753 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004754 {
4755 return error(GL_INVALID_VALUE);
4756 }
4757 break;
4758 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004759 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004760 {
4761 return error(GL_INVALID_VALUE);
4762 }
4763 break;
4764 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004765 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004766 {
4767 return error(GL_INVALID_VALUE);
4768 }
4769 break;
4770 default:
4771 return error(GL_INVALID_ENUM);
4772 }
4773 }
4774}
4775
4776void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4777{
Nicolas Capens805d7612018-08-02 13:56:32 -04004778 TexParameterf(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004779}
4780
4781void TexParameteri(GLenum target, GLenum pname, GLint param)
4782{
4783 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4784
Chris Forbes108f3e12018-08-30 19:41:59 -07004785 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004786
4787 if(context)
4788 {
4789 es2::Texture *texture;
4790
Nicolas Capens0bac2852016-05-07 06:09:58 -04004791 switch(target)
4792 {
Nicolas Capens83463112018-06-12 23:55:16 -04004793 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4794 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4795 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4796 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4797 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4798 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004799 default:
4800 return error(GL_INVALID_ENUM);
4801 }
4802
4803 switch(pname)
4804 {
4805 case GL_TEXTURE_WRAP_S:
4806 if(!texture->setWrapS((GLenum)param))
4807 {
4808 return error(GL_INVALID_ENUM);
4809 }
4810 break;
4811 case GL_TEXTURE_WRAP_T:
4812 if(!texture->setWrapT((GLenum)param))
4813 {
4814 return error(GL_INVALID_ENUM);
4815 }
4816 break;
4817 case GL_TEXTURE_WRAP_R_OES:
4818 if(!texture->setWrapR((GLenum)param))
4819 {
4820 return error(GL_INVALID_ENUM);
4821 }
4822 break;
4823 case GL_TEXTURE_MIN_FILTER:
4824 if(!texture->setMinFilter((GLenum)param))
4825 {
4826 return error(GL_INVALID_ENUM);
4827 }
4828 break;
4829 case GL_TEXTURE_MAG_FILTER:
4830 if(!texture->setMagFilter((GLenum)param))
4831 {
4832 return error(GL_INVALID_ENUM);
4833 }
4834 break;
4835 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4836 if(!texture->setMaxAnisotropy((GLfloat)param))
4837 {
4838 return error(GL_INVALID_VALUE);
4839 }
4840 break;
4841 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004842 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4843 {
4844 return error(GL_INVALID_OPERATION); // Base level has to be 0
4845 }
Nicolas Capens83463112018-06-12 23:55:16 -04004846 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004847 {
4848 return error(GL_INVALID_VALUE);
4849 }
4850 break;
4851 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004852 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004853 {
4854 return error(GL_INVALID_VALUE);
4855 }
4856 break;
4857 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004858 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004859 {
4860 return error(GL_INVALID_VALUE);
4861 }
4862 break;
4863 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004864 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004865 {
4866 return error(GL_INVALID_VALUE);
4867 }
4868 break;
4869 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004870 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004871 {
4872 return error(GL_INVALID_VALUE);
4873 }
4874 break;
4875 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004876 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004877 {
4878 return error(GL_INVALID_VALUE);
4879 }
4880 break;
4881 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004882 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004883 {
4884 return error(GL_INVALID_VALUE);
4885 }
4886 break;
4887 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004888 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004889 {
4890 return error(GL_INVALID_VALUE);
4891 }
4892 break;
4893 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004894 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004895 {
4896 return error(GL_INVALID_VALUE);
4897 }
4898 break;
4899 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004900 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004901 {
4902 return error(GL_INVALID_VALUE);
4903 }
4904 break;
4905 default:
4906 return error(GL_INVALID_ENUM);
4907 }
4908 }
4909}
4910
4911void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4912{
Nicolas Capens805d7612018-08-02 13:56:32 -04004913 TexParameteri(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004914}
4915
4916void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004917 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004918{
4919 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4920 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004921 "const GLvoid* data = %p)",
4922 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004923
4924 if(!es2::IsTextureTarget(target))
4925 {
4926 return error(GL_INVALID_ENUM);
4927 }
4928
4929 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4930 {
4931 return error(GL_INVALID_VALUE);
4932 }
4933
4934 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4935 {
4936 return error(GL_INVALID_VALUE);
4937 }
4938
4939 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4940 {
4941 return error(GL_INVALID_VALUE);
4942 }
4943
Chris Forbes108f3e12018-08-30 19:41:59 -07004944 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004945
4946 if(context)
4947 {
Alexis Hetu46768622018-01-16 22:09:28 -05004948 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004949 {
Alexis Hetu46768622018-01-16 22:09:28 -05004950 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004951
Nicolas Capens83463112018-06-12 23:55:16 -04004952 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004953 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004954 {
4955 return error(validationError);
4956 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004957
Nicolas Capens5555af42017-12-14 13:14:03 -05004958 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004959 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004960 {
4961 return error(validationError);
4962 }
4963
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004964 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004965 }
4966 else if(es2::IsCubemapTextureTarget(target))
4967 {
4968 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4969
Nicolas Capens83463112018-06-12 23:55:16 -04004970 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004971 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004972 {
4973 return error(validationError);
4974 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004975
Nicolas Capens5555af42017-12-14 13:14:03 -05004976 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004977 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004978 {
4979 return error(validationError);
4980 }
4981
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004982 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004983 }
4984 else UNREACHABLE(target);
4985 }
4986}
4987
Nicolas Capens0bac2852016-05-07 06:09:58 -04004988void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4989{
4990 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4991
4992 if(count < 0)
4993 {
4994 return error(GL_INVALID_VALUE);
4995 }
4996
Chris Forbes108f3e12018-08-30 19:41:59 -07004997 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004998
4999 if(context)
5000 {
5001 es2::Program *program = context->getCurrentProgram();
5002
5003 if(!program)
5004 {
5005 return error(GL_INVALID_OPERATION);
5006 }
5007
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005008 if(location == -1)
5009 {
5010 return;
5011 }
5012
Nicolas Capens0bac2852016-05-07 06:09:58 -04005013 if(!program->setUniform1fv(location, count, v))
5014 {
5015 return error(GL_INVALID_OPERATION);
5016 }
5017 }
5018}
5019
Nicolas Capens805d7612018-08-02 13:56:32 -04005020void Uniform1f(GLint location, GLfloat x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005021{
Nicolas Capens805d7612018-08-02 13:56:32 -04005022 Uniform1fv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005023}
5024
5025void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5026{
5027 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5028
5029 if(count < 0)
5030 {
5031 return error(GL_INVALID_VALUE);
5032 }
5033
Chris Forbes108f3e12018-08-30 19:41:59 -07005034 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005035
5036 if(context)
5037 {
5038 es2::Program *program = context->getCurrentProgram();
5039
5040 if(!program)
5041 {
5042 return error(GL_INVALID_OPERATION);
5043 }
5044
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005045 if(location == -1)
5046 {
5047 return;
5048 }
5049
Nicolas Capens0bac2852016-05-07 06:09:58 -04005050 if(!program->setUniform1iv(location, count, v))
5051 {
5052 return error(GL_INVALID_OPERATION);
5053 }
5054 }
5055}
5056
Nicolas Capens805d7612018-08-02 13:56:32 -04005057void Uniform1i(GLint location, GLint x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005058{
Nicolas Capens805d7612018-08-02 13:56:32 -04005059 Uniform1iv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005060}
5061
5062void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5063{
5064 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5065
5066 if(count < 0)
5067 {
5068 return error(GL_INVALID_VALUE);
5069 }
5070
Chris Forbes108f3e12018-08-30 19:41:59 -07005071 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005072
5073 if(context)
5074 {
5075 es2::Program *program = context->getCurrentProgram();
5076
5077 if(!program)
5078 {
5079 return error(GL_INVALID_OPERATION);
5080 }
5081
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005082 if(location == -1)
5083 {
5084 return;
5085 }
5086
Nicolas Capens0bac2852016-05-07 06:09:58 -04005087 if(!program->setUniform2fv(location, count, v))
5088 {
5089 return error(GL_INVALID_OPERATION);
5090 }
5091 }
5092}
5093
Nicolas Capens805d7612018-08-02 13:56:32 -04005094void Uniform2f(GLint location, GLfloat x, GLfloat y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005095{
Nicolas Capens805d7612018-08-02 13:56:32 -04005096 GLfloat xy[2] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005097
Nicolas Capens805d7612018-08-02 13:56:32 -04005098 Uniform2fv(location, 1, (GLfloat*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005099}
5100
5101void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5102{
5103 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5104
5105 if(count < 0)
5106 {
5107 return error(GL_INVALID_VALUE);
5108 }
5109
Chris Forbes108f3e12018-08-30 19:41:59 -07005110 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005111
5112 if(context)
5113 {
5114 es2::Program *program = context->getCurrentProgram();
5115
5116 if(!program)
5117 {
5118 return error(GL_INVALID_OPERATION);
5119 }
5120
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005121 if(location == -1)
5122 {
5123 return;
5124 }
5125
Nicolas Capens0bac2852016-05-07 06:09:58 -04005126 if(!program->setUniform2iv(location, count, v))
5127 {
5128 return error(GL_INVALID_OPERATION);
5129 }
5130 }
5131}
5132
Nicolas Capens805d7612018-08-02 13:56:32 -04005133void Uniform2i(GLint location, GLint x, GLint y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005134{
Nicolas Capens805d7612018-08-02 13:56:32 -04005135 GLint xy[4] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005136
Nicolas Capens805d7612018-08-02 13:56:32 -04005137 Uniform2iv(location, 1, (GLint*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005138}
5139
5140void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5141{
5142 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5143
5144 if(count < 0)
5145 {
5146 return error(GL_INVALID_VALUE);
5147 }
5148
Chris Forbes108f3e12018-08-30 19:41:59 -07005149 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005150
5151 if(context)
5152 {
5153 es2::Program *program = context->getCurrentProgram();
5154
5155 if(!program)
5156 {
5157 return error(GL_INVALID_OPERATION);
5158 }
5159
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005160 if(location == -1)
5161 {
5162 return;
5163 }
5164
Nicolas Capens0bac2852016-05-07 06:09:58 -04005165 if(!program->setUniform3fv(location, count, v))
5166 {
5167 return error(GL_INVALID_OPERATION);
5168 }
5169 }
5170}
5171
Nicolas Capens805d7612018-08-02 13:56:32 -04005172void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005173{
Nicolas Capens805d7612018-08-02 13:56:32 -04005174 GLfloat xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005175
Nicolas Capens805d7612018-08-02 13:56:32 -04005176 Uniform3fv(location, 1, (GLfloat*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005177}
5178
5179void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5180{
5181 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5182
5183 if(count < 0)
5184 {
5185 return error(GL_INVALID_VALUE);
5186 }
5187
Chris Forbes108f3e12018-08-30 19:41:59 -07005188 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005189
5190 if(context)
5191 {
5192 es2::Program *program = context->getCurrentProgram();
5193
5194 if(!program)
5195 {
5196 return error(GL_INVALID_OPERATION);
5197 }
5198
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005199 if(location == -1)
5200 {
5201 return;
5202 }
5203
Nicolas Capens0bac2852016-05-07 06:09:58 -04005204 if(!program->setUniform3iv(location, count, v))
5205 {
5206 return error(GL_INVALID_OPERATION);
5207 }
5208 }
5209}
5210
Nicolas Capens805d7612018-08-02 13:56:32 -04005211void Uniform3i(GLint location, GLint x, GLint y, GLint z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005212{
Nicolas Capens805d7612018-08-02 13:56:32 -04005213 GLint xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005214
Nicolas Capens805d7612018-08-02 13:56:32 -04005215 Uniform3iv(location, 1, (GLint*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005216}
5217
5218void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5219{
5220 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5221
5222 if(count < 0)
5223 {
5224 return error(GL_INVALID_VALUE);
5225 }
5226
Chris Forbes108f3e12018-08-30 19:41:59 -07005227 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005228
5229 if(context)
5230 {
5231 es2::Program *program = context->getCurrentProgram();
5232
5233 if(!program)
5234 {
5235 return error(GL_INVALID_OPERATION);
5236 }
5237
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005238 if(location == -1)
5239 {
5240 return;
5241 }
5242
Nicolas Capens0bac2852016-05-07 06:09:58 -04005243 if(!program->setUniform4fv(location, count, v))
5244 {
5245 return error(GL_INVALID_OPERATION);
5246 }
5247 }
5248}
5249
Nicolas Capens805d7612018-08-02 13:56:32 -04005250void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005251{
Nicolas Capens805d7612018-08-02 13:56:32 -04005252 GLfloat xyzw[4] = {x, y, z, w};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005253
Nicolas Capens805d7612018-08-02 13:56:32 -04005254 Uniform4fv(location, 1, (GLfloat*)&xyzw);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005255}
5256
5257void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5258{
5259 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5260
5261 if(count < 0)
5262 {
5263 return error(GL_INVALID_VALUE);
5264 }
5265
Chris Forbes108f3e12018-08-30 19:41:59 -07005266 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005267
5268 if(context)
5269 {
5270 es2::Program *program = context->getCurrentProgram();
5271
5272 if(!program)
5273 {
5274 return error(GL_INVALID_OPERATION);
5275 }
5276
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005277 if(location == -1)
5278 {
5279 return;
5280 }
5281
Nicolas Capens0bac2852016-05-07 06:09:58 -04005282 if(!program->setUniform4iv(location, count, v))
5283 {
5284 return error(GL_INVALID_OPERATION);
5285 }
5286 }
5287}
5288
Nicolas Capens805d7612018-08-02 13:56:32 -04005289void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5290{
5291 GLint xyzw[4] = {x, y, z, w};
5292
5293 Uniform4iv(location, 1, (GLint*)&xyzw);
5294}
5295
Nicolas Capens0bac2852016-05-07 06:09:58 -04005296void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5297{
5298 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5299 location, count, transpose, value);
5300
5301 if(count < 0)
5302 {
5303 return error(GL_INVALID_VALUE);
5304 }
5305
Chris Forbes108f3e12018-08-30 19:41:59 -07005306 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005307
5308 if(context)
5309 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005310 es2::Program *program = context->getCurrentProgram();
5311
5312 if(!program)
5313 {
5314 return error(GL_INVALID_OPERATION);
5315 }
5316
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005317 if(location == -1)
5318 {
5319 return;
5320 }
5321
Nicolas Capens0bac2852016-05-07 06:09:58 -04005322 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5323 {
5324 return error(GL_INVALID_OPERATION);
5325 }
5326 }
5327}
5328
5329void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5330{
5331 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5332 location, count, transpose, value);
5333
5334 if(count < 0)
5335 {
5336 return error(GL_INVALID_VALUE);
5337 }
5338
Chris Forbes108f3e12018-08-30 19:41:59 -07005339 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005340
5341 if(context)
5342 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005343 es2::Program *program = context->getCurrentProgram();
5344
5345 if(!program)
5346 {
5347 return error(GL_INVALID_OPERATION);
5348 }
5349
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005350 if(location == -1)
5351 {
5352 return;
5353 }
5354
Nicolas Capens0bac2852016-05-07 06:09:58 -04005355 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5356 {
5357 return error(GL_INVALID_OPERATION);
5358 }
5359 }
5360}
5361
5362void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5363{
5364 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5365 location, count, transpose, value);
5366
5367 if(count < 0)
5368 {
5369 return error(GL_INVALID_VALUE);
5370 }
5371
Chris Forbes108f3e12018-08-30 19:41:59 -07005372 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005373
5374 if(context)
5375 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005376 es2::Program *program = context->getCurrentProgram();
5377
5378 if(!program)
5379 {
5380 return error(GL_INVALID_OPERATION);
5381 }
5382
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005383 if(location == -1)
5384 {
5385 return;
5386 }
5387
Nicolas Capens0bac2852016-05-07 06:09:58 -04005388 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5389 {
5390 return error(GL_INVALID_OPERATION);
5391 }
5392 }
5393}
5394
5395void UseProgram(GLuint program)
5396{
5397 TRACE("(GLuint program = %d)", program);
5398
Chris Forbes108f3e12018-08-30 19:41:59 -07005399 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005400
5401 if(context)
5402 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005403 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5404 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5405 {
5406 return error(GL_INVALID_OPERATION);
5407 }
5408
Nicolas Capens0bac2852016-05-07 06:09:58 -04005409 es2::Program *programObject = context->getProgram(program);
5410
5411 if(!programObject && program != 0)
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
5423 if(program != 0 && !programObject->isLinked())
5424 {
5425 return error(GL_INVALID_OPERATION);
5426 }
5427
5428 context->useProgram(program);
5429 }
5430}
5431
5432void ValidateProgram(GLuint program)
5433{
5434 TRACE("(GLuint program = %d)", program);
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 es2::Program *programObject = context->getProgram(program);
5441
5442 if(!programObject)
5443 {
5444 if(context->getShader(program))
5445 {
5446 return error(GL_INVALID_OPERATION);
5447 }
5448 else
5449 {
5450 return error(GL_INVALID_VALUE);
5451 }
5452 }
5453
Ben Vanik1fd3b282017-07-10 14:08:12 -07005454 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005455 }
5456}
5457
5458void VertexAttrib1f(GLuint index, GLfloat x)
5459{
5460 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5461
5462 if(index >= es2::MAX_VERTEX_ATTRIBS)
5463 {
5464 return error(GL_INVALID_VALUE);
5465 }
5466
Chris Forbes108f3e12018-08-30 19:41:59 -07005467 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005468
5469 if(context)
5470 {
5471 GLfloat vals[4] = { x, 0, 0, 1 };
5472 context->setVertexAttrib(index, vals);
5473 }
5474}
5475
5476void VertexAttrib1fv(GLuint index, const GLfloat* values)
5477{
5478 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5479
5480 if(index >= es2::MAX_VERTEX_ATTRIBS)
5481 {
5482 return error(GL_INVALID_VALUE);
5483 }
5484
Chris Forbes108f3e12018-08-30 19:41:59 -07005485 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005486
5487 if(context)
5488 {
5489 GLfloat vals[4] = { values[0], 0, 0, 1 };
5490 context->setVertexAttrib(index, vals);
5491 }
5492}
5493
5494void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5495{
5496 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5497
5498 if(index >= es2::MAX_VERTEX_ATTRIBS)
5499 {
5500 return error(GL_INVALID_VALUE);
5501 }
5502
Chris Forbes108f3e12018-08-30 19:41:59 -07005503 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005504
5505 if(context)
5506 {
5507 GLfloat vals[4] = { x, y, 0, 1 };
5508 context->setVertexAttrib(index, vals);
5509 }
5510}
5511
5512void VertexAttrib2fv(GLuint index, const GLfloat* values)
5513{
5514 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5515
5516 if(index >= es2::MAX_VERTEX_ATTRIBS)
5517 {
5518 return error(GL_INVALID_VALUE);
5519 }
5520
Chris Forbes108f3e12018-08-30 19:41:59 -07005521 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005522
5523 if(context)
5524 {
5525 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5526 context->setVertexAttrib(index, vals);
5527 }
5528}
5529
5530void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5531{
5532 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5533
5534 if(index >= es2::MAX_VERTEX_ATTRIBS)
5535 {
5536 return error(GL_INVALID_VALUE);
5537 }
5538
Chris Forbes108f3e12018-08-30 19:41:59 -07005539 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005540
5541 if(context)
5542 {
5543 GLfloat vals[4] = { x, y, z, 1 };
5544 context->setVertexAttrib(index, vals);
5545 }
5546}
5547
5548void VertexAttrib3fv(GLuint index, const GLfloat* values)
5549{
5550 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5551
5552 if(index >= es2::MAX_VERTEX_ATTRIBS)
5553 {
5554 return error(GL_INVALID_VALUE);
5555 }
5556
Chris Forbes108f3e12018-08-30 19:41:59 -07005557 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005558
5559 if(context)
5560 {
5561 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5562 context->setVertexAttrib(index, vals);
5563 }
5564}
5565
5566void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5567{
5568 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5569
5570 if(index >= es2::MAX_VERTEX_ATTRIBS)
5571 {
5572 return error(GL_INVALID_VALUE);
5573 }
5574
Chris Forbes108f3e12018-08-30 19:41:59 -07005575 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005576
5577 if(context)
5578 {
5579 GLfloat vals[4] = { x, y, z, w };
5580 context->setVertexAttrib(index, vals);
5581 }
5582}
5583
5584void VertexAttrib4fv(GLuint index, const GLfloat* values)
5585{
5586 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5587
5588 if(index >= es2::MAX_VERTEX_ATTRIBS)
5589 {
5590 return error(GL_INVALID_VALUE);
5591 }
5592
Chris Forbes108f3e12018-08-30 19:41:59 -07005593 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005594
5595 if(context)
5596 {
5597 context->setVertexAttrib(index, values);
5598 }
5599}
5600
5601void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5602{
5603 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5604 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5605 index, size, type, normalized, stride, ptr);
5606
5607 if(index >= es2::MAX_VERTEX_ATTRIBS)
5608 {
5609 return error(GL_INVALID_VALUE);
5610 }
5611
5612 if(size < 1 || size > 4)
5613 {
5614 return error(GL_INVALID_VALUE);
5615 }
5616
Nicolas Capens0bac2852016-05-07 06:09:58 -04005617 switch(type)
5618 {
5619 case GL_BYTE:
5620 case GL_UNSIGNED_BYTE:
5621 case GL_SHORT:
5622 case GL_UNSIGNED_SHORT:
5623 case GL_FIXED:
5624 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005625 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005626 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005627 break;
5628 case GL_INT_2_10_10_10_REV:
5629 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005630 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005631 {
Nicolas Capens83463112018-06-12 23:55:16 -04005632 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005633 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005634 case GL_INT:
5635 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005636 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005637 default:
5638 return error(GL_INVALID_ENUM);
5639 }
5640
5641 if(stride < 0)
5642 {
5643 return error(GL_INVALID_VALUE);
5644 }
5645
Chris Forbes108f3e12018-08-30 19:41:59 -07005646 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005647
5648 if(context)
5649 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005650 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5651 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5652 {
5653 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5654 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5655 return error(GL_INVALID_OPERATION);
5656 }
5657
Nicolas Capens51814272018-10-15 13:01:22 -04005658 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized != GL_FALSE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005659 }
5660}
5661
5662void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5663{
5664 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5665
5666 if(width < 0 || height < 0)
5667 {
5668 return error(GL_INVALID_VALUE);
5669 }
5670
Chris Forbes108f3e12018-08-30 19:41:59 -07005671 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005672
5673 if(context)
5674 {
5675 context->setViewportParams(x, y, width, height);
5676 }
5677}
5678
Nicolas Capens805d7612018-08-02 13:56:32 -04005679static void BlitFramebufferSW(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 -04005680{
5681 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5682 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5683 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5684 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5685
5686 switch(filter)
5687 {
5688 case GL_NEAREST:
5689 break;
5690 default:
5691 return error(GL_INVALID_ENUM);
5692 }
5693
5694 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5695 {
5696 return error(GL_INVALID_VALUE);
5697 }
5698
Chris Forbes108f3e12018-08-30 19:41:59 -07005699 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005700
5701 if(context)
5702 {
5703 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5704 {
5705 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5706 return error(GL_INVALID_OPERATION);
5707 }
5708
Alexis Hetub9dda642016-10-06 11:25:32 -04005709 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005710 }
5711}
5712
Alexis Hetub9dda642016-10-06 11:25:32 -04005713void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5714{
Nicolas Capens805d7612018-08-02 13:56:32 -04005715 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
Alexis Hetub9dda642016-10-06 11:25:32 -04005716}
5717
Nicolas Capens0bac2852016-05-07 06:09:58 -04005718void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5719 GLbitfield mask, GLenum filter)
5720{
5721 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5722 {
5723 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5724 return error(GL_INVALID_OPERATION);
5725 }
5726
Nicolas Capens805d7612018-08-02 13:56:32 -04005727 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005728}
5729
5730void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005731 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005732{
5733 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5734 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005735 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5736 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005737
5738 switch(target)
5739 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005740 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005741 switch(format)
5742 {
5743 case GL_DEPTH_COMPONENT:
5744 case GL_DEPTH_STENCIL_OES:
5745 return error(GL_INVALID_OPERATION);
5746 default:
5747 break;
5748 }
5749 break;
5750 default:
5751 return error(GL_INVALID_ENUM);
5752 }
5753
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005754 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005755 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005756 return error(GL_INVALID_OPERATION);
5757 }
5758
Nicolas Capens83463112018-06-12 23:55:16 -04005759 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005760 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005761 {
5762 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005763 }
5764
5765 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5766 {
5767 return error(GL_INVALID_VALUE);
5768 }
5769
Nicolas Capensefdf1032018-05-08 16:03:16 -04005770 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005771 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5772 {
5773 return error(GL_INVALID_VALUE);
5774 }
5775
5776 if(border != 0)
5777 {
5778 return error(GL_INVALID_VALUE);
5779 }
5780
Chris Forbes108f3e12018-08-30 19:41:59 -07005781 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005782
5783 if(context)
5784 {
5785 es2::Texture3D *texture = context->getTexture3D();
5786
5787 if(!texture)
5788 {
5789 return error(GL_INVALID_OPERATION);
5790 }
5791
Nicolas Capens2fc90512018-01-23 22:24:22 +00005792 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005793 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005794 {
5795 return error(validationError);
5796 }
5797
Nicolas Capens894858a2018-03-22 00:55:23 -04005798 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005799 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005800 }
5801}
5802
Alexis Hetu53f48092016-06-17 14:08:06 -04005803void 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 -04005804{
5805 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5806 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005807 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5808 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005809
5810 switch(target)
5811 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005812 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005813 break;
5814 default:
5815 return error(GL_INVALID_ENUM);
5816 }
5817
Nicolas Capens0bac2852016-05-07 06:09:58 -04005818 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5819 {
5820 return error(GL_INVALID_VALUE);
5821 }
5822
5823 if((width < 0) || (height < 0) || (depth < 0))
5824 {
5825 return error(GL_INVALID_VALUE);
5826 }
5827
Chris Forbes108f3e12018-08-30 19:41:59 -07005828 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005829
5830 if(context)
5831 {
5832 es2::Texture3D *texture = context->getTexture3D();
5833
Nicolas Capens83463112018-06-12 23:55:16 -04005834 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005835 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005836 {
5837 return error(validationError);
5838 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005839
Nicolas Capens5555af42017-12-14 13:14:03 -05005840 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005841 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005842 {
5843 return error(validationError);
5844 }
5845
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005846 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005847 }
5848}
5849
5850void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5851{
5852 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5853 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5854 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5855
5856 switch(target)
5857 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005858 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005859 break;
5860 default:
5861 return error(GL_INVALID_ENUM);
5862 }
5863
5864 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5865 {
5866 return error(GL_INVALID_VALUE);
5867 }
5868
Chris Forbes108f3e12018-08-30 19:41:59 -07005869 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005870
5871 if(context)
5872 {
5873 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5874
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005875 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005876 {
5877 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5878 }
5879
5880 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5881
5882 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5883 {
5884 return error(GL_INVALID_OPERATION);
5885 }
5886
5887 es2::Texture3D *texture = context->getTexture3D();
5888
Nicolas Capens83463112018-06-12 23:55:16 -04005889 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 -05005890 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005891 {
5892 return error(validationError);
5893 }
5894
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005895 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005896 }
5897}
5898
5899void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5900{
5901 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5902 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5903 target, level, internalformat, width, height, depth, border, imageSize, data);
5904
5905 switch(target)
5906 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005907 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005908 break;
5909 default:
5910 return error(GL_INVALID_ENUM);
5911 }
5912
5913 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5914 {
5915 return error(GL_INVALID_VALUE);
5916 }
5917
Nicolas Capensefdf1032018-05-08 16:03:16 -04005918 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005919 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5920 {
5921 return error(GL_INVALID_VALUE);
5922 }
5923
Nicolas Capens83463112018-06-12 23:55:16 -04005924 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005925 {
Nicolas Capens03589982018-02-01 17:28:32 -05005926 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005927 }
5928
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005929 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005930 {
5931 return error(GL_INVALID_VALUE);
5932 }
5933
Chris Forbes108f3e12018-08-30 19:41:59 -07005934 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005935
5936 if(context)
5937 {
5938 es2::Texture3D *texture = context->getTexture3D();
5939
5940 if(!texture)
5941 {
5942 return error(GL_INVALID_OPERATION);
5943 }
5944
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005945 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005946
Nicolas Capense65f5642018-02-26 17:47:06 -05005947 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005948 {
5949 return error(validationError);
5950 }
5951
Nicolas Capens0bac2852016-05-07 06:09:58 -04005952 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5953 }
5954}
5955
5956void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5957{
5958 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5959 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5960 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5961 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5962
5963 switch(target)
5964 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005965 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005966 break;
5967 default:
5968 return error(GL_INVALID_ENUM);
5969 }
5970
5971 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5972 {
5973 return error(GL_INVALID_VALUE);
5974 }
5975
5976 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5977 {
5978 return error(GL_INVALID_VALUE);
5979 }
5980
Nicolas Capens83463112018-06-12 23:55:16 -04005981 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005982 {
Nicolas Capens03589982018-02-01 17:28:32 -05005983 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005984 }
5985
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005986 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005987 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005988 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005989 }
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 es2::Texture3D *texture = context->getTexture3D();
5996
5997 if(!texture)
5998 {
5999 return error(GL_INVALID_OPERATION);
6000 }
6001
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05006002 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05006003 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05006004 {
6005 return error(validationError);
6006 }
6007
6008 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006009 }
6010}
6011
6012void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
6013{
6014 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
6015 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
6016
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006017 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006018 {
6019 return error(GL_INVALID_ENUM);
6020 }
6021
Chris Forbes108f3e12018-08-30 19:41:59 -07006022 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006023
6024 if(context)
6025 {
6026 if(texture == 0)
6027 {
6028 textarget = GL_NONE;
6029 }
6030 else
6031 {
6032 es2::Texture *tex = context->getTexture(texture);
6033
6034 if(!tex)
6035 {
6036 return error(GL_INVALID_OPERATION);
6037 }
6038
Nicolas Capens0bac2852016-05-07 06:09:58 -04006039 switch(textarget)
6040 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006041 case GL_TEXTURE_3D:
6042 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006043 {
6044 return error(GL_INVALID_OPERATION);
6045 }
6046 break;
6047 default:
6048 return error(GL_INVALID_ENUM);
6049 }
6050
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006051 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006052 {
6053 return error(GL_INVALID_VALUE);
6054 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006055
6056 if(tex->isCompressed(textarget, level))
6057 {
6058 return error(GL_INVALID_OPERATION);
6059 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006060 }
6061
6062 es2::Framebuffer *framebuffer = nullptr;
6063 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006064 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006065 {
6066 framebuffer = context->getReadFramebuffer();
6067 framebufferName = context->getReadFramebufferName();
6068 }
6069 else
6070 {
6071 framebuffer = context->getDrawFramebuffer();
6072 framebufferName = context->getDrawFramebufferName();
6073 }
6074
6075 if(framebufferName == 0 || !framebuffer)
6076 {
6077 return error(GL_INVALID_OPERATION);
6078 }
6079
Nicolas Capens0bac2852016-05-07 06:09:58 -04006080 switch(attachment)
6081 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006082 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6083 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006084 default:
Nicolas Capens4e344192018-10-24 21:01:17 -04006085 if(attachment < GL_COLOR_ATTACHMENT0 || attachment > GL_COLOR_ATTACHMENT31)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006086 {
6087 return error(GL_INVALID_ENUM);
6088 }
Nicolas Capens4e344192018-10-24 21:01:17 -04006089
6090 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6091 {
6092 return error(GL_INVALID_OPERATION);
6093 }
6094
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006095 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006096 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006097 }
6098 }
6099}
6100
6101void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6102{
6103 if(egl::getClientVersion() == 1)
6104 {
6105 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6106 }
6107
6108 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6109
6110 switch(target)
6111 {
6112 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006113 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006114 case GL_TEXTURE_EXTERNAL_OES:
6115 break;
6116 default:
6117 return error(GL_INVALID_ENUM);
6118 }
6119
Chris Forbes108f3e12018-08-30 19:41:59 -07006120 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006121
6122 if(context)
6123 {
Alexis Hetu46768622018-01-16 22:09:28 -05006124 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006125
6126 if(!texture)
6127 {
6128 return error(GL_INVALID_OPERATION);
6129 }
6130
Nicolas Capens58df2f62016-06-07 14:48:56 -04006131 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006132
Nicolas Capens58df2f62016-06-07 14:48:56 -04006133 if(!eglImage)
6134 {
6135 return error(GL_INVALID_OPERATION);
6136 }
6137
6138 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006139 }
6140}
6141
6142void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6143{
6144 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6145
6146 UNIMPLEMENTED();
6147}
6148
6149GLboolean IsRenderbufferOES(GLuint renderbuffer)
6150{
6151 return IsRenderbuffer(renderbuffer);
6152}
6153
6154void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6155{
6156 BindRenderbuffer(target, renderbuffer);
6157}
6158
6159void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6160{
6161 DeleteRenderbuffers(n, renderbuffers);
6162}
6163
6164void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6165{
6166 GenRenderbuffers(n, renderbuffers);
6167}
6168
6169void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6170{
6171 RenderbufferStorage(target, internalformat, width, height);
6172}
6173
6174void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6175{
6176 GetRenderbufferParameteriv(target, pname, params);
6177}
6178
6179GLboolean IsFramebufferOES(GLuint framebuffer)
6180{
6181 return IsFramebuffer(framebuffer);
6182}
6183
6184void BindFramebufferOES(GLenum target, GLuint framebuffer)
6185{
6186 BindFramebuffer(target, framebuffer);
6187}
6188
6189void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6190{
6191 DeleteFramebuffers(n, framebuffers);
6192}
6193
6194void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6195{
6196 GenFramebuffers(n, framebuffers);
6197}
6198
6199GLenum CheckFramebufferStatusOES(GLenum target)
6200{
6201 return CheckFramebufferStatus(target);
6202}
6203
6204void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6205{
6206 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6207}
6208
6209void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6210{
6211 FramebufferTexture2D(target, attachment, textarget, texture, level);
6212}
6213
6214void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6215{
6216 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6217}
6218
6219void GenerateMipmapOES(GLenum target)
6220{
6221 GenerateMipmap(target);
6222}
6223
6224void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6225{
6226 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6227
6228 if(n < 0 || n > MAX_DRAW_BUFFERS)
6229 {
6230 return error(GL_INVALID_VALUE);
6231 }
6232
Chris Forbes108f3e12018-08-30 19:41:59 -07006233 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006234
6235 if(context)
6236 {
6237 GLuint drawFramebufferName = context->getDrawFramebufferName();
6238
6239 if((drawFramebufferName == 0) && (n != 1))
6240 {
6241 return error(GL_INVALID_OPERATION);
6242 }
6243
6244 for(unsigned int i = 0; i < (unsigned)n; i++)
6245 {
6246 switch(bufs[i])
6247 {
6248 case GL_BACK:
6249 if(drawFramebufferName != 0)
6250 {
6251 return error(GL_INVALID_OPERATION);
6252 }
6253 break;
6254 case GL_NONE:
6255 break;
6256 case GL_COLOR_ATTACHMENT0_EXT:
6257 case GL_COLOR_ATTACHMENT1_EXT:
6258 case GL_COLOR_ATTACHMENT2_EXT:
6259 case GL_COLOR_ATTACHMENT3_EXT:
6260 case GL_COLOR_ATTACHMENT4_EXT:
6261 case GL_COLOR_ATTACHMENT5_EXT:
6262 case GL_COLOR_ATTACHMENT6_EXT:
6263 case GL_COLOR_ATTACHMENT7_EXT:
6264 case GL_COLOR_ATTACHMENT8_EXT:
6265 case GL_COLOR_ATTACHMENT9_EXT:
6266 case GL_COLOR_ATTACHMENT10_EXT:
6267 case GL_COLOR_ATTACHMENT11_EXT:
6268 case GL_COLOR_ATTACHMENT12_EXT:
6269 case GL_COLOR_ATTACHMENT13_EXT:
6270 case GL_COLOR_ATTACHMENT14_EXT:
6271 case GL_COLOR_ATTACHMENT15_EXT:
6272 {
6273 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6274
6275 if(index >= MAX_COLOR_ATTACHMENTS)
6276 {
6277 return error(GL_INVALID_OPERATION);
6278 }
6279
6280 if(index != i)
6281 {
6282 return error(GL_INVALID_OPERATION);
6283 }
6284
6285 if(drawFramebufferName == 0)
6286 {
6287 return error(GL_INVALID_OPERATION);
6288 }
6289 }
6290 break;
6291 default:
6292 return error(GL_INVALID_ENUM);
6293 }
6294 }
6295
6296 context->setFramebufferDrawBuffers(n, bufs);
6297 }
6298}
6299
6300}
6301
Nicolas Capens805d7612018-08-02 13:56:32 -04006302#include "entry_points.h"
6303
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006304extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006305{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006306 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006307 {
6308 const char *name;
6309 __eglMustCastToProperFunctionPointerType address;
6310 };
6311
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006312 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006313 {
Nicolas Capens805d7612018-08-02 13:56:32 -04006314 #define FUNCTION(name) {"gl" #name, (__eglMustCastToProperFunctionPointerType)gl::name}
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006315
Nicolas Capens805d7612018-08-02 13:56:32 -04006316 FUNCTION(ActiveTexture),
6317 FUNCTION(AttachShader),
6318 FUNCTION(BeginQuery),
6319 FUNCTION(BeginQueryEXT),
6320 FUNCTION(BeginTransformFeedback),
6321 FUNCTION(BindAttribLocation),
6322 FUNCTION(BindBuffer),
6323 FUNCTION(BindBufferBase),
6324 FUNCTION(BindBufferRange),
6325 FUNCTION(BindFramebuffer),
6326 FUNCTION(BindFramebufferOES),
6327 FUNCTION(BindRenderbuffer),
6328 FUNCTION(BindRenderbufferOES),
6329 FUNCTION(BindSampler),
6330 FUNCTION(BindTexture),
6331 FUNCTION(BindTransformFeedback),
6332 FUNCTION(BindVertexArray),
6333 FUNCTION(BindVertexArrayOES),
6334 FUNCTION(BlendColor),
6335 FUNCTION(BlendEquation),
6336 FUNCTION(BlendEquationSeparate),
6337 FUNCTION(BlendFunc),
6338 FUNCTION(BlendFuncSeparate),
6339 FUNCTION(BlitFramebuffer),
6340 FUNCTION(BlitFramebufferANGLE),
6341 FUNCTION(BufferData),
6342 FUNCTION(BufferSubData),
6343 FUNCTION(CheckFramebufferStatus),
6344 FUNCTION(CheckFramebufferStatusOES),
6345 FUNCTION(Clear),
6346 FUNCTION(ClearBufferfi),
6347 FUNCTION(ClearBufferfv),
6348 FUNCTION(ClearBufferiv),
6349 FUNCTION(ClearBufferuiv),
6350 FUNCTION(ClearColor),
6351 FUNCTION(ClearDepthf),
6352 FUNCTION(ClearStencil),
6353 FUNCTION(ClientWaitSync),
6354 FUNCTION(ColorMask),
6355 FUNCTION(CompileShader),
6356 FUNCTION(CompressedTexImage2D),
6357 FUNCTION(CompressedTexImage3D),
6358 FUNCTION(CompressedTexSubImage2D),
6359 FUNCTION(CompressedTexSubImage3D),
6360 FUNCTION(CopyBufferSubData),
6361 FUNCTION(CopyTexImage2D),
6362 FUNCTION(CopyTexSubImage2D),
6363 FUNCTION(CopyTexSubImage3D),
6364 FUNCTION(CreateProgram),
6365 FUNCTION(CreateShader),
6366 FUNCTION(CullFace),
6367 FUNCTION(DeleteBuffers),
6368 FUNCTION(DeleteFencesNV),
6369 FUNCTION(DeleteFramebuffers),
6370 FUNCTION(DeleteFramebuffersOES),
6371 FUNCTION(DeleteProgram),
6372 FUNCTION(DeleteQueries),
6373 FUNCTION(DeleteQueriesEXT),
6374 FUNCTION(DeleteRenderbuffers),
6375 FUNCTION(DeleteRenderbuffersOES),
6376 FUNCTION(DeleteSamplers),
6377 FUNCTION(DeleteShader),
6378 FUNCTION(DeleteSync),
6379 FUNCTION(DeleteTextures),
6380 FUNCTION(DeleteTransformFeedbacks),
6381 FUNCTION(DeleteVertexArrays),
6382 FUNCTION(DeleteVertexArraysOES),
6383 FUNCTION(DepthFunc),
6384 FUNCTION(DepthMask),
6385 FUNCTION(DepthRangef),
6386 FUNCTION(DetachShader),
6387 FUNCTION(Disable),
6388 FUNCTION(DisableVertexAttribArray),
6389 FUNCTION(DrawArrays),
6390 FUNCTION(DrawArraysInstanced),
6391 FUNCTION(DrawBuffers),
6392 FUNCTION(DrawBuffersEXT),
6393 FUNCTION(DrawElements),
6394 FUNCTION(DrawElementsInstanced),
6395 FUNCTION(DrawRangeElements),
6396 FUNCTION(EGLImageTargetRenderbufferStorageOES),
6397 FUNCTION(EGLImageTargetTexture2DOES),
6398 FUNCTION(Enable),
6399 FUNCTION(EnableVertexAttribArray),
6400 FUNCTION(EndQuery),
6401 FUNCTION(EndQueryEXT),
6402 FUNCTION(EndTransformFeedback),
6403 FUNCTION(FenceSync),
6404 FUNCTION(Finish),
6405 FUNCTION(FinishFenceNV),
6406 FUNCTION(Flush),
6407 FUNCTION(FlushMappedBufferRange),
6408 FUNCTION(FramebufferRenderbuffer),
6409 FUNCTION(FramebufferRenderbufferOES),
6410 FUNCTION(FramebufferTexture2D),
6411 FUNCTION(FramebufferTexture2DOES),
6412 FUNCTION(FramebufferTextureLayer),
6413 FUNCTION(FrontFace),
6414 FUNCTION(GenBuffers),
6415 FUNCTION(GenFencesNV),
6416 FUNCTION(GenFramebuffers),
6417 FUNCTION(GenFramebuffersOES),
6418 FUNCTION(GenQueries),
6419 FUNCTION(GenQueriesEXT),
6420 FUNCTION(GenRenderbuffers),
6421 FUNCTION(GenRenderbuffersOES),
6422 FUNCTION(GenSamplers),
6423 FUNCTION(GenTextures),
6424 FUNCTION(GenTransformFeedbacks),
6425 FUNCTION(GenVertexArrays),
6426 FUNCTION(GenVertexArraysOES),
6427 FUNCTION(GenerateMipmap),
6428 FUNCTION(GenerateMipmapOES),
6429 FUNCTION(GetActiveAttrib),
6430 FUNCTION(GetActiveUniform),
6431 FUNCTION(GetActiveUniformBlockName),
6432 FUNCTION(GetActiveUniformBlockiv),
6433 FUNCTION(GetActiveUniformsiv),
6434 FUNCTION(GetAttachedShaders),
6435 FUNCTION(GetAttribLocation),
6436 FUNCTION(GetBooleanv),
6437 FUNCTION(GetBufferParameteri64v),
6438 FUNCTION(GetBufferParameteriv),
6439 FUNCTION(GetBufferPointerv),
6440 FUNCTION(GetError),
6441 FUNCTION(GetFenceivNV),
6442 FUNCTION(GetFloatv),
6443 FUNCTION(GetFragDataLocation),
6444 FUNCTION(GetFramebufferAttachmentParameteriv),
6445 FUNCTION(GetFramebufferAttachmentParameterivOES),
6446 FUNCTION(GetGraphicsResetStatusEXT),
6447 FUNCTION(GetInteger64i_v),
6448 FUNCTION(GetInteger64v),
6449 FUNCTION(GetIntegeri_v),
6450 FUNCTION(GetIntegerv),
6451 FUNCTION(GetInternalformativ),
6452 FUNCTION(GetProgramBinary),
6453 FUNCTION(GetProgramInfoLog),
6454 FUNCTION(GetProgramiv),
6455 FUNCTION(GetQueryObjectuiv),
6456 FUNCTION(GetQueryObjectuivEXT),
6457 FUNCTION(GetQueryiv),
6458 FUNCTION(GetQueryivEXT),
6459 FUNCTION(GetRenderbufferParameteriv),
6460 FUNCTION(GetRenderbufferParameterivOES),
6461 FUNCTION(GetSamplerParameterfv),
6462 FUNCTION(GetSamplerParameteriv),
6463 FUNCTION(GetShaderInfoLog),
6464 FUNCTION(GetShaderPrecisionFormat),
6465 FUNCTION(GetShaderSource),
6466 FUNCTION(GetShaderiv),
6467 FUNCTION(GetString),
6468 FUNCTION(GetStringi),
6469 FUNCTION(GetSynciv),
6470 FUNCTION(GetTexParameterfv),
6471 FUNCTION(GetTexParameteriv),
6472 FUNCTION(GetTransformFeedbackVarying),
6473 FUNCTION(GetUniformBlockIndex),
6474 FUNCTION(GetUniformIndices),
6475 FUNCTION(GetUniformLocation),
6476 FUNCTION(GetUniformfv),
6477 FUNCTION(GetUniformiv),
6478 FUNCTION(GetUniformuiv),
6479 FUNCTION(GetVertexAttribIiv),
6480 FUNCTION(GetVertexAttribIuiv),
6481 FUNCTION(GetVertexAttribPointerv),
6482 FUNCTION(GetVertexAttribfv),
6483 FUNCTION(GetVertexAttribiv),
6484 FUNCTION(GetnUniformfvEXT),
6485 FUNCTION(GetnUniformivEXT),
6486 FUNCTION(Hint),
6487 FUNCTION(InvalidateFramebuffer),
6488 FUNCTION(InvalidateSubFramebuffer),
6489 FUNCTION(IsBuffer),
6490 FUNCTION(IsEnabled),
6491 FUNCTION(IsFenceNV),
6492 FUNCTION(IsFramebuffer),
6493 FUNCTION(IsFramebufferOES),
6494 FUNCTION(IsProgram),
6495 FUNCTION(IsQuery),
6496 FUNCTION(IsQueryEXT),
6497 FUNCTION(IsRenderbuffer),
6498 FUNCTION(IsRenderbufferOES),
6499 FUNCTION(IsSampler),
6500 FUNCTION(IsShader),
6501 FUNCTION(IsSync),
6502 FUNCTION(IsTexture),
6503 FUNCTION(IsTransformFeedback),
6504 FUNCTION(IsVertexArray),
6505 FUNCTION(IsVertexArrayOES),
6506 FUNCTION(LineWidth),
6507 FUNCTION(LinkProgram),
6508 FUNCTION(MapBufferRange),
6509 FUNCTION(PauseTransformFeedback),
6510 FUNCTION(PixelStorei),
6511 FUNCTION(PolygonOffset),
6512 FUNCTION(ProgramBinary),
6513 FUNCTION(ProgramParameteri),
6514 FUNCTION(ReadBuffer),
6515 FUNCTION(ReadPixels),
6516 FUNCTION(ReadnPixelsEXT),
6517 FUNCTION(ReleaseShaderCompiler),
6518 FUNCTION(RenderbufferStorage),
6519 FUNCTION(RenderbufferStorageMultisample),
6520 FUNCTION(RenderbufferStorageMultisampleANGLE),
6521 FUNCTION(RenderbufferStorageOES),
6522 FUNCTION(ResumeTransformFeedback),
6523 FUNCTION(SampleCoverage),
6524 FUNCTION(SamplerParameterf),
6525 FUNCTION(SamplerParameterfv),
6526 FUNCTION(SamplerParameteri),
6527 FUNCTION(SamplerParameteriv),
6528 FUNCTION(Scissor),
6529 FUNCTION(SetFenceNV),
6530 FUNCTION(ShaderBinary),
6531 FUNCTION(ShaderSource),
6532 FUNCTION(StencilFunc),
6533 FUNCTION(StencilFuncSeparate),
6534 FUNCTION(StencilMask),
6535 FUNCTION(StencilMaskSeparate),
6536 FUNCTION(StencilOp),
6537 FUNCTION(StencilOpSeparate),
6538 FUNCTION(TestFenceNV),
6539 FUNCTION(TexImage2D),
6540 FUNCTION(TexImage3D),
6541 FUNCTION(TexImage3DOES),
6542 FUNCTION(TexParameterf),
6543 FUNCTION(TexParameterfv),
6544 FUNCTION(TexParameteri),
6545 FUNCTION(TexParameteriv),
6546 FUNCTION(TexStorage2D),
6547 FUNCTION(TexStorage3D),
6548 FUNCTION(TexSubImage2D),
6549 FUNCTION(TexSubImage3D),
6550 FUNCTION(TransformFeedbackVaryings),
6551 FUNCTION(Uniform1f),
6552 FUNCTION(Uniform1fv),
6553 FUNCTION(Uniform1i),
6554 FUNCTION(Uniform1iv),
6555 FUNCTION(Uniform1ui),
6556 FUNCTION(Uniform1uiv),
6557 FUNCTION(Uniform2f),
6558 FUNCTION(Uniform2fv),
6559 FUNCTION(Uniform2i),
6560 FUNCTION(Uniform2iv),
6561 FUNCTION(Uniform2ui),
6562 FUNCTION(Uniform2uiv),
6563 FUNCTION(Uniform3f),
6564 FUNCTION(Uniform3fv),
6565 FUNCTION(Uniform3i),
6566 FUNCTION(Uniform3iv),
6567 FUNCTION(Uniform3ui),
6568 FUNCTION(Uniform3uiv),
6569 FUNCTION(Uniform4f),
6570 FUNCTION(Uniform4fv),
6571 FUNCTION(Uniform4i),
6572 FUNCTION(Uniform4iv),
6573 FUNCTION(Uniform4ui),
6574 FUNCTION(Uniform4uiv),
6575 FUNCTION(UniformBlockBinding),
6576 FUNCTION(UniformMatrix2fv),
6577 FUNCTION(UniformMatrix2x3fv),
6578 FUNCTION(UniformMatrix2x4fv),
6579 FUNCTION(UniformMatrix3fv),
6580 FUNCTION(UniformMatrix3x2fv),
6581 FUNCTION(UniformMatrix3x4fv),
6582 FUNCTION(UniformMatrix4fv),
6583 FUNCTION(UniformMatrix4x2fv),
6584 FUNCTION(UniformMatrix4x3fv),
6585 FUNCTION(UnmapBuffer),
6586 FUNCTION(UseProgram),
6587 FUNCTION(ValidateProgram),
6588 FUNCTION(VertexAttrib1f),
6589 FUNCTION(VertexAttrib1fv),
6590 FUNCTION(VertexAttrib2f),
6591 FUNCTION(VertexAttrib2fv),
6592 FUNCTION(VertexAttrib3f),
6593 FUNCTION(VertexAttrib3fv),
6594 FUNCTION(VertexAttrib4f),
6595 FUNCTION(VertexAttrib4fv),
6596 FUNCTION(VertexAttribDivisor),
6597 FUNCTION(VertexAttribDivisorANGLE),
6598 FUNCTION(VertexAttribDivisorEXT),
6599 FUNCTION(VertexAttribI4i),
6600 FUNCTION(VertexAttribI4iv),
6601 FUNCTION(VertexAttribI4ui),
6602 FUNCTION(VertexAttribI4uiv),
6603 FUNCTION(VertexAttribIPointer),
6604 FUNCTION(VertexAttribPointer),
6605 FUNCTION(Viewport),
6606 FUNCTION(WaitSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006607
6608 #undef FUNCTION
6609 };
6610
6611 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6612 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6613
Nicolas Capens48908cb2018-01-08 13:07:14 -05006614 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6615 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6616 #ifndef NDEBUG
6617 for(size_t i = 0; i < numFunctions - 1; i++)
6618 {
6619 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6620 }
6621 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006622
6623 if(procname && strncmp("gl", procname, 2) == 0)
6624 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006625 struct CompareFunctor
6626 {
6627 bool operator()(const Function &a, const Function &b) const
6628 {
6629 return strcmp(a.name, b.name) < 0;
6630 }
6631 };
6632
6633 Function needle;
6634 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006635 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006636
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006637 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006638 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006639 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006640 }
6641 }
6642
6643 return nullptr;
6644}