blob: ef00cc3ae8637856dc0b3e1732c5a61f5158cc3f [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 Capens83463112018-06-12 23:55:16 -04001930 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
1931 {
1932 return error(GL_INVALID_ENUM);
1933 }
1934 framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer, attachment - GL_COLOR_ATTACHMENT0);
1935 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001936 }
1937 }
1938}
1939
1940void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
1941{
1942 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
1943 "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
1944
Nicolas Capens6c4564a2018-01-26 01:14:34 +00001945 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001946 {
1947 return error(GL_INVALID_ENUM);
1948 }
1949
Chris Forbes108f3e12018-08-30 19:41:59 -07001950 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001951
1952 if(context)
1953 {
1954 if(texture == 0)
1955 {
1956 textarget = GL_NONE;
1957 }
1958 else
1959 {
1960 es2::Texture *tex = context->getTexture(texture);
1961
1962 if(!tex)
1963 {
1964 return error(GL_INVALID_OPERATION);
1965 }
1966
1967 switch(textarget)
1968 {
1969 case GL_TEXTURE_2D:
1970 if(tex->getTarget() != GL_TEXTURE_2D)
1971 {
1972 return error(GL_INVALID_OPERATION);
1973 }
1974 break;
Alexis Hetu46768622018-01-16 22:09:28 -05001975 case GL_TEXTURE_RECTANGLE_ARB:
1976 if(tex->getTarget() != GL_TEXTURE_RECTANGLE_ARB)
1977 {
1978 return error(GL_INVALID_OPERATION);
1979 }
1980 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001981 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1982 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1983 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1984 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1985 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1986 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1987 if(tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1988 {
1989 return error(GL_INVALID_OPERATION);
1990 }
1991 break;
1992 default:
1993 return error(GL_INVALID_ENUM);
1994 }
1995
Nicolas Capens83463112018-06-12 23:55:16 -04001996 if((textarget == GL_TEXTURE_RECTANGLE_ARB) && (level != 0))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001997 {
1998 return error(GL_INVALID_VALUE);
1999 }
2000
2001 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
2002 {
2003 return error(GL_INVALID_VALUE);
2004 }
Nicolas Capens1fb3a752016-06-08 14:18:06 -04002005
2006 if(tex->isCompressed(textarget, level))
2007 {
2008 return error(GL_INVALID_OPERATION);
2009 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002010 }
2011
2012 es2::Framebuffer *framebuffer = nullptr;
2013 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00002014 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002015 {
2016 framebuffer = context->getReadFramebuffer();
2017 framebufferName = context->getReadFramebufferName();
2018 }
2019 else
2020 {
2021 framebuffer = context->getDrawFramebuffer();
2022 framebufferName = context->getDrawFramebufferName();
2023 }
2024
2025 if(framebufferName == 0 || !framebuffer)
2026 {
2027 return error(GL_INVALID_OPERATION);
2028 }
2029
2030 switch(attachment)
2031 {
Nicolas Capens83463112018-06-12 23:55:16 -04002032 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
2033 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
2034 case GL_DEPTH_STENCIL_ATTACHMENT:
2035 framebuffer->setDepthbuffer(textarget, texture, level);
2036 framebuffer->setStencilbuffer(textarget, texture, level);
2037 break;
2038 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002039 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
2040 {
2041 return error(GL_INVALID_ENUM);
2042 }
2043 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
2044 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002045 }
2046 }
2047}
2048
2049void FrontFace(GLenum mode)
2050{
2051 TRACE("(GLenum mode = 0x%X)", mode);
2052
2053 switch(mode)
2054 {
2055 case GL_CW:
2056 case GL_CCW:
2057 {
Chris Forbes108f3e12018-08-30 19:41:59 -07002058 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002059
2060 if(context)
2061 {
2062 context->setFrontFace(mode);
2063 }
2064 }
2065 break;
2066 default:
2067 return error(GL_INVALID_ENUM);
2068 }
2069}
2070
2071void GenBuffers(GLsizei n, GLuint* buffers)
2072{
2073 TRACE("(GLsizei n = %d, GLuint* buffers = %p)", n, buffers);
2074
2075 if(n < 0)
2076 {
2077 return error(GL_INVALID_VALUE);
2078 }
2079
Chris Forbes108f3e12018-08-30 19:41:59 -07002080 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002081
2082 if(context)
2083 {
2084 for(int i = 0; i < n; i++)
2085 {
2086 buffers[i] = context->createBuffer();
2087 }
2088 }
2089}
2090
2091void GenerateMipmap(GLenum target)
2092{
2093 TRACE("(GLenum target = 0x%X)", target);
2094
Chris Forbes108f3e12018-08-30 19:41:59 -07002095 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002096
2097 if(context)
2098 {
2099 es2::Texture *texture = nullptr;
2100
Nicolas Capens0bac2852016-05-07 06:09:58 -04002101 switch(target)
2102 {
2103 case GL_TEXTURE_2D:
2104 texture = context->getTexture2D();
2105 break;
2106 case GL_TEXTURE_CUBE_MAP:
Nicolas Capens5fc1e752017-12-19 10:35:40 -05002107 {
2108 TextureCubeMap *cube = context->getTextureCubeMap();
2109 texture = cube;
2110
2111 if(!cube->isCubeComplete())
2112 {
2113 return error(GL_INVALID_OPERATION);
2114 }
2115 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002116 break;
2117 case GL_TEXTURE_2D_ARRAY:
Nicolas Capens83463112018-06-12 23:55:16 -04002118 texture = context->getTexture2DArray();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002119 break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05002120 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002121 texture = context->getTexture3D();
2122 break;
Alexis Hetu46768622018-01-16 22:09:28 -05002123 case GL_TEXTURE_RECTANGLE_ARB:
2124 texture = context->getTexture2DRect();
2125 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002126 default:
2127 return error(GL_INVALID_ENUM);
2128 }
2129
Nicolas Capens83463112018-06-12 23:55:16 -04002130 if(!IsMipmappable(texture->getFormat(target, texture->getBaseLevel())))
Alexis Hetuf89cd0b2017-11-20 17:00:39 -05002131 {
2132 return error(GL_INVALID_OPERATION);
2133 }
2134
Nicolas Capens0bac2852016-05-07 06:09:58 -04002135 texture->generateMipmaps();
2136 }
2137}
2138
2139void GenFencesNV(GLsizei n, GLuint* fences)
2140{
2141 TRACE("(GLsizei n = %d, GLuint* fences = %p)", n, fences);
2142
2143 if(n < 0)
2144 {
2145 return error(GL_INVALID_VALUE);
2146 }
2147
Chris Forbes108f3e12018-08-30 19:41:59 -07002148 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002149
2150 if(context)
2151 {
2152 for(int i = 0; i < n; i++)
2153 {
2154 fences[i] = context->createFence();
2155 }
2156 }
2157}
2158
2159void GenFramebuffers(GLsizei n, GLuint* framebuffers)
2160{
2161 TRACE("(GLsizei n = %d, GLuint* framebuffers = %p)", n, framebuffers);
2162
2163 if(n < 0)
2164 {
2165 return error(GL_INVALID_VALUE);
2166 }
2167
Chris Forbes108f3e12018-08-30 19:41:59 -07002168 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002169
2170 if(context)
2171 {
2172 for(int i = 0; i < n; i++)
2173 {
2174 framebuffers[i] = context->createFramebuffer();
2175 }
2176 }
2177}
2178
2179void GenQueriesEXT(GLsizei n, GLuint* ids)
2180{
2181 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
2182
2183 if(n < 0)
2184 {
2185 return error(GL_INVALID_VALUE);
2186 }
2187
Chris Forbes108f3e12018-08-30 19:41:59 -07002188 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002189
2190 if(context)
2191 {
2192 for(int i = 0; i < n; i++)
2193 {
2194 ids[i] = context->createQuery();
2195 }
2196 }
2197}
2198
2199void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
2200{
2201 TRACE("(GLsizei n = %d, GLuint* renderbuffers = %p)", n, renderbuffers);
2202
2203 if(n < 0)
2204 {
2205 return error(GL_INVALID_VALUE);
2206 }
2207
Chris Forbes108f3e12018-08-30 19:41:59 -07002208 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002209
2210 if(context)
2211 {
2212 for(int i = 0; i < n; i++)
2213 {
2214 renderbuffers[i] = context->createRenderbuffer();
2215 }
2216 }
2217}
2218
2219void GenTextures(GLsizei n, GLuint* textures)
2220{
2221 TRACE("(GLsizei n = %d, GLuint* textures = %p)", n, textures);
2222
2223 if(n < 0)
2224 {
2225 return error(GL_INVALID_VALUE);
2226 }
2227
Chris Forbes108f3e12018-08-30 19:41:59 -07002228 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002229
2230 if(context)
2231 {
2232 for(int i = 0; i < n; i++)
2233 {
2234 textures[i] = context->createTexture();
2235 }
2236 }
2237}
2238
2239void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2240{
2241 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = %p, "
2242 "GLint *size = %p, GLenum *type = %p, GLchar *name = %p)",
2243 program, index, bufsize, length, size, type, name);
2244
2245 if(bufsize < 0)
2246 {
2247 return error(GL_INVALID_VALUE);
2248 }
2249
Chris Forbes108f3e12018-08-30 19:41:59 -07002250 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002251
2252 if(context)
2253 {
2254 es2::Program *programObject = context->getProgram(program);
2255
2256 if(!programObject)
2257 {
2258 if(context->getShader(program))
2259 {
2260 return error(GL_INVALID_OPERATION);
2261 }
2262 else
2263 {
2264 return error(GL_INVALID_VALUE);
2265 }
2266 }
2267
2268 if(index >= programObject->getActiveAttributeCount())
2269 {
2270 return error(GL_INVALID_VALUE);
2271 }
2272
2273 programObject->getActiveAttribute(index, bufsize, length, size, type, name);
2274 }
2275}
2276
2277void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
2278{
2279 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
2280 "GLsizei* length = %p, GLint* size = %p, GLenum* type = %p, GLchar* name = %s)",
2281 program, index, bufsize, length, size, type, name);
2282
2283 if(bufsize < 0)
2284 {
2285 return error(GL_INVALID_VALUE);
2286 }
2287
Chris Forbes108f3e12018-08-30 19:41:59 -07002288 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002289
2290 if(context)
2291 {
2292 es2::Program *programObject = context->getProgram(program);
2293
2294 if(!programObject)
2295 {
2296 if(context->getShader(program))
2297 {
2298 return error(GL_INVALID_OPERATION);
2299 }
2300 else
2301 {
2302 return error(GL_INVALID_VALUE);
2303 }
2304 }
2305
2306 if(index >= programObject->getActiveUniformCount())
2307 {
2308 return error(GL_INVALID_VALUE);
2309 }
2310
2311 programObject->getActiveUniform(index, bufsize, length, size, type, name);
2312 }
2313}
2314
2315void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
2316{
2317 TRACE("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = %p, GLuint* shaders = %p)",
2318 program, maxcount, count, shaders);
2319
2320 if(maxcount < 0)
2321 {
2322 return error(GL_INVALID_VALUE);
2323 }
2324
Chris Forbes108f3e12018-08-30 19:41:59 -07002325 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002326
2327 if(context)
2328 {
2329 es2::Program *programObject = context->getProgram(program);
2330
2331 if(!programObject)
2332 {
2333 if(context->getShader(program))
2334 {
2335 return error(GL_INVALID_OPERATION);
2336 }
2337 else
2338 {
2339 return error(GL_INVALID_VALUE);
2340 }
2341 }
2342
2343 return programObject->getAttachedShaders(maxcount, count, shaders);
2344 }
2345}
2346
2347int GetAttribLocation(GLuint program, const GLchar* name)
2348{
2349 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
2350
Chris Forbes108f3e12018-08-30 19:41:59 -07002351 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002352
2353 if(context)
2354 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04002355 es2::Program *programObject = context->getProgram(program);
2356
2357 if(!programObject)
2358 {
2359 if(context->getShader(program))
2360 {
2361 return error(GL_INVALID_OPERATION, -1);
2362 }
2363 else
2364 {
2365 return error(GL_INVALID_VALUE, -1);
2366 }
2367 }
2368
2369 if(!programObject->isLinked())
2370 {
2371 return error(GL_INVALID_OPERATION, -1);
2372 }
2373
2374 return programObject->getAttributeLocation(name);
2375 }
2376
2377 return -1;
2378}
2379
2380void GetBooleanv(GLenum pname, GLboolean* params)
2381{
2382 TRACE("(GLenum pname = 0x%X, GLboolean* params = %p)", pname, params);
2383
Chris Forbes108f3e12018-08-30 19:41:59 -07002384 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002385
2386 if(context)
2387 {
2388 if(!(context->getBooleanv(pname, params)))
2389 {
2390 GLenum nativeType;
2391 unsigned int numParams = 0;
2392 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2393 return error(GL_INVALID_ENUM);
2394
2395 if(numParams == 0)
2396 return; // it is known that the pname is valid, but there are no parameters to return
2397
2398 if(nativeType == GL_FLOAT)
2399 {
2400 GLfloat *floatParams = nullptr;
2401 floatParams = new GLfloat[numParams];
2402
2403 context->getFloatv(pname, floatParams);
2404
2405 for(unsigned int i = 0; i < numParams; ++i)
2406 {
2407 if(floatParams[i] == 0.0f)
2408 params[i] = GL_FALSE;
2409 else
2410 params[i] = GL_TRUE;
2411 }
2412
2413 delete [] floatParams;
2414 }
2415 else if(nativeType == GL_INT)
2416 {
2417 GLint *intParams = nullptr;
2418 intParams = new GLint[numParams];
2419
2420 context->getIntegerv(pname, intParams);
2421
2422 for(unsigned int i = 0; i < numParams; ++i)
2423 {
2424 if(intParams[i] == 0)
2425 params[i] = GL_FALSE;
2426 else
2427 params[i] = GL_TRUE;
2428 }
2429
2430 delete [] intParams;
2431 }
2432 }
2433 }
2434}
2435
2436void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
2437{
2438 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
2439
Chris Forbes108f3e12018-08-30 19:41:59 -07002440 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002441
2442 if(context)
2443 {
2444 es2::Buffer *buffer;
2445 if(!context->getBuffer(target, &buffer))
2446 {
2447 return error(GL_INVALID_ENUM);
2448 }
2449
2450 if(!buffer)
2451 {
2452 // A null buffer means that "0" is bound to the requested buffer target
2453 return error(GL_INVALID_OPERATION);
2454 }
2455
Nicolas Capens0bac2852016-05-07 06:09:58 -04002456 switch(pname)
2457 {
2458 case GL_BUFFER_USAGE:
2459 *params = buffer->usage();
2460 break;
2461 case GL_BUFFER_SIZE:
2462 *params = (GLint)buffer->size();
2463 break;
2464 case GL_BUFFER_ACCESS_FLAGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002465 *params = buffer->access();
2466 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002467 case GL_BUFFER_MAPPED:
Nicolas Capens83463112018-06-12 23:55:16 -04002468 *params = buffer->isMapped();
2469 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002470 case GL_BUFFER_MAP_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002471 *params = (GLint)buffer->length();
2472 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002473 case GL_BUFFER_MAP_OFFSET:
Nicolas Capens83463112018-06-12 23:55:16 -04002474 *params = (GLint)buffer->offset();
2475 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002476 default:
2477 return error(GL_INVALID_ENUM);
2478 }
2479 }
2480}
2481
2482GLenum GetError(void)
2483{
2484 TRACE("()");
2485
Chris Forbes108f3e12018-08-30 19:41:59 -07002486 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002487
2488 if(context)
2489 {
2490 return context->getError();
2491 }
2492
2493 return GL_NO_ERROR;
2494}
2495
2496void GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
2497{
2498 TRACE("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = %p)", fence, pname, params);
2499
Chris Forbes108f3e12018-08-30 19:41:59 -07002500 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002501
2502 if(context)
2503 {
2504 es2::Fence *fenceObject = context->getFence(fence);
2505
2506 if(!fenceObject)
2507 {
2508 return error(GL_INVALID_OPERATION);
2509 }
2510
2511 fenceObject->getFenceiv(pname, params);
2512 }
2513}
2514
2515void GetFloatv(GLenum pname, GLfloat* params)
2516{
2517 TRACE("(GLenum pname = 0x%X, GLfloat* params = %p)", pname, params);
2518
Chris Forbes108f3e12018-08-30 19:41:59 -07002519 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002520
2521 if(context)
2522 {
2523 if(!(context->getFloatv(pname, params)))
2524 {
2525 GLenum nativeType;
2526 unsigned int numParams = 0;
2527 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2528 return error(GL_INVALID_ENUM);
2529
2530 if(numParams == 0)
2531 return; // it is known that the pname is valid, but that there are no parameters to return.
2532
2533 if(nativeType == GL_BOOL)
2534 {
2535 GLboolean *boolParams = nullptr;
2536 boolParams = new GLboolean[numParams];
2537
2538 context->getBooleanv(pname, boolParams);
2539
2540 for(unsigned int i = 0; i < numParams; ++i)
2541 {
2542 if(boolParams[i] == GL_FALSE)
2543 params[i] = 0.0f;
2544 else
2545 params[i] = 1.0f;
2546 }
2547
2548 delete [] boolParams;
2549 }
2550 else if(nativeType == GL_INT)
2551 {
2552 GLint *intParams = nullptr;
2553 intParams = new GLint[numParams];
2554
2555 context->getIntegerv(pname, intParams);
2556
2557 for(unsigned int i = 0; i < numParams; ++i)
2558 {
2559 params[i] = (GLfloat)intParams[i];
2560 }
2561
2562 delete [] intParams;
2563 }
2564 }
2565 }
2566}
2567
2568void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
2569{
2570 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = %p)",
2571 target, attachment, pname, params);
2572
Chris Forbes108f3e12018-08-30 19:41:59 -07002573 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002574
2575 if(context)
2576 {
2577 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
2578 {
2579 return error(GL_INVALID_ENUM);
2580 }
2581
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002582 GLuint framebufferName = 0;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002583
Nicolas Capens0bac2852016-05-07 06:09:58 -04002584 if(target == GL_READ_FRAMEBUFFER)
2585 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002586 framebufferName = context->getReadFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002587 }
2588 else
2589 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002590 framebufferName = context->getDrawFramebufferName();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002591 }
2592
Nicolas Capens0bac2852016-05-07 06:09:58 -04002593 switch(attachment)
2594 {
2595 case GL_BACK:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002596 case GL_DEPTH:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002597 case GL_STENCIL:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002598 if(framebufferName != 0)
2599 {
2600 return error(GL_INVALID_OPERATION);
2601 }
2602 break;
2603 case GL_DEPTH_ATTACHMENT:
2604 case GL_STENCIL_ATTACHMENT:
2605 if(framebufferName == 0)
2606 {
2607 return error(GL_INVALID_OPERATION);
2608 }
2609 break;
2610 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002611 if(framebufferName == 0)
2612 {
2613 return error(GL_INVALID_OPERATION);
2614 }
2615 break;
2616 default:
2617 if((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS)
2618 {
2619 if(framebufferName == 0)
2620 {
2621 return error(GL_INVALID_OPERATION);
2622 }
2623 }
2624 else return error(GL_INVALID_ENUM);
2625 }
2626
2627 es2::Framebuffer *framebuffer = context->getFramebuffer(framebufferName);
2628
Alexis Hetu5cd502b2018-03-22 08:29:31 -04002629 if(!framebuffer)
2630 {
2631 return error(GL_INVALID_OPERATION);
2632 }
2633
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002634 GLenum attachmentType;
2635 GLuint attachmentHandle;
2636 GLint attachmentLayer;
2637 Renderbuffer *renderbuffer = nullptr;
2638 switch(attachment)
2639 {
2640 case GL_BACK:
2641 attachmentType = framebuffer->getColorbufferType(0);
2642 attachmentHandle = framebuffer->getColorbufferName(0);
2643 attachmentLayer = framebuffer->getColorbufferLayer(0);
2644 renderbuffer = framebuffer->getColorbuffer(0);
2645 break;
2646 case GL_DEPTH:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002647 case GL_DEPTH_ATTACHMENT:
2648 attachmentType = framebuffer->getDepthbufferType();
2649 attachmentHandle = framebuffer->getDepthbufferName();
2650 attachmentLayer = framebuffer->getDepthbufferLayer();
2651 renderbuffer = framebuffer->getDepthbuffer();
2652 break;
2653 case GL_STENCIL:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002654 case GL_STENCIL_ATTACHMENT:
2655 attachmentType = framebuffer->getStencilbufferType();
2656 attachmentHandle = framebuffer->getStencilbufferName();
2657 attachmentLayer = framebuffer->getStencilbufferLayer();
2658 renderbuffer = framebuffer->getStencilbuffer();
2659 break;
2660 case GL_DEPTH_STENCIL_ATTACHMENT:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002661 attachmentType = framebuffer->getDepthbufferType();
2662 attachmentHandle = framebuffer->getDepthbufferName();
2663 attachmentLayer = framebuffer->getDepthbufferLayer();
2664 renderbuffer = framebuffer->getDepthbuffer();
2665
2666 if(attachmentHandle != framebuffer->getStencilbufferName())
Nicolas Capens0bac2852016-05-07 06:09:58 -04002667 {
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002668 // Different attachments to DEPTH and STENCIL, query fails
2669 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002670 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04002671 break;
2672 default:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002673 ASSERT((unsigned int)(attachment - GL_COLOR_ATTACHMENT0) < MAX_COLOR_ATTACHMENTS);
2674 attachmentType = framebuffer->getColorbufferType(attachment - GL_COLOR_ATTACHMENT0);
2675 attachmentHandle = framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0);
2676 attachmentLayer = framebuffer->getColorbufferLayer(attachment - GL_COLOR_ATTACHMENT0);
2677 renderbuffer = framebuffer->getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
2678 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002679 }
2680
2681 GLenum attachmentObjectType = GL_NONE; // Type category
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002682 if(framebufferName == 0)
2683 {
2684 attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
2685 }
2686 else if(attachmentType == GL_NONE || Framebuffer::IsRenderbuffer(attachmentType))
Nicolas Capens0bac2852016-05-07 06:09:58 -04002687 {
2688 attachmentObjectType = attachmentType;
2689 }
2690 else if(es2::IsTextureTarget(attachmentType))
2691 {
2692 attachmentObjectType = GL_TEXTURE;
2693 }
2694 else UNREACHABLE(attachmentType);
2695
2696 if(attachmentObjectType != GL_NONE)
2697 {
2698 switch(pname)
2699 {
2700 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2701 *params = attachmentObjectType;
2702 break;
2703 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capensd95dbb82017-12-05 16:17:39 -05002704 if(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002705 {
2706 *params = attachmentHandle;
2707 }
2708 else
2709 {
2710 return error(GL_INVALID_ENUM);
2711 }
2712 break;
2713 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2714 if(attachmentObjectType == GL_TEXTURE)
2715 {
Nicolas Capens83463112018-06-12 23:55:16 -04002716 *params = renderbuffer->getLevel();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002717 }
2718 else
2719 {
2720 return error(GL_INVALID_ENUM);
2721 }
2722 break;
2723 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2724 if(attachmentObjectType == GL_TEXTURE)
2725 {
2726 if(es2::IsCubemapTextureTarget(attachmentType))
2727 {
2728 *params = attachmentType;
2729 }
2730 else
2731 {
2732 *params = 0;
2733 }
2734 }
2735 else
2736 {
2737 return error(GL_INVALID_ENUM);
2738 }
2739 break;
2740 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
Nicolas Capens83463112018-06-12 23:55:16 -04002741 *params = attachmentLayer;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002742 break;
2743 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002744 *params = renderbuffer->getRedSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002745 break;
2746 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002747 *params = renderbuffer->getGreenSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002748 break;
2749 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002750 *params = renderbuffer->getBlueSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002751 break;
2752 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002753 *params = renderbuffer->getAlphaSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002754 break;
2755 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002756 *params = renderbuffer->getDepthSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002757 break;
2758 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
Nicolas Capens83463112018-06-12 23:55:16 -04002759 *params = renderbuffer->getStencilSize();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002760 break;
2761 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
Nicolas Capens505b7712016-06-14 01:08:12 -04002762 // case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: // GL_EXT_color_buffer_half_float
2763 if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04002764 {
Nicolas Capens505b7712016-06-14 01:08:12 -04002765 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002766 }
Nicolas Capens505b7712016-06-14 01:08:12 -04002767
Nicolas Capensc61f46b2017-12-04 16:07:22 -05002768 *params = GetComponentType(renderbuffer->getFormat(), attachment);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002769 break;
2770 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
Nicolas Capens83463112018-06-12 23:55:16 -04002771 *params = GetColorEncoding(renderbuffer->getFormat());
Nicolas Capens0bac2852016-05-07 06:09:58 -04002772 break;
2773 default:
2774 return error(GL_INVALID_ENUM);
2775 }
2776 }
2777 else
2778 {
2779 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
2780 // is NONE, then querying any other pname will generate INVALID_ENUM.
2781
2782 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
2783 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
2784 // INVALID_OPERATION for all other pnames
2785
2786 switch(pname)
2787 {
2788 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2789 *params = GL_NONE;
2790 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002791 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002792 *params = 0;
2793 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002794 default:
Nicolas Capens83463112018-06-12 23:55:16 -04002795 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002796 }
2797 }
2798 }
2799}
2800
2801GLenum GetGraphicsResetStatusEXT(void)
2802{
2803 TRACE("()");
2804
2805 return GL_NO_ERROR;
2806}
2807
2808void GetIntegerv(GLenum pname, GLint* params)
2809{
2810 TRACE("(GLenum pname = 0x%X, GLint* params = %p)", pname, params);
2811
Chris Forbes108f3e12018-08-30 19:41:59 -07002812 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002813
2814 if(!context)
2815 {
2816 // Not strictly an error, but probably unintended or attempting to rely on non-compliant behavior
Alistair Strachanc28d28a2018-03-24 12:24:00 -07002817 ERR("glGetIntegerv() called without current context.");
Nicolas Capens0bac2852016-05-07 06:09:58 -04002818
2819 // This is not spec compliant! When there is no current GL context, functions should
2820 // have no side effects. Google Maps queries these values before creating a context,
2821 // so we need this as a bug-compatible workaround.
2822 switch(pname)
2823 {
2824 case GL_MAX_TEXTURE_SIZE: *params = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE; return;
2825 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = es2::MAX_VERTEX_TEXTURE_IMAGE_UNITS; return;
2826 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS; return;
2827 case GL_STENCIL_BITS: *params = 8; return;
2828 case GL_ALIASED_LINE_WIDTH_RANGE:
2829 params[0] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MIN;
2830 params[1] = (GLint)es2::ALIASED_LINE_WIDTH_RANGE_MAX;
2831 return;
2832 }
2833 }
2834
2835 if(context)
2836 {
2837 if(!(context->getIntegerv(pname, params)))
2838 {
2839 GLenum nativeType;
2840 unsigned int numParams = 0;
2841 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
2842 return error(GL_INVALID_ENUM);
2843
2844 if(numParams == 0)
2845 return; // it is known that pname is valid, but there are no parameters to return
2846
2847 if(nativeType == GL_BOOL)
2848 {
2849 GLboolean *boolParams = nullptr;
2850 boolParams = new GLboolean[numParams];
2851
2852 context->getBooleanv(pname, boolParams);
2853
2854 for(unsigned int i = 0; i < numParams; ++i)
2855 {
2856 params[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
2857 }
2858
2859 delete [] boolParams;
2860 }
2861 else if(nativeType == GL_FLOAT)
2862 {
2863 GLfloat *floatParams = nullptr;
2864 floatParams = new GLfloat[numParams];
2865
2866 context->getFloatv(pname, floatParams);
2867
2868 for(unsigned int i = 0; i < numParams; ++i)
2869 {
2870 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
2871 {
Alexis Hetu60e20282017-12-13 07:42:22 -05002872 params[i] = convert_float_fixed(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002873 }
2874 else
2875 {
2876 params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
2877 }
2878 }
2879
2880 delete [] floatParams;
2881 }
2882 }
2883 }
2884}
2885
2886void GetProgramiv(GLuint program, GLenum pname, GLint* params)
2887{
2888 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint* params = %p)", program, pname, params);
2889
Chris Forbes108f3e12018-08-30 19:41:59 -07002890 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002891
2892 if(context)
2893 {
2894 es2::Program *programObject = context->getProgram(program);
2895
2896 if(!programObject)
2897 {
2898 if(context->getShader(program))
2899 {
2900 return error(GL_INVALID_OPERATION);
2901 }
2902 else
2903 {
2904 return error(GL_INVALID_VALUE);
2905 }
2906 }
2907
Nicolas Capens0bac2852016-05-07 06:09:58 -04002908 switch(pname)
2909 {
2910 case GL_DELETE_STATUS:
2911 *params = programObject->isFlaggedForDeletion();
2912 return;
2913 case GL_LINK_STATUS:
2914 *params = programObject->isLinked();
2915 return;
2916 case GL_VALIDATE_STATUS:
2917 *params = programObject->isValidated();
2918 return;
2919 case GL_INFO_LOG_LENGTH:
2920 *params = (GLint)programObject->getInfoLogLength();
2921 return;
2922 case GL_ATTACHED_SHADERS:
2923 *params = programObject->getAttachedShadersCount();
2924 return;
2925 case GL_ACTIVE_ATTRIBUTES:
2926 *params = (GLint)programObject->getActiveAttributeCount();
2927 return;
2928 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
2929 *params = programObject->getActiveAttributeMaxLength();
2930 return;
2931 case GL_ACTIVE_UNIFORMS:
2932 *params = (GLint)programObject->getActiveUniformCount();
2933 return;
2934 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
2935 *params = programObject->getActiveUniformMaxLength();
2936 return;
2937 case GL_ACTIVE_UNIFORM_BLOCKS:
Nicolas Capens83463112018-06-12 23:55:16 -04002938 *params = (GLint)programObject->getActiveUniformBlockCount();
2939 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002940 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002941 *params = programObject->getActiveUniformBlockMaxLength();
2942 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002943 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04002944 *params = programObject->getTransformFeedbackBufferMode();
2945 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002946 case GL_TRANSFORM_FEEDBACK_VARYINGS:
Nicolas Capens83463112018-06-12 23:55:16 -04002947 *params = programObject->getTransformFeedbackVaryingCount();
2948 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002949 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002950 *params = programObject->getTransformFeedbackVaryingMaxLength();
2951 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002952 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Nicolas Capens83463112018-06-12 23:55:16 -04002953 *params = programObject->getBinaryRetrievableHint();
2954 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002955 case GL_PROGRAM_BINARY_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04002956 *params = programObject->getBinaryLength();
2957 return;
Nicolas Capens0bac2852016-05-07 06:09:58 -04002958 default:
2959 return error(GL_INVALID_ENUM);
2960 }
2961 }
2962}
2963
2964void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
2965{
2966 TRACE("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
2967 program, bufsize, length, infolog);
2968
2969 if(bufsize < 0)
2970 {
2971 return error(GL_INVALID_VALUE);
2972 }
2973
Chris Forbes108f3e12018-08-30 19:41:59 -07002974 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04002975
2976 if(context)
2977 {
2978 es2::Program *programObject = context->getProgram(program);
2979
2980 if(!programObject)
2981 {
2982 if(context->getShader(program))
2983 {
2984 return error(GL_INVALID_OPERATION);
2985 }
2986 else
2987 {
2988 return error(GL_INVALID_VALUE);
2989 }
2990 }
2991
2992 programObject->getInfoLog(bufsize, length, infolog);
2993 }
2994}
2995
2996void GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
2997{
2998 TRACE("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)", target, pname, params);
2999
3000 switch(pname)
3001 {
3002 case GL_CURRENT_QUERY_EXT:
3003 break;
3004 default:
3005 return error(GL_INVALID_ENUM);
3006 }
3007
Chris Forbes108f3e12018-08-30 19:41:59 -07003008 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003009
3010 if(context)
3011 {
3012 params[0] = context->getActiveQuery(target);
3013 }
3014}
3015
3016void GetQueryObjectuivEXT(GLuint name, GLenum pname, GLuint *params)
3017{
3018 TRACE("(GLuint name = %d, GLenum pname = 0x%X, GLuint *params = %p)", name, pname, params);
3019
3020 switch(pname)
3021 {
3022 case GL_QUERY_RESULT_EXT:
3023 case GL_QUERY_RESULT_AVAILABLE_EXT:
3024 break;
3025 default:
3026 return error(GL_INVALID_ENUM);
3027 }
3028
Chris Forbes108f3e12018-08-30 19:41:59 -07003029 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003030
3031 if(context)
3032 {
3033 es2::Query *queryObject = context->getQuery(name);
3034
3035 if(!queryObject)
3036 {
3037 return error(GL_INVALID_OPERATION);
3038 }
3039
3040 if(context->getActiveQuery(queryObject->getType()) == name)
3041 {
3042 return error(GL_INVALID_OPERATION);
3043 }
3044
3045 switch(pname)
3046 {
3047 case GL_QUERY_RESULT_EXT:
3048 params[0] = queryObject->getResult();
3049 break;
3050 case GL_QUERY_RESULT_AVAILABLE_EXT:
3051 params[0] = queryObject->isResultAvailable();
3052 break;
3053 default:
3054 ASSERT(false);
3055 }
3056 }
3057}
3058
3059void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
3060{
3061 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3062
Chris Forbes108f3e12018-08-30 19:41:59 -07003063 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003064
3065 if(context)
3066 {
3067 if(target != GL_RENDERBUFFER)
3068 {
3069 return error(GL_INVALID_ENUM);
3070 }
3071
3072 if(context->getRenderbufferName() == 0)
3073 {
3074 return error(GL_INVALID_OPERATION);
3075 }
3076
3077 es2::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferName());
3078
3079 switch(pname)
3080 {
3081 case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
3082 case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
Nicolas Capensf11cd722017-12-05 17:28:04 -05003083 case GL_RENDERBUFFER_INTERNAL_FORMAT:
3084 {
3085 GLint internalformat = renderbuffer->getFormat();
3086 *params = (internalformat == GL_NONE) ? GL_RGBA4 : internalformat;
3087 }
3088 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003089 case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
3090 case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
3091 case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
3092 case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
3093 case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
3094 case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003095 case GL_RENDERBUFFER_SAMPLES: *params = renderbuffer->getSamples(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003096 default:
3097 return error(GL_INVALID_ENUM);
3098 }
3099 }
3100}
3101
3102void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
3103{
3104 TRACE("(GLuint shader = %d, GLenum pname = %d, GLint* params = %p)", shader, pname, params);
3105
Chris Forbes108f3e12018-08-30 19:41:59 -07003106 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003107
3108 if(context)
3109 {
3110 es2::Shader *shaderObject = context->getShader(shader);
3111
3112 if(!shaderObject)
3113 {
3114 if(context->getProgram(shader))
3115 {
3116 return error(GL_INVALID_OPERATION);
3117 }
3118 else
3119 {
3120 return error(GL_INVALID_VALUE);
3121 }
3122 }
3123
3124 switch(pname)
3125 {
3126 case GL_SHADER_TYPE:
3127 *params = shaderObject->getType();
3128 return;
3129 case GL_DELETE_STATUS:
3130 *params = shaderObject->isFlaggedForDeletion();
3131 return;
3132 case GL_COMPILE_STATUS:
3133 *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
3134 return;
3135 case GL_INFO_LOG_LENGTH:
3136 *params = (GLint)shaderObject->getInfoLogLength();
3137 return;
3138 case GL_SHADER_SOURCE_LENGTH:
3139 *params = (GLint)shaderObject->getSourceLength();
3140 return;
3141 default:
3142 return error(GL_INVALID_ENUM);
3143 }
3144 }
3145}
3146
3147void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
3148{
3149 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* infolog = %p)",
3150 shader, bufsize, length, infolog);
3151
3152 if(bufsize < 0)
3153 {
3154 return error(GL_INVALID_VALUE);
3155 }
3156
Chris Forbes108f3e12018-08-30 19:41:59 -07003157 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003158
3159 if(context)
3160 {
3161 es2::Shader *shaderObject = context->getShader(shader);
3162
3163 if(!shaderObject)
3164 {
3165 if(context->getProgram(shader))
3166 {
3167 return error(GL_INVALID_OPERATION);
3168 }
3169 else
3170 {
3171 return error(GL_INVALID_VALUE);
3172 }
3173 }
3174
3175 shaderObject->getInfoLog(bufsize, length, infolog);
3176 }
3177}
3178
3179void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
3180{
3181 TRACE("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = %p, GLint* precision = %p)",
3182 shadertype, precisiontype, range, precision);
3183
3184 switch(shadertype)
3185 {
3186 case GL_VERTEX_SHADER:
3187 case GL_FRAGMENT_SHADER:
3188 break;
3189 default:
3190 return error(GL_INVALID_ENUM);
3191 }
3192
3193 switch(precisiontype)
3194 {
3195 case GL_LOW_FLOAT:
3196 case GL_MEDIUM_FLOAT:
3197 case GL_HIGH_FLOAT:
3198 // IEEE 754 single-precision
3199 range[0] = 127;
3200 range[1] = 127;
3201 *precision = 23;
3202 break;
3203 case GL_LOW_INT:
3204 case GL_MEDIUM_INT:
3205 case GL_HIGH_INT:
3206 // Full integer precision is supported
3207 range[0] = 31;
3208 range[1] = 30;
3209 *precision = 0;
3210 break;
3211 default:
3212 return error(GL_INVALID_ENUM);
3213 }
3214}
3215
3216void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
3217{
3218 TRACE("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = %p, GLchar* source = %p)",
3219 shader, bufsize, length, source);
3220
3221 if(bufsize < 0)
3222 {
3223 return error(GL_INVALID_VALUE);
3224 }
3225
Chris Forbes108f3e12018-08-30 19:41:59 -07003226 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003227
3228 if(context)
3229 {
3230 es2::Shader *shaderObject = context->getShader(shader);
3231
3232 if(!shaderObject)
3233 {
3234 if(context->getProgram(shader))
3235 {
3236 return error(GL_INVALID_OPERATION);
3237 }
3238 else
3239 {
3240 return error(GL_INVALID_VALUE);
3241 }
3242 }
3243
3244 shaderObject->getSource(bufsize, length, source);
3245 }
3246}
3247
3248const GLubyte* GetString(GLenum name)
3249{
3250 TRACE("(GLenum name = 0x%X)", name);
3251
3252 switch(name)
3253 {
3254 case GL_VENDOR:
3255 return (GLubyte*)"Google Inc.";
3256 case GL_RENDERER:
3257 return (GLubyte*)"Google SwiftShader";
3258 case GL_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003259 return (GLubyte*)"OpenGL ES 3.0 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003260 case GL_SHADING_LANGUAGE_VERSION:
Nicolas Capens83463112018-06-12 23:55:16 -04003261 return (GLubyte*)"OpenGL ES GLSL ES 3.00 SwiftShader " VERSION_STRING;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003262 case GL_EXTENSIONS:
Nicolas Capens894858a2018-03-22 00:55:23 -04003263 {
Chris Forbes108f3e12018-08-30 19:41:59 -07003264 auto context = es2::getContext();
Nicolas Capens894858a2018-03-22 00:55:23 -04003265 return context ? context->getExtensions(GL_INVALID_INDEX) : (GLubyte*)nullptr;
3266 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003267 default:
3268 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
3269 }
3270}
3271
3272void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
3273{
3274 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = %p)", target, pname, params);
3275
Chris Forbes108f3e12018-08-30 19:41:59 -07003276 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003277
3278 if(context)
3279 {
3280 es2::Texture *texture;
3281
Nicolas Capens0bac2852016-05-07 06:09:58 -04003282 switch(target)
3283 {
Nicolas Capens83463112018-06-12 23:55:16 -04003284 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3285 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3286 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3287 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3288 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3289 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003290 default:
3291 return error(GL_INVALID_ENUM);
3292 }
3293
3294 switch(pname)
3295 {
3296 case GL_TEXTURE_MAG_FILTER:
3297 *params = (GLfloat)texture->getMagFilter();
3298 break;
3299 case GL_TEXTURE_MIN_FILTER:
3300 *params = (GLfloat)texture->getMinFilter();
3301 break;
3302 case GL_TEXTURE_WRAP_S:
3303 *params = (GLfloat)texture->getWrapS();
3304 break;
3305 case GL_TEXTURE_WRAP_T:
3306 *params = (GLfloat)texture->getWrapT();
3307 break;
3308 case GL_TEXTURE_WRAP_R_OES:
3309 *params = (GLfloat)texture->getWrapR();
3310 break;
3311 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3312 *params = texture->getMaxAnisotropy();
3313 break;
3314 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3315 *params = (GLfloat)1;
3316 break;
3317 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003318 *params = (GLfloat)texture->getBaseLevel();
3319 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003320 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003321 *params = (GLfloat)texture->getCompareFunc();
3322 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003323 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003324 *params = (GLfloat)texture->getCompareMode();
3325 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003326 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003327 *params = (GLfloat)texture->getImmutableFormat();
3328 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003329 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003330 *params = (GLfloat)texture->getImmutableLevels();
3331 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003332 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003333 *params = (GLfloat)texture->getMaxLevel();
3334 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003335 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003336 *params = texture->getMaxLOD();
3337 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003338 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003339 *params = texture->getMinLOD();
3340 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003341 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003342 *params = (GLfloat)texture->getSwizzleR();
3343 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003344 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003345 *params = (GLfloat)texture->getSwizzleG();
3346 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003347 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003348 *params = (GLfloat)texture->getSwizzleB();
3349 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003350 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003351 *params = (GLfloat)texture->getSwizzleA();
3352 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003353 default:
3354 return error(GL_INVALID_ENUM);
3355 }
3356 }
3357}
3358
3359void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
3360{
3361 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = %p)", target, pname, params);
3362
Chris Forbes108f3e12018-08-30 19:41:59 -07003363 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003364
3365 if(context)
3366 {
3367 es2::Texture *texture;
3368
Nicolas Capens0bac2852016-05-07 06:09:58 -04003369 switch(target)
3370 {
Nicolas Capens83463112018-06-12 23:55:16 -04003371 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
3372 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
3373 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
3374 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
3375 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
3376 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003377 default:
3378 return error(GL_INVALID_ENUM);
3379 }
3380
3381 switch(pname)
3382 {
3383 case GL_TEXTURE_MAG_FILTER:
3384 *params = texture->getMagFilter();
3385 break;
3386 case GL_TEXTURE_MIN_FILTER:
3387 *params = texture->getMinFilter();
3388 break;
3389 case GL_TEXTURE_WRAP_S:
3390 *params = texture->getWrapS();
3391 break;
3392 case GL_TEXTURE_WRAP_T:
3393 *params = texture->getWrapT();
3394 break;
3395 case GL_TEXTURE_WRAP_R_OES:
3396 *params = texture->getWrapR();
3397 break;
3398 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
3399 *params = (GLint)texture->getMaxAnisotropy();
3400 break;
3401 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
3402 *params = 1;
3403 break;
3404 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003405 *params = texture->getBaseLevel();
3406 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003407 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04003408 *params = (GLint)texture->getCompareFunc();
3409 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003410 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04003411 *params = (GLint)texture->getCompareMode();
3412 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003413 case GL_TEXTURE_IMMUTABLE_FORMAT:
Nicolas Capens83463112018-06-12 23:55:16 -04003414 *params = (GLint)texture->getImmutableFormat();
3415 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003416 case GL_TEXTURE_IMMUTABLE_LEVELS:
Nicolas Capens83463112018-06-12 23:55:16 -04003417 *params = (GLint)texture->getImmutableLevels();
3418 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003419 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04003420 *params = texture->getMaxLevel();
3421 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003422 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003423 *params = (GLint)roundf(texture->getMaxLOD());
3424 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003425 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04003426 *params = (GLint)roundf(texture->getMinLOD());
3427 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003428 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04003429 *params = (GLint)texture->getSwizzleR();
3430 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003431 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04003432 *params = (GLint)texture->getSwizzleG();
3433 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003434 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04003435 *params = (GLint)texture->getSwizzleB();
3436 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003437 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04003438 *params = (GLint)texture->getSwizzleA();
3439 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04003440 default:
3441 return error(GL_INVALID_ENUM);
3442 }
3443 }
3444}
3445
3446void GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
3447{
3448 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = %p)",
3449 program, location, bufSize, params);
3450
3451 if(bufSize < 0)
3452 {
3453 return error(GL_INVALID_VALUE);
3454 }
3455
Chris Forbes108f3e12018-08-30 19:41:59 -07003456 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003457
3458 if(context)
3459 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003460 es2::Program *programObject = context->getProgram(program);
3461
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003462 if(!programObject)
3463 {
3464 if(context->getShader(program))
3465 {
3466 return error(GL_INVALID_OPERATION);
3467 }
3468 else
3469 {
3470 return error(GL_INVALID_VALUE);
3471 }
3472 }
3473
3474 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003475 {
3476 return error(GL_INVALID_OPERATION);
3477 }
3478
3479 if(!programObject->getUniformfv(location, &bufSize, params))
3480 {
3481 return error(GL_INVALID_OPERATION);
3482 }
3483 }
3484}
3485
3486void GetUniformfv(GLuint program, GLint location, GLfloat* params)
3487{
3488 TRACE("(GLuint program = %d, GLint location = %d, GLfloat* params = %p)", program, location, params);
3489
Chris Forbes108f3e12018-08-30 19:41:59 -07003490 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003491
3492 if(context)
3493 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003494 es2::Program *programObject = context->getProgram(program);
3495
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003496 if(!programObject)
3497 {
3498 if(context->getShader(program))
3499 {
3500 return error(GL_INVALID_OPERATION);
3501 }
3502 else
3503 {
3504 return error(GL_INVALID_VALUE);
3505 }
3506 }
3507
3508 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003509 {
3510 return error(GL_INVALID_OPERATION);
3511 }
3512
3513 if(!programObject->getUniformfv(location, nullptr, params))
3514 {
3515 return error(GL_INVALID_OPERATION);
3516 }
3517 }
3518}
3519
3520void GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
3521{
3522 TRACE("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = %p)",
3523 program, location, bufSize, params);
3524
3525 if(bufSize < 0)
3526 {
3527 return error(GL_INVALID_VALUE);
3528 }
3529
Chris Forbes108f3e12018-08-30 19:41:59 -07003530 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003531
3532 if(context)
3533 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003534 es2::Program *programObject = context->getProgram(program);
3535
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003536 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003537 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003538 if(context->getShader(program))
3539 {
3540 return error(GL_INVALID_OPERATION);
3541 }
3542 else
3543 {
3544 return error(GL_INVALID_VALUE);
3545 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003546 }
3547
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003548 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003549 {
3550 return error(GL_INVALID_OPERATION);
3551 }
3552
3553 if(!programObject->getUniformiv(location, &bufSize, params))
3554 {
3555 return error(GL_INVALID_OPERATION);
3556 }
3557 }
3558}
3559
3560void GetUniformiv(GLuint program, GLint location, GLint* params)
3561{
3562 TRACE("(GLuint program = %d, GLint location = %d, GLint* params = %p)", program, location, params);
3563
Chris Forbes108f3e12018-08-30 19:41:59 -07003564 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003565
3566 if(context)
3567 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003568 es2::Program *programObject = context->getProgram(program);
3569
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003570 if(!programObject)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003571 {
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003572 if(context->getShader(program))
3573 {
3574 return error(GL_INVALID_OPERATION);
3575 }
3576 else
3577 {
3578 return error(GL_INVALID_VALUE);
3579 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003580 }
3581
Nicolas Capens7eaa10a2016-06-09 10:01:58 -04003582 if(!programObject->isLinked())
Nicolas Capens0bac2852016-05-07 06:09:58 -04003583 {
3584 return error(GL_INVALID_OPERATION);
3585 }
3586
3587 if(!programObject->getUniformiv(location, nullptr, params))
3588 {
3589 return error(GL_INVALID_OPERATION);
3590 }
3591 }
3592}
3593
3594int GetUniformLocation(GLuint program, const GLchar* name)
3595{
3596 TRACE("(GLuint program = %d, const GLchar* name = %s)", program, name);
3597
Chris Forbes108f3e12018-08-30 19:41:59 -07003598 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003599
3600 if(strstr(name, "gl_") == name)
3601 {
3602 return -1;
3603 }
3604
3605 if(context)
3606 {
3607 es2::Program *programObject = context->getProgram(program);
3608
3609 if(!programObject)
3610 {
3611 if(context->getShader(program))
3612 {
3613 return error(GL_INVALID_OPERATION, -1);
3614 }
3615 else
3616 {
3617 return error(GL_INVALID_VALUE, -1);
3618 }
3619 }
3620
3621 if(!programObject->isLinked())
3622 {
3623 return error(GL_INVALID_OPERATION, -1);
3624 }
3625
3626 return programObject->getUniformLocation(name);
3627 }
3628
3629 return -1;
3630}
3631
3632void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
3633{
3634 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = %p)", index, pname, params);
3635
Chris Forbes108f3e12018-08-30 19:41:59 -07003636 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003637
3638 if(context)
3639 {
3640 if(index >= es2::MAX_VERTEX_ATTRIBS)
3641 {
3642 return error(GL_INVALID_VALUE);
3643 }
3644
3645 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3646
Nicolas Capens0bac2852016-05-07 06:09:58 -04003647 switch(pname)
3648 {
3649 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3650 *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3651 break;
3652 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3653 *params = (GLfloat)attribState.mSize;
3654 break;
3655 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3656 *params = (GLfloat)attribState.mStride;
3657 break;
3658 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3659 *params = (GLfloat)attribState.mType;
3660 break;
3661 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3662 *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE);
3663 break;
3664 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3665 *params = (GLfloat)attribState.mBoundBuffer.name();
3666 break;
3667 case GL_CURRENT_VERTEX_ATTRIB:
3668 {
3669 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3670 for(int i = 0; i < 4; ++i)
3671 {
3672 params[i] = attrib.getCurrentValueF(i);
3673 }
3674 }
3675 break;
3676 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003677 *params = (GLfloat)(attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3678 break;
3679 default:
3680 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003681 }
3682 }
3683}
3684
3685void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
3686{
3687 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = %p)", index, pname, params);
3688
Chris Forbes108f3e12018-08-30 19:41:59 -07003689 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003690
3691 if(context)
3692 {
3693 if(index >= es2::MAX_VERTEX_ATTRIBS)
3694 {
3695 return error(GL_INVALID_VALUE);
3696 }
3697
3698 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
3699
Nicolas Capens0bac2852016-05-07 06:09:58 -04003700 switch(pname)
3701 {
3702 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
3703 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
3704 break;
3705 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
3706 *params = attribState.mSize;
3707 break;
3708 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
3709 *params = attribState.mStride;
3710 break;
3711 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
3712 *params = attribState.mType;
3713 break;
3714 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
3715 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
3716 break;
3717 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
3718 *params = attribState.mBoundBuffer.name();
3719 break;
3720 case GL_CURRENT_VERTEX_ATTRIB:
3721 {
3722 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
3723 for(int i = 0; i < 4; ++i)
3724 {
3725 float currentValue = attrib.getCurrentValueF(i);
3726 params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f));
3727 }
3728 }
3729 break;
3730 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Nicolas Capens83463112018-06-12 23:55:16 -04003731 *params = (attribState.mPureInteger ? GL_TRUE : GL_FALSE);
3732 break;
3733 default:
3734 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003735 }
3736 }
3737}
3738
3739void GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
3740{
3741 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = %p)", index, pname, pointer);
3742
Chris Forbes108f3e12018-08-30 19:41:59 -07003743 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003744
3745 if(context)
3746 {
3747 if(index >= es2::MAX_VERTEX_ATTRIBS)
3748 {
3749 return error(GL_INVALID_VALUE);
3750 }
3751
3752 if(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
3753 {
3754 return error(GL_INVALID_ENUM);
3755 }
3756
3757 *pointer = const_cast<GLvoid*>(context->getVertexAttribPointer(index));
3758 }
3759}
3760
3761void Hint(GLenum target, GLenum mode)
3762{
3763 TRACE("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
3764
3765 switch(mode)
3766 {
3767 case GL_FASTEST:
3768 case GL_NICEST:
3769 case GL_DONT_CARE:
3770 break;
3771 default:
3772 return error(GL_INVALID_ENUM);
3773 }
3774
Chris Forbes108f3e12018-08-30 19:41:59 -07003775 auto context = es2::getContext();
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003776
3777 if(context)
Nicolas Capens0bac2852016-05-07 06:09:58 -04003778 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05003779 switch(target)
3780 {
3781 case GL_GENERATE_MIPMAP_HINT:
3782 context->setGenerateMipmapHint(mode);
3783 break;
3784 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
3785 context->setFragmentShaderDerivativeHint(mode);
3786 break;
3787 case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
3788 context->setTextureFilteringHint(mode);
3789 break;
3790 default:
3791 return error(GL_INVALID_ENUM);
3792 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003793 }
3794}
3795
3796GLboolean IsBuffer(GLuint buffer)
3797{
3798 TRACE("(GLuint buffer = %d)", buffer);
3799
Chris Forbes108f3e12018-08-30 19:41:59 -07003800 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003801
3802 if(context && buffer)
3803 {
3804 es2::Buffer *bufferObject = context->getBuffer(buffer);
3805
3806 if(bufferObject)
3807 {
3808 return GL_TRUE;
3809 }
3810 }
3811
3812 return GL_FALSE;
3813}
3814
3815GLboolean IsEnabled(GLenum cap)
3816{
3817 TRACE("(GLenum cap = 0x%X)", cap);
3818
Chris Forbes108f3e12018-08-30 19:41:59 -07003819 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003820
3821 if(context)
3822 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04003823 switch(cap)
3824 {
3825 case GL_CULL_FACE: return context->isCullFaceEnabled();
3826 case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled();
3827 case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled();
3828 case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled();
3829 case GL_SCISSOR_TEST: return context->isScissorTestEnabled();
3830 case GL_STENCIL_TEST: return context->isStencilTestEnabled();
3831 case GL_DEPTH_TEST: return context->isDepthTestEnabled();
3832 case GL_BLEND: return context->isBlendEnabled();
3833 case GL_DITHER: return context->isDitherEnabled();
Nicolas Capens83463112018-06-12 23:55:16 -04003834 case GL_PRIMITIVE_RESTART_FIXED_INDEX: return context->isPrimitiveRestartFixedIndexEnabled();
3835 case GL_RASTERIZER_DISCARD: return context->isRasterizerDiscardEnabled();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003836 default:
3837 return error(GL_INVALID_ENUM, false);
3838 }
3839 }
3840
3841 return false;
3842}
3843
3844GLboolean IsFenceNV(GLuint fence)
3845{
3846 TRACE("(GLuint fence = %d)", fence);
3847
Chris Forbes108f3e12018-08-30 19:41:59 -07003848 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003849
3850 if(context)
3851 {
3852 es2::Fence *fenceObject = context->getFence(fence);
3853
3854 if(!fenceObject)
3855 {
3856 return GL_FALSE;
3857 }
3858
3859 return fenceObject->isFence();
3860 }
3861
3862 return GL_FALSE;
3863}
3864
3865GLboolean IsFramebuffer(GLuint framebuffer)
3866{
3867 TRACE("(GLuint framebuffer = %d)", framebuffer);
3868
Chris Forbes108f3e12018-08-30 19:41:59 -07003869 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003870
3871 if(context && framebuffer)
3872 {
3873 es2::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
3874
3875 if(framebufferObject)
3876 {
3877 return GL_TRUE;
3878 }
3879 }
3880
3881 return GL_FALSE;
3882}
3883
3884GLboolean IsProgram(GLuint program)
3885{
3886 TRACE("(GLuint program = %d)", program);
3887
Chris Forbes108f3e12018-08-30 19:41:59 -07003888 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003889
3890 if(context && program)
3891 {
3892 es2::Program *programObject = context->getProgram(program);
3893
3894 if(programObject)
3895 {
3896 return GL_TRUE;
3897 }
3898 }
3899
3900 return GL_FALSE;
3901}
3902
3903GLboolean IsQueryEXT(GLuint name)
3904{
3905 TRACE("(GLuint name = %d)", name);
3906
3907 if(name == 0)
3908 {
3909 return GL_FALSE;
3910 }
3911
Chris Forbes108f3e12018-08-30 19:41:59 -07003912 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003913
3914 if(context)
3915 {
3916 es2::Query *queryObject = context->getQuery(name);
3917
3918 if(queryObject)
3919 {
3920 return GL_TRUE;
3921 }
3922 }
3923
3924 return GL_FALSE;
3925}
3926
3927GLboolean IsRenderbuffer(GLuint renderbuffer)
3928{
3929 TRACE("(GLuint renderbuffer = %d)", renderbuffer);
3930
Chris Forbes108f3e12018-08-30 19:41:59 -07003931 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003932
3933 if(context && renderbuffer)
3934 {
3935 es2::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
3936
3937 if(renderbufferObject)
3938 {
3939 return GL_TRUE;
3940 }
3941 }
3942
3943 return GL_FALSE;
3944}
3945
3946GLboolean IsShader(GLuint shader)
3947{
3948 TRACE("(GLuint shader = %d)", shader);
3949
Chris Forbes108f3e12018-08-30 19:41:59 -07003950 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003951
3952 if(context && shader)
3953 {
3954 es2::Shader *shaderObject = context->getShader(shader);
3955
3956 if(shaderObject)
3957 {
3958 return GL_TRUE;
3959 }
3960 }
3961
3962 return GL_FALSE;
3963}
3964
3965GLboolean IsTexture(GLuint texture)
3966{
3967 TRACE("(GLuint texture = %d)", texture);
3968
Chris Forbes108f3e12018-08-30 19:41:59 -07003969 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003970
3971 if(context && texture)
3972 {
3973 es2::Texture *textureObject = context->getTexture(texture);
3974
3975 if(textureObject)
3976 {
3977 return GL_TRUE;
3978 }
3979 }
3980
3981 return GL_FALSE;
3982}
3983
3984void LineWidth(GLfloat width)
3985{
3986 TRACE("(GLfloat width = %f)", width);
3987
3988 if(width <= 0.0f)
3989 {
3990 return error(GL_INVALID_VALUE);
3991 }
3992
Chris Forbes108f3e12018-08-30 19:41:59 -07003993 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04003994
3995 if(context)
3996 {
3997 context->setLineWidth(width);
3998 }
3999}
4000
4001void LinkProgram(GLuint program)
4002{
4003 TRACE("(GLuint program = %d)", program);
4004
Chris Forbes108f3e12018-08-30 19:41:59 -07004005 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004006
4007 if(context)
4008 {
4009 es2::Program *programObject = context->getProgram(program);
4010
4011 if(!programObject)
4012 {
4013 if(context->getShader(program))
4014 {
4015 return error(GL_INVALID_OPERATION);
4016 }
4017 else
4018 {
4019 return error(GL_INVALID_VALUE);
4020 }
4021 }
4022
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004023 if(programObject == context->getCurrentProgram())
4024 {
4025 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
4026 if(transformFeedback && transformFeedback->isActive())
4027 {
4028 return error(GL_INVALID_OPERATION);
4029 }
4030 }
4031
Nicolas Capens0bac2852016-05-07 06:09:58 -04004032 programObject->link();
4033 }
4034}
4035
4036void PixelStorei(GLenum pname, GLint param)
4037{
4038 TRACE("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
4039
Chris Forbes108f3e12018-08-30 19:41:59 -07004040 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004041
4042 if(context)
4043 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004044 switch(pname)
4045 {
4046 case GL_UNPACK_ALIGNMENT:
4047 if(param != 1 && param != 2 && param != 4 && param != 8)
4048 {
4049 return error(GL_INVALID_VALUE);
4050 }
4051 context->setUnpackAlignment(param);
4052 break;
4053 case GL_PACK_ALIGNMENT:
4054 if(param != 1 && param != 2 && param != 4 && param != 8)
4055 {
4056 return error(GL_INVALID_VALUE);
4057 }
4058 context->setPackAlignment(param);
4059 break;
4060 case GL_PACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004061 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004062 {
Nicolas Capens83463112018-06-12 23:55:16 -04004063 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004064 }
Nicolas Capens83463112018-06-12 23:55:16 -04004065 context->setPackRowLength(param);
4066 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004067 case GL_PACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004068 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004069 {
Nicolas Capens83463112018-06-12 23:55:16 -04004070 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004071 }
Nicolas Capens83463112018-06-12 23:55:16 -04004072 context->setPackSkipPixels(param);
4073 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004074 case GL_PACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004075 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004076 {
Nicolas Capens83463112018-06-12 23:55:16 -04004077 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004078 }
Nicolas Capens83463112018-06-12 23:55:16 -04004079 context->setPackSkipRows(param);
4080 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004081 case GL_UNPACK_ROW_LENGTH:
Nicolas Capens83463112018-06-12 23:55:16 -04004082 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004083 {
Nicolas Capens83463112018-06-12 23:55:16 -04004084 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004085 }
Nicolas Capens83463112018-06-12 23:55:16 -04004086 context->setUnpackRowLength(param);
4087 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004088 case GL_UNPACK_IMAGE_HEIGHT:
Nicolas Capens83463112018-06-12 23:55:16 -04004089 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004090 {
Nicolas Capens83463112018-06-12 23:55:16 -04004091 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004092 }
Nicolas Capens83463112018-06-12 23:55:16 -04004093 context->setUnpackImageHeight(param);
4094 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004095 case GL_UNPACK_SKIP_PIXELS:
Nicolas Capens83463112018-06-12 23:55:16 -04004096 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004097 {
Nicolas Capens83463112018-06-12 23:55:16 -04004098 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004099 }
Nicolas Capens83463112018-06-12 23:55:16 -04004100 context->setUnpackSkipPixels(param);
4101 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004102 case GL_UNPACK_SKIP_ROWS:
Nicolas Capens83463112018-06-12 23:55:16 -04004103 if(param < 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004104 {
Nicolas Capens83463112018-06-12 23:55:16 -04004105 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004106 }
Nicolas Capens83463112018-06-12 23:55:16 -04004107 context->setUnpackSkipRows(param);
4108 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004109 case GL_UNPACK_SKIP_IMAGES:
Nicolas Capens83463112018-06-12 23:55:16 -04004110 if(param < 0)
4111 {
4112 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004113 }
Nicolas Capens83463112018-06-12 23:55:16 -04004114 context->setUnpackSkipImages(param);
4115 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004116 default:
4117 return error(GL_INVALID_ENUM);
4118 }
4119 }
4120}
4121
4122void PolygonOffset(GLfloat factor, GLfloat units)
4123{
4124 TRACE("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
4125
Chris Forbes108f3e12018-08-30 19:41:59 -07004126 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004127
4128 if(context)
4129 {
4130 context->setPolygonOffsetParams(factor, units);
4131 }
4132}
4133
4134void ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
4135 GLenum format, GLenum type, GLsizei bufSize, GLvoid *data)
4136{
4137 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4138 "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = %p)",
4139 x, y, width, height, format, type, bufSize, data);
4140
4141 if(width < 0 || height < 0 || bufSize < 0)
4142 {
4143 return error(GL_INVALID_VALUE);
4144 }
4145
Chris Forbes108f3e12018-08-30 19:41:59 -07004146 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004147
4148 if(context)
4149 {
4150 context->readPixels(x, y, width, height, format, type, &bufSize, data);
4151 }
4152}
4153
4154void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
4155{
4156 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
4157 "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = %p)",
4158 x, y, width, height, format, type, pixels);
4159
4160 if(width < 0 || height < 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, nullptr, pixels);
4170 }
4171}
4172
4173void ReleaseShaderCompiler(void)
4174{
4175 TRACE("()");
4176
4177 es2::Shader::releaseCompiler();
4178}
4179
Nicolas Capens400667e2017-03-29 14:40:14 -04004180void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004181{
4182 TRACE("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
4183 target, samples, internalformat, width, height);
4184
4185 switch(target)
4186 {
4187 case GL_RENDERBUFFER:
4188 break;
4189 default:
4190 return error(GL_INVALID_ENUM);
4191 }
4192
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004193 if(width < 0 || height < 0 || samples < 0 ||
4194 width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
4195 height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004196 {
4197 return error(GL_INVALID_VALUE);
4198 }
4199
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004200 if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
Nicolas Capens5a0e7272017-12-06 13:18:52 -05004201 (IsNonNormalizedInteger(internalformat) && samples > 0))
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05004202 {
4203 return error(GL_INVALID_OPERATION);
4204 }
4205
Chris Forbes108f3e12018-08-30 19:41:59 -07004206 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004207
4208 if(context)
4209 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004210 GLuint handle = context->getRenderbufferName();
4211 if(handle == 0)
4212 {
4213 return error(GL_INVALID_OPERATION);
4214 }
4215
Nicolas Capens83463112018-06-12 23:55:16 -04004216 if(IsColorRenderable(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004217 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04004218 context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
Nicolas Capens0bac2852016-05-07 06:09:58 -04004219 }
Nicolas Capens83463112018-06-12 23:55:16 -04004220 else if(IsDepthRenderable(internalformat) && IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004221 {
4222 context->setRenderbufferStorage(new es2::DepthStencilbuffer(width, height, internalformat, samples));
4223 }
Nicolas Capens83463112018-06-12 23:55:16 -04004224 else if(IsDepthRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004225 {
4226 context->setRenderbufferStorage(new es2::Depthbuffer(width, height, internalformat, samples));
4227 }
Nicolas Capens83463112018-06-12 23:55:16 -04004228 else if(IsStencilRenderable(internalformat))
Nicolas Capens400667e2017-03-29 14:40:14 -04004229 {
4230 context->setRenderbufferStorage(new es2::Stencilbuffer(width, height, samples));
4231 }
4232 else error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004233 }
4234}
4235
Nicolas Capens400667e2017-03-29 14:40:14 -04004236void RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
4237{
4238 RenderbufferStorageMultisample(target, samples, internalformat, width, height);
4239}
4240
Nicolas Capens0bac2852016-05-07 06:09:58 -04004241void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
4242{
Nicolas Capens400667e2017-03-29 14:40:14 -04004243 RenderbufferStorageMultisample(target, 0, internalformat, width, height);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004244}
4245
4246void SampleCoverage(GLclampf value, GLboolean invert)
4247{
4248 TRACE("(GLclampf value = %f, GLboolean invert = %d)", value, invert);
4249
Chris Forbes108f3e12018-08-30 19:41:59 -07004250 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004251
4252 if(context)
4253 {
Nicolas Capens51814272018-10-15 13:01:22 -04004254 context->setSampleCoverageParams(es2::clamp01(value), invert != GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004255 }
4256}
4257
4258void SetFenceNV(GLuint fence, GLenum condition)
4259{
4260 TRACE("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
4261
4262 if(condition != GL_ALL_COMPLETED_NV)
4263 {
4264 return error(GL_INVALID_ENUM);
4265 }
4266
Chris Forbes108f3e12018-08-30 19:41:59 -07004267 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004268
4269 if(context)
4270 {
4271 es2::Fence *fenceObject = context->getFence(fence);
4272
4273 if(!fenceObject)
4274 {
4275 return error(GL_INVALID_OPERATION);
4276 }
4277
4278 fenceObject->setFence(condition);
4279 }
4280}
4281
4282void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
4283{
4284 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
4285
4286 if(width < 0 || height < 0)
4287 {
4288 return error(GL_INVALID_VALUE);
4289 }
4290
Chris Forbes108f3e12018-08-30 19:41:59 -07004291 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004292
4293 if(context)
4294 {
4295 context->setScissorParams(x, y, width, height);
4296 }
4297}
4298
4299void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
4300{
4301 TRACE("(GLsizei n = %d, const GLuint* shaders = %p, GLenum binaryformat = 0x%X, "
4302 "const GLvoid* binary = %p, GLsizei length = %d)",
4303 n, shaders, binaryformat, binary, length);
4304
4305 // No binary shader formats are supported.
4306 return error(GL_INVALID_ENUM);
4307}
4308
4309void ShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
4310{
4311 TRACE("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = %p, const GLint* length = %p)",
4312 shader, count, string, length);
4313
4314 if(count < 0)
4315 {
4316 return error(GL_INVALID_VALUE);
4317 }
4318
Chris Forbes108f3e12018-08-30 19:41:59 -07004319 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004320
4321 if(context)
4322 {
4323 es2::Shader *shaderObject = context->getShader(shader);
4324
4325 if(!shaderObject)
4326 {
4327 if(context->getProgram(shader))
4328 {
4329 return error(GL_INVALID_OPERATION);
4330 }
4331 else
4332 {
4333 return error(GL_INVALID_VALUE);
4334 }
4335 }
4336
4337 shaderObject->setSource(count, string, length);
4338 }
4339}
4340
Nicolas Capens0bac2852016-05-07 06:09:58 -04004341void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
4342{
4343 TRACE("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
4344
4345 switch(face)
4346 {
4347 case GL_FRONT:
4348 case GL_BACK:
4349 case GL_FRONT_AND_BACK:
4350 break;
4351 default:
4352 return error(GL_INVALID_ENUM);
4353 }
4354
4355 switch(func)
4356 {
4357 case GL_NEVER:
4358 case GL_ALWAYS:
4359 case GL_LESS:
4360 case GL_LEQUAL:
4361 case GL_EQUAL:
4362 case GL_GEQUAL:
4363 case GL_GREATER:
4364 case GL_NOTEQUAL:
4365 break;
4366 default:
4367 return error(GL_INVALID_ENUM);
4368 }
4369
Chris Forbes108f3e12018-08-30 19:41:59 -07004370 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004371
4372 if(context)
4373 {
4374 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4375 {
4376 context->setStencilParams(func, ref, mask);
4377 }
4378
4379 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4380 {
4381 context->setStencilBackParams(func, ref, mask);
4382 }
4383 }
4384}
4385
Nicolas Capens805d7612018-08-02 13:56:32 -04004386void StencilFunc(GLenum func, GLint ref, GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004387{
Nicolas Capens805d7612018-08-02 13:56:32 -04004388 StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004389}
4390
4391void StencilMaskSeparate(GLenum face, GLuint mask)
4392{
4393 TRACE("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
4394
4395 switch(face)
4396 {
4397 case GL_FRONT:
4398 case GL_BACK:
4399 case GL_FRONT_AND_BACK:
4400 break;
4401 default:
4402 return error(GL_INVALID_ENUM);
4403 }
4404
Chris Forbes108f3e12018-08-30 19:41:59 -07004405 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004406
4407 if(context)
4408 {
4409 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4410 {
4411 context->setStencilWritemask(mask);
4412 }
4413
4414 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4415 {
4416 context->setStencilBackWritemask(mask);
4417 }
4418 }
4419}
4420
Nicolas Capens805d7612018-08-02 13:56:32 -04004421void StencilMask(GLuint mask)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004422{
Nicolas Capens805d7612018-08-02 13:56:32 -04004423 StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004424}
4425
4426void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
4427{
4428 TRACE("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
4429 face, fail, zfail, zpass);
4430
4431 switch(face)
4432 {
4433 case GL_FRONT:
4434 case GL_BACK:
4435 case GL_FRONT_AND_BACK:
4436 break;
4437 default:
4438 return error(GL_INVALID_ENUM);
4439 }
4440
4441 switch(fail)
4442 {
4443 case GL_ZERO:
4444 case GL_KEEP:
4445 case GL_REPLACE:
4446 case GL_INCR:
4447 case GL_DECR:
4448 case GL_INVERT:
4449 case GL_INCR_WRAP:
4450 case GL_DECR_WRAP:
4451 break;
4452 default:
4453 return error(GL_INVALID_ENUM);
4454 }
4455
4456 switch(zfail)
4457 {
4458 case GL_ZERO:
4459 case GL_KEEP:
4460 case GL_REPLACE:
4461 case GL_INCR:
4462 case GL_DECR:
4463 case GL_INVERT:
4464 case GL_INCR_WRAP:
4465 case GL_DECR_WRAP:
4466 break;
4467 default:
4468 return error(GL_INVALID_ENUM);
4469 }
4470
4471 switch(zpass)
4472 {
4473 case GL_ZERO:
4474 case GL_KEEP:
4475 case GL_REPLACE:
4476 case GL_INCR:
4477 case GL_DECR:
4478 case GL_INVERT:
4479 case GL_INCR_WRAP:
4480 case GL_DECR_WRAP:
4481 break;
4482 default:
4483 return error(GL_INVALID_ENUM);
4484 }
4485
Chris Forbes108f3e12018-08-30 19:41:59 -07004486 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004487
4488 if(context)
4489 {
4490 if(face == GL_FRONT || face == GL_FRONT_AND_BACK)
4491 {
4492 context->setStencilOperations(fail, zfail, zpass);
4493 }
4494
4495 if(face == GL_BACK || face == GL_FRONT_AND_BACK)
4496 {
4497 context->setStencilBackOperations(fail, zfail, zpass);
4498 }
4499 }
4500}
4501
Nicolas Capens805d7612018-08-02 13:56:32 -04004502void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
4503{
4504 StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
4505}
4506
Nicolas Capens0bac2852016-05-07 06:09:58 -04004507GLboolean TestFenceNV(GLuint fence)
4508{
4509 TRACE("(GLuint fence = %d)", fence);
4510
Chris Forbes108f3e12018-08-30 19:41:59 -07004511 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004512
4513 if(context)
4514 {
4515 es2::Fence *fenceObject = context->getFence(fence);
4516
4517 if(!fenceObject)
4518 {
4519 return error(GL_INVALID_OPERATION, GL_TRUE);
4520 }
4521
4522 return fenceObject->testFence();
4523 }
4524
4525 return GL_TRUE;
4526}
4527
4528void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004529 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004530{
4531 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004532 "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* data = %p)",
4533 target, level, internalformat, width, height, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004534
4535 if(!validImageSize(level, width, height))
4536 {
4537 return error(GL_INVALID_VALUE);
4538 }
4539
Chris Forbes108f3e12018-08-30 19:41:59 -07004540 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004541
4542 if(context)
4543 {
Nicolas Capens83463112018-06-12 23:55:16 -04004544 // GL_APPLE_texture_format_BGRA8888 allows (only) GL_BGRA_EXT / GL_RGBA, while
Nicolas Capensbc62c3b2018-02-27 16:45:43 -05004545 // GL_EXT_texture_format_BGRA8888 also allows GL_BGRA_EXT / GL_BGRA_EXT.
4546 if(format == GL_BGRA_EXT && internalformat == GL_RGBA)
4547 {
4548 internalformat = GL_BGRA_EXT;
4549 }
4550
Nicolas Capens83463112018-06-12 23:55:16 -04004551 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05004552 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004553 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004554 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004555 }
4556
4557 if(border != 0)
4558 {
4559 return error(GL_INVALID_VALUE);
4560 }
4561
4562 switch(target)
4563 {
Alexis Hetu46768622018-01-16 22:09:28 -05004564 case GL_TEXTURE_RECTANGLE_ARB:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004565 if(level != 0)
4566 {
4567 return error(GL_INVALID_VALUE); // Defining level other than 0 is not allowed
4568 }
Nicolas Capens894858a2018-03-22 00:55:23 -04004569 // Fall through to GL_TEXTURE_2D case.
Alexis Hetu0988fb82018-02-02 17:23:48 -05004570 case GL_TEXTURE_2D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04004571 if(width > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level) ||
4572 height > (es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level))
4573 {
4574 return error(GL_INVALID_VALUE);
4575 }
4576 break;
4577 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4581 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4582 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4583 if(width != height)
4584 {
4585 return error(GL_INVALID_VALUE);
4586 }
4587
4588 if(width > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level) ||
4589 height > (es2::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE >> level))
4590 {
4591 return error(GL_INVALID_VALUE);
4592 }
4593 break;
4594 default:
4595 return error(GL_INVALID_ENUM);
4596 }
4597
Nicolas Capens5555af42017-12-14 13:14:03 -05004598 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004599 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05004600 {
4601 return error(validationError);
4602 }
4603
Nicolas Capens894858a2018-03-22 00:55:23 -04004604 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
4605
Alexis Hetu46768622018-01-16 22:09:28 -05004606 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004607 {
Alexis Hetu46768622018-01-16 22:09:28 -05004608 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004609
4610 if(!texture)
4611 {
4612 return error(GL_INVALID_OPERATION);
4613 }
4614
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004615 texture->setImage(level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004616 }
4617 else
4618 {
4619 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4620
4621 if(!texture)
4622 {
4623 return error(GL_INVALID_OPERATION);
4624 }
4625
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004626 texture->setImage(target, level, width, height, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004627 }
4628 }
4629}
4630
4631void TexParameterf(GLenum target, GLenum pname, GLfloat param)
4632{
4633 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
4634
Chris Forbes108f3e12018-08-30 19:41:59 -07004635 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004636
4637 if(context)
4638 {
4639 es2::Texture *texture;
4640
Nicolas Capens0bac2852016-05-07 06:09:58 -04004641 switch(target)
4642 {
Nicolas Capens83463112018-06-12 23:55:16 -04004643 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4644 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4645 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4646 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4647 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4648 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004649 default:
4650 return error(GL_INVALID_ENUM);
4651 }
4652
4653 switch(pname)
4654 {
4655 case GL_TEXTURE_WRAP_S:
4656 if(!texture->setWrapS((GLenum)param))
4657 {
4658 return error(GL_INVALID_ENUM);
4659 }
4660 break;
4661 case GL_TEXTURE_WRAP_T:
4662 if(!texture->setWrapT((GLenum)param))
4663 {
4664 return error(GL_INVALID_ENUM);
4665 }
4666 break;
4667 case GL_TEXTURE_WRAP_R_OES:
4668 if(!texture->setWrapR((GLenum)param))
4669 {
4670 return error(GL_INVALID_ENUM);
4671 }
4672 break;
4673 case GL_TEXTURE_MIN_FILTER:
4674 if(!texture->setMinFilter((GLenum)param))
4675 {
4676 return error(GL_INVALID_ENUM);
4677 }
4678 break;
4679 case GL_TEXTURE_MAG_FILTER:
4680 if(!texture->setMagFilter((GLenum)param))
4681 {
4682 return error(GL_INVALID_ENUM);
4683 }
4684 break;
4685 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4686 if(!texture->setMaxAnisotropy(param))
4687 {
4688 return error(GL_INVALID_VALUE);
4689 }
4690 break;
4691 case GL_TEXTURE_BASE_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004692 if(!texture->setBaseLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004693 {
4694 return error(GL_INVALID_VALUE);
4695 }
4696 break;
4697 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004698 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004699 {
4700 return error(GL_INVALID_VALUE);
4701 }
4702 break;
4703 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004704 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004705 {
4706 return error(GL_INVALID_VALUE);
4707 }
4708 break;
4709 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004710 if(!texture->setMaxLevel((GLint)(roundf(param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004711 {
4712 return error(GL_INVALID_VALUE);
4713 }
4714 break;
4715 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004716 if(!texture->setMaxLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004717 {
4718 return error(GL_INVALID_VALUE);
4719 }
4720 break;
4721 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004722 if(!texture->setMinLOD(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004723 {
4724 return error(GL_INVALID_VALUE);
4725 }
4726 break;
4727 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004728 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004729 {
4730 return error(GL_INVALID_VALUE);
4731 }
4732 break;
4733 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004734 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004735 {
4736 return error(GL_INVALID_VALUE);
4737 }
4738 break;
4739 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004740 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004741 {
4742 return error(GL_INVALID_VALUE);
4743 }
4744 break;
4745 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004746 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004747 {
4748 return error(GL_INVALID_VALUE);
4749 }
4750 break;
4751 default:
4752 return error(GL_INVALID_ENUM);
4753 }
4754 }
4755}
4756
4757void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
4758{
Nicolas Capens805d7612018-08-02 13:56:32 -04004759 TexParameterf(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004760}
4761
4762void TexParameteri(GLenum target, GLenum pname, GLint param)
4763{
4764 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
4765
Chris Forbes108f3e12018-08-30 19:41:59 -07004766 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004767
4768 if(context)
4769 {
4770 es2::Texture *texture;
4771
Nicolas Capens0bac2852016-05-07 06:09:58 -04004772 switch(target)
4773 {
Nicolas Capens83463112018-06-12 23:55:16 -04004774 case GL_TEXTURE_2D: texture = context->getTexture2D(); break;
4775 case GL_TEXTURE_2D_ARRAY: texture = context->getTexture2DArray(); break;
4776 case GL_TEXTURE_3D: texture = context->getTexture3D(); break;
4777 case GL_TEXTURE_CUBE_MAP: texture = context->getTextureCubeMap(); break;
4778 case GL_TEXTURE_EXTERNAL_OES: texture = context->getTextureExternal(); break;
4779 case GL_TEXTURE_RECTANGLE_ARB: texture = context->getTexture2DRect(); break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04004780 default:
4781 return error(GL_INVALID_ENUM);
4782 }
4783
4784 switch(pname)
4785 {
4786 case GL_TEXTURE_WRAP_S:
4787 if(!texture->setWrapS((GLenum)param))
4788 {
4789 return error(GL_INVALID_ENUM);
4790 }
4791 break;
4792 case GL_TEXTURE_WRAP_T:
4793 if(!texture->setWrapT((GLenum)param))
4794 {
4795 return error(GL_INVALID_ENUM);
4796 }
4797 break;
4798 case GL_TEXTURE_WRAP_R_OES:
4799 if(!texture->setWrapR((GLenum)param))
4800 {
4801 return error(GL_INVALID_ENUM);
4802 }
4803 break;
4804 case GL_TEXTURE_MIN_FILTER:
4805 if(!texture->setMinFilter((GLenum)param))
4806 {
4807 return error(GL_INVALID_ENUM);
4808 }
4809 break;
4810 case GL_TEXTURE_MAG_FILTER:
4811 if(!texture->setMagFilter((GLenum)param))
4812 {
4813 return error(GL_INVALID_ENUM);
4814 }
4815 break;
4816 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4817 if(!texture->setMaxAnisotropy((GLfloat)param))
4818 {
4819 return error(GL_INVALID_VALUE);
4820 }
4821 break;
4822 case GL_TEXTURE_BASE_LEVEL:
Alexis Hetu0988fb82018-02-02 17:23:48 -05004823 if((texture->getTarget() == GL_TEXTURE_RECTANGLE_ARB) && (param != 0))
4824 {
4825 return error(GL_INVALID_OPERATION); // Base level has to be 0
4826 }
Nicolas Capens83463112018-06-12 23:55:16 -04004827 if(!texture->setBaseLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004828 {
4829 return error(GL_INVALID_VALUE);
4830 }
4831 break;
4832 case GL_TEXTURE_COMPARE_FUNC:
Nicolas Capens83463112018-06-12 23:55:16 -04004833 if(!texture->setCompareFunc((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004834 {
4835 return error(GL_INVALID_VALUE);
4836 }
4837 break;
4838 case GL_TEXTURE_COMPARE_MODE:
Nicolas Capens83463112018-06-12 23:55:16 -04004839 if(!texture->setCompareMode((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004840 {
4841 return error(GL_INVALID_VALUE);
4842 }
4843 break;
4844 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens83463112018-06-12 23:55:16 -04004845 if(!texture->setMaxLevel(param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004846 {
4847 return error(GL_INVALID_VALUE);
4848 }
4849 break;
4850 case GL_TEXTURE_MAX_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004851 if(!texture->setMaxLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004852 {
4853 return error(GL_INVALID_VALUE);
4854 }
4855 break;
4856 case GL_TEXTURE_MIN_LOD:
Nicolas Capens83463112018-06-12 23:55:16 -04004857 if(!texture->setMinLOD((GLfloat)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004858 {
4859 return error(GL_INVALID_VALUE);
4860 }
4861 break;
4862 case GL_TEXTURE_SWIZZLE_R:
Nicolas Capens83463112018-06-12 23:55:16 -04004863 if(!texture->setSwizzleR((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004864 {
4865 return error(GL_INVALID_VALUE);
4866 }
4867 break;
4868 case GL_TEXTURE_SWIZZLE_G:
Nicolas Capens83463112018-06-12 23:55:16 -04004869 if(!texture->setSwizzleG((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004870 {
4871 return error(GL_INVALID_VALUE);
4872 }
4873 break;
4874 case GL_TEXTURE_SWIZZLE_B:
Nicolas Capens83463112018-06-12 23:55:16 -04004875 if(!texture->setSwizzleB((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004876 {
4877 return error(GL_INVALID_VALUE);
4878 }
4879 break;
4880 case GL_TEXTURE_SWIZZLE_A:
Nicolas Capens83463112018-06-12 23:55:16 -04004881 if(!texture->setSwizzleA((GLenum)param))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004882 {
4883 return error(GL_INVALID_VALUE);
4884 }
4885 break;
4886 default:
4887 return error(GL_INVALID_ENUM);
4888 }
4889 }
4890}
4891
4892void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
4893{
Nicolas Capens805d7612018-08-02 13:56:32 -04004894 TexParameteri(target, pname, *params);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004895}
4896
4897void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
Alexis Hetu53f48092016-06-17 14:08:06 -04004898 GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004899{
4900 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
4901 "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
Alexis Hetu53f48092016-06-17 14:08:06 -04004902 "const GLvoid* data = %p)",
4903 target, level, xoffset, yoffset, width, height, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004904
4905 if(!es2::IsTextureTarget(target))
4906 {
4907 return error(GL_INVALID_ENUM);
4908 }
4909
4910 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4911 {
4912 return error(GL_INVALID_VALUE);
4913 }
4914
4915 if(xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
4916 {
4917 return error(GL_INVALID_VALUE);
4918 }
4919
4920 if(std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
4921 {
4922 return error(GL_INVALID_VALUE);
4923 }
4924
Chris Forbes108f3e12018-08-30 19:41:59 -07004925 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004926
4927 if(context)
4928 {
Alexis Hetu46768622018-01-16 22:09:28 -05004929 if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004930 {
Alexis Hetu46768622018-01-16 22:09:28 -05004931 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004932
Nicolas Capens83463112018-06-12 23:55:16 -04004933 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004934 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004935 {
4936 return error(validationError);
4937 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004938
Nicolas Capens5555af42017-12-14 13:14:03 -05004939 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004940 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004941 {
4942 return error(validationError);
4943 }
4944
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004945 texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004946 }
4947 else if(es2::IsCubemapTextureTarget(target))
4948 {
4949 es2::TextureCubeMap *texture = context->getTextureCubeMap();
4950
Nicolas Capens83463112018-06-12 23:55:16 -04004951 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05004952 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04004953 {
4954 return error(validationError);
4955 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004956
Nicolas Capens5555af42017-12-14 13:14:03 -05004957 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05004958 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05004959 {
4960 return error(validationError);
4961 }
4962
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05004963 texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004964 }
4965 else UNREACHABLE(target);
4966 }
4967}
4968
Nicolas Capens0bac2852016-05-07 06:09:58 -04004969void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
4970{
4971 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
4972
4973 if(count < 0)
4974 {
4975 return error(GL_INVALID_VALUE);
4976 }
4977
Chris Forbes108f3e12018-08-30 19:41:59 -07004978 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04004979
4980 if(context)
4981 {
4982 es2::Program *program = context->getCurrentProgram();
4983
4984 if(!program)
4985 {
4986 return error(GL_INVALID_OPERATION);
4987 }
4988
Alexis Hetu3eb573f2017-11-22 13:27:03 -05004989 if(location == -1)
4990 {
4991 return;
4992 }
4993
Nicolas Capens0bac2852016-05-07 06:09:58 -04004994 if(!program->setUniform1fv(location, count, v))
4995 {
4996 return error(GL_INVALID_OPERATION);
4997 }
4998 }
4999}
5000
Nicolas Capens805d7612018-08-02 13:56:32 -04005001void Uniform1f(GLint location, GLfloat x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005002{
Nicolas Capens805d7612018-08-02 13:56:32 -04005003 Uniform1fv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005004}
5005
5006void Uniform1iv(GLint location, GLsizei count, const GLint* v)
5007{
5008 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5009
5010 if(count < 0)
5011 {
5012 return error(GL_INVALID_VALUE);
5013 }
5014
Chris Forbes108f3e12018-08-30 19:41:59 -07005015 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005016
5017 if(context)
5018 {
5019 es2::Program *program = context->getCurrentProgram();
5020
5021 if(!program)
5022 {
5023 return error(GL_INVALID_OPERATION);
5024 }
5025
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005026 if(location == -1)
5027 {
5028 return;
5029 }
5030
Nicolas Capens0bac2852016-05-07 06:09:58 -04005031 if(!program->setUniform1iv(location, count, v))
5032 {
5033 return error(GL_INVALID_OPERATION);
5034 }
5035 }
5036}
5037
Nicolas Capens805d7612018-08-02 13:56:32 -04005038void Uniform1i(GLint location, GLint x)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005039{
Nicolas Capens805d7612018-08-02 13:56:32 -04005040 Uniform1iv(location, 1, &x);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005041}
5042
5043void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
5044{
5045 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5046
5047 if(count < 0)
5048 {
5049 return error(GL_INVALID_VALUE);
5050 }
5051
Chris Forbes108f3e12018-08-30 19:41:59 -07005052 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005053
5054 if(context)
5055 {
5056 es2::Program *program = context->getCurrentProgram();
5057
5058 if(!program)
5059 {
5060 return error(GL_INVALID_OPERATION);
5061 }
5062
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005063 if(location == -1)
5064 {
5065 return;
5066 }
5067
Nicolas Capens0bac2852016-05-07 06:09:58 -04005068 if(!program->setUniform2fv(location, count, v))
5069 {
5070 return error(GL_INVALID_OPERATION);
5071 }
5072 }
5073}
5074
Nicolas Capens805d7612018-08-02 13:56:32 -04005075void Uniform2f(GLint location, GLfloat x, GLfloat y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005076{
Nicolas Capens805d7612018-08-02 13:56:32 -04005077 GLfloat xy[2] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005078
Nicolas Capens805d7612018-08-02 13:56:32 -04005079 Uniform2fv(location, 1, (GLfloat*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005080}
5081
5082void Uniform2iv(GLint location, GLsizei count, const GLint* v)
5083{
5084 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5085
5086 if(count < 0)
5087 {
5088 return error(GL_INVALID_VALUE);
5089 }
5090
Chris Forbes108f3e12018-08-30 19:41:59 -07005091 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005092
5093 if(context)
5094 {
5095 es2::Program *program = context->getCurrentProgram();
5096
5097 if(!program)
5098 {
5099 return error(GL_INVALID_OPERATION);
5100 }
5101
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005102 if(location == -1)
5103 {
5104 return;
5105 }
5106
Nicolas Capens0bac2852016-05-07 06:09:58 -04005107 if(!program->setUniform2iv(location, count, v))
5108 {
5109 return error(GL_INVALID_OPERATION);
5110 }
5111 }
5112}
5113
Nicolas Capens805d7612018-08-02 13:56:32 -04005114void Uniform2i(GLint location, GLint x, GLint y)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005115{
Nicolas Capens805d7612018-08-02 13:56:32 -04005116 GLint xy[4] = {x, y};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005117
Nicolas Capens805d7612018-08-02 13:56:32 -04005118 Uniform2iv(location, 1, (GLint*)&xy);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005119}
5120
5121void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
5122{
5123 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5124
5125 if(count < 0)
5126 {
5127 return error(GL_INVALID_VALUE);
5128 }
5129
Chris Forbes108f3e12018-08-30 19:41:59 -07005130 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005131
5132 if(context)
5133 {
5134 es2::Program *program = context->getCurrentProgram();
5135
5136 if(!program)
5137 {
5138 return error(GL_INVALID_OPERATION);
5139 }
5140
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005141 if(location == -1)
5142 {
5143 return;
5144 }
5145
Nicolas Capens0bac2852016-05-07 06:09:58 -04005146 if(!program->setUniform3fv(location, count, v))
5147 {
5148 return error(GL_INVALID_OPERATION);
5149 }
5150 }
5151}
5152
Nicolas Capens805d7612018-08-02 13:56:32 -04005153void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005154{
Nicolas Capens805d7612018-08-02 13:56:32 -04005155 GLfloat xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005156
Nicolas Capens805d7612018-08-02 13:56:32 -04005157 Uniform3fv(location, 1, (GLfloat*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005158}
5159
5160void Uniform3iv(GLint location, GLsizei count, const GLint* v)
5161{
5162 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5163
5164 if(count < 0)
5165 {
5166 return error(GL_INVALID_VALUE);
5167 }
5168
Chris Forbes108f3e12018-08-30 19:41:59 -07005169 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005170
5171 if(context)
5172 {
5173 es2::Program *program = context->getCurrentProgram();
5174
5175 if(!program)
5176 {
5177 return error(GL_INVALID_OPERATION);
5178 }
5179
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005180 if(location == -1)
5181 {
5182 return;
5183 }
5184
Nicolas Capens0bac2852016-05-07 06:09:58 -04005185 if(!program->setUniform3iv(location, count, v))
5186 {
5187 return error(GL_INVALID_OPERATION);
5188 }
5189 }
5190}
5191
Nicolas Capens805d7612018-08-02 13:56:32 -04005192void Uniform3i(GLint location, GLint x, GLint y, GLint z)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005193{
Nicolas Capens805d7612018-08-02 13:56:32 -04005194 GLint xyz[3] = {x, y, z};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005195
Nicolas Capens805d7612018-08-02 13:56:32 -04005196 Uniform3iv(location, 1, (GLint*)&xyz);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005197}
5198
5199void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
5200{
5201 TRACE("(GLint location = %d, GLsizei count = %d, const GLfloat* v = %p)", location, count, v);
5202
5203 if(count < 0)
5204 {
5205 return error(GL_INVALID_VALUE);
5206 }
5207
Chris Forbes108f3e12018-08-30 19:41:59 -07005208 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005209
5210 if(context)
5211 {
5212 es2::Program *program = context->getCurrentProgram();
5213
5214 if(!program)
5215 {
5216 return error(GL_INVALID_OPERATION);
5217 }
5218
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005219 if(location == -1)
5220 {
5221 return;
5222 }
5223
Nicolas Capens0bac2852016-05-07 06:09:58 -04005224 if(!program->setUniform4fv(location, count, v))
5225 {
5226 return error(GL_INVALID_OPERATION);
5227 }
5228 }
5229}
5230
Nicolas Capens805d7612018-08-02 13:56:32 -04005231void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005232{
Nicolas Capens805d7612018-08-02 13:56:32 -04005233 GLfloat xyzw[4] = {x, y, z, w};
Nicolas Capens0bac2852016-05-07 06:09:58 -04005234
Nicolas Capens805d7612018-08-02 13:56:32 -04005235 Uniform4fv(location, 1, (GLfloat*)&xyzw);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005236}
5237
5238void Uniform4iv(GLint location, GLsizei count, const GLint* v)
5239{
5240 TRACE("(GLint location = %d, GLsizei count = %d, const GLint* v = %p)", location, count, v);
5241
5242 if(count < 0)
5243 {
5244 return error(GL_INVALID_VALUE);
5245 }
5246
Chris Forbes108f3e12018-08-30 19:41:59 -07005247 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005248
5249 if(context)
5250 {
5251 es2::Program *program = context->getCurrentProgram();
5252
5253 if(!program)
5254 {
5255 return error(GL_INVALID_OPERATION);
5256 }
5257
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005258 if(location == -1)
5259 {
5260 return;
5261 }
5262
Nicolas Capens0bac2852016-05-07 06:09:58 -04005263 if(!program->setUniform4iv(location, count, v))
5264 {
5265 return error(GL_INVALID_OPERATION);
5266 }
5267 }
5268}
5269
Nicolas Capens805d7612018-08-02 13:56:32 -04005270void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
5271{
5272 GLint xyzw[4] = {x, y, z, w};
5273
5274 Uniform4iv(location, 1, (GLint*)&xyzw);
5275}
5276
Nicolas Capens0bac2852016-05-07 06:09:58 -04005277void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5278{
5279 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5280 location, count, transpose, value);
5281
5282 if(count < 0)
5283 {
5284 return error(GL_INVALID_VALUE);
5285 }
5286
Chris Forbes108f3e12018-08-30 19:41:59 -07005287 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005288
5289 if(context)
5290 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005291 es2::Program *program = context->getCurrentProgram();
5292
5293 if(!program)
5294 {
5295 return error(GL_INVALID_OPERATION);
5296 }
5297
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005298 if(location == -1)
5299 {
5300 return;
5301 }
5302
Nicolas Capens0bac2852016-05-07 06:09:58 -04005303 if(!program->setUniformMatrix2fv(location, count, transpose, value))
5304 {
5305 return error(GL_INVALID_OPERATION);
5306 }
5307 }
5308}
5309
5310void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5311{
5312 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5313 location, count, transpose, value);
5314
5315 if(count < 0)
5316 {
5317 return error(GL_INVALID_VALUE);
5318 }
5319
Chris Forbes108f3e12018-08-30 19:41:59 -07005320 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005321
5322 if(context)
5323 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005324 es2::Program *program = context->getCurrentProgram();
5325
5326 if(!program)
5327 {
5328 return error(GL_INVALID_OPERATION);
5329 }
5330
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005331 if(location == -1)
5332 {
5333 return;
5334 }
5335
Nicolas Capens0bac2852016-05-07 06:09:58 -04005336 if(!program->setUniformMatrix3fv(location, count, transpose, value))
5337 {
5338 return error(GL_INVALID_OPERATION);
5339 }
5340 }
5341}
5342
5343void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
5344{
5345 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = %p)",
5346 location, count, transpose, value);
5347
5348 if(count < 0)
5349 {
5350 return error(GL_INVALID_VALUE);
5351 }
5352
Chris Forbes108f3e12018-08-30 19:41:59 -07005353 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005354
5355 if(context)
5356 {
Nicolas Capens0bac2852016-05-07 06:09:58 -04005357 es2::Program *program = context->getCurrentProgram();
5358
5359 if(!program)
5360 {
5361 return error(GL_INVALID_OPERATION);
5362 }
5363
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005364 if(location == -1)
5365 {
5366 return;
5367 }
5368
Nicolas Capens0bac2852016-05-07 06:09:58 -04005369 if(!program->setUniformMatrix4fv(location, count, transpose, value))
5370 {
5371 return error(GL_INVALID_OPERATION);
5372 }
5373 }
5374}
5375
5376void UseProgram(GLuint program)
5377{
5378 TRACE("(GLuint program = %d)", program);
5379
Chris Forbes108f3e12018-08-30 19:41:59 -07005380 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005381
5382 if(context)
5383 {
Alexis Hetu3eb573f2017-11-22 13:27:03 -05005384 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
5385 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
5386 {
5387 return error(GL_INVALID_OPERATION);
5388 }
5389
Nicolas Capens0bac2852016-05-07 06:09:58 -04005390 es2::Program *programObject = context->getProgram(program);
5391
5392 if(!programObject && program != 0)
5393 {
5394 if(context->getShader(program))
5395 {
5396 return error(GL_INVALID_OPERATION);
5397 }
5398 else
5399 {
5400 return error(GL_INVALID_VALUE);
5401 }
5402 }
5403
5404 if(program != 0 && !programObject->isLinked())
5405 {
5406 return error(GL_INVALID_OPERATION);
5407 }
5408
5409 context->useProgram(program);
5410 }
5411}
5412
5413void ValidateProgram(GLuint program)
5414{
5415 TRACE("(GLuint program = %d)", program);
5416
Chris Forbes108f3e12018-08-30 19:41:59 -07005417 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005418
5419 if(context)
5420 {
5421 es2::Program *programObject = context->getProgram(program);
5422
5423 if(!programObject)
5424 {
5425 if(context->getShader(program))
5426 {
5427 return error(GL_INVALID_OPERATION);
5428 }
5429 else
5430 {
5431 return error(GL_INVALID_VALUE);
5432 }
5433 }
5434
Ben Vanik1fd3b282017-07-10 14:08:12 -07005435 programObject->validate(context->getDevice());
Nicolas Capens0bac2852016-05-07 06:09:58 -04005436 }
5437}
5438
5439void VertexAttrib1f(GLuint index, GLfloat x)
5440{
5441 TRACE("(GLuint index = %d, GLfloat x = %f)", index, x);
5442
5443 if(index >= es2::MAX_VERTEX_ATTRIBS)
5444 {
5445 return error(GL_INVALID_VALUE);
5446 }
5447
Chris Forbes108f3e12018-08-30 19:41:59 -07005448 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005449
5450 if(context)
5451 {
5452 GLfloat vals[4] = { x, 0, 0, 1 };
5453 context->setVertexAttrib(index, vals);
5454 }
5455}
5456
5457void VertexAttrib1fv(GLuint index, const GLfloat* values)
5458{
5459 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5460
5461 if(index >= es2::MAX_VERTEX_ATTRIBS)
5462 {
5463 return error(GL_INVALID_VALUE);
5464 }
5465
Chris Forbes108f3e12018-08-30 19:41:59 -07005466 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005467
5468 if(context)
5469 {
5470 GLfloat vals[4] = { values[0], 0, 0, 1 };
5471 context->setVertexAttrib(index, vals);
5472 }
5473}
5474
5475void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
5476{
5477 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
5478
5479 if(index >= es2::MAX_VERTEX_ATTRIBS)
5480 {
5481 return error(GL_INVALID_VALUE);
5482 }
5483
Chris Forbes108f3e12018-08-30 19:41:59 -07005484 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005485
5486 if(context)
5487 {
5488 GLfloat vals[4] = { x, y, 0, 1 };
5489 context->setVertexAttrib(index, vals);
5490 }
5491}
5492
5493void VertexAttrib2fv(GLuint index, const GLfloat* values)
5494{
5495 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5496
5497 if(index >= es2::MAX_VERTEX_ATTRIBS)
5498 {
5499 return error(GL_INVALID_VALUE);
5500 }
5501
Chris Forbes108f3e12018-08-30 19:41:59 -07005502 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005503
5504 if(context)
5505 {
5506 GLfloat vals[4] = { values[0], values[1], 0, 1 };
5507 context->setVertexAttrib(index, vals);
5508 }
5509}
5510
5511void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
5512{
5513 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
5514
5515 if(index >= es2::MAX_VERTEX_ATTRIBS)
5516 {
5517 return error(GL_INVALID_VALUE);
5518 }
5519
Chris Forbes108f3e12018-08-30 19:41:59 -07005520 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005521
5522 if(context)
5523 {
5524 GLfloat vals[4] = { x, y, z, 1 };
5525 context->setVertexAttrib(index, vals);
5526 }
5527}
5528
5529void VertexAttrib3fv(GLuint index, const GLfloat* values)
5530{
5531 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5532
5533 if(index >= es2::MAX_VERTEX_ATTRIBS)
5534 {
5535 return error(GL_INVALID_VALUE);
5536 }
5537
Chris Forbes108f3e12018-08-30 19:41:59 -07005538 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005539
5540 if(context)
5541 {
5542 GLfloat vals[4] = { values[0], values[1], values[2], 1 };
5543 context->setVertexAttrib(index, vals);
5544 }
5545}
5546
5547void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
5548{
5549 TRACE("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
5550
5551 if(index >= es2::MAX_VERTEX_ATTRIBS)
5552 {
5553 return error(GL_INVALID_VALUE);
5554 }
5555
Chris Forbes108f3e12018-08-30 19:41:59 -07005556 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005557
5558 if(context)
5559 {
5560 GLfloat vals[4] = { x, y, z, w };
5561 context->setVertexAttrib(index, vals);
5562 }
5563}
5564
5565void VertexAttrib4fv(GLuint index, const GLfloat* values)
5566{
5567 TRACE("(GLuint index = %d, const GLfloat* values = %p)", index, values);
5568
5569 if(index >= es2::MAX_VERTEX_ATTRIBS)
5570 {
5571 return error(GL_INVALID_VALUE);
5572 }
5573
Chris Forbes108f3e12018-08-30 19:41:59 -07005574 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005575
5576 if(context)
5577 {
5578 context->setVertexAttrib(index, values);
5579 }
5580}
5581
5582void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
5583{
5584 TRACE("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
5585 "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = %p)",
5586 index, size, type, normalized, stride, ptr);
5587
5588 if(index >= es2::MAX_VERTEX_ATTRIBS)
5589 {
5590 return error(GL_INVALID_VALUE);
5591 }
5592
5593 if(size < 1 || size > 4)
5594 {
5595 return error(GL_INVALID_VALUE);
5596 }
5597
Nicolas Capens0bac2852016-05-07 06:09:58 -04005598 switch(type)
5599 {
5600 case GL_BYTE:
5601 case GL_UNSIGNED_BYTE:
5602 case GL_SHORT:
5603 case GL_UNSIGNED_SHORT:
5604 case GL_FIXED:
5605 case GL_FLOAT:
Nicolas Capens84d0e222017-08-03 12:53:47 -04005606 case GL_HALF_FLOAT_OES: // GL_OES_vertex_half_float
Nicolas Capensce8eb942018-04-26 16:38:05 -04005607 case GL_HALF_FLOAT:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005608 break;
5609 case GL_INT_2_10_10_10_REV:
5610 case GL_UNSIGNED_INT_2_10_10_10_REV:
Nicolas Capens83463112018-06-12 23:55:16 -04005611 if(size != 4)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005612 {
Nicolas Capens83463112018-06-12 23:55:16 -04005613 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005614 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04005615 case GL_INT:
5616 case GL_UNSIGNED_INT:
Nicolas Capens83463112018-06-12 23:55:16 -04005617 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005618 default:
5619 return error(GL_INVALID_ENUM);
5620 }
5621
5622 if(stride < 0)
5623 {
5624 return error(GL_INVALID_VALUE);
5625 }
5626
Chris Forbes108f3e12018-08-30 19:41:59 -07005627 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005628
5629 if(context)
5630 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05005631 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
5632 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && ptr)
5633 {
5634 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
5635 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
5636 return error(GL_INVALID_OPERATION);
5637 }
5638
Nicolas Capens51814272018-10-15 13:01:22 -04005639 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized != GL_FALSE), false, stride, ptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005640 }
5641}
5642
5643void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
5644{
5645 TRACE("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
5646
5647 if(width < 0 || height < 0)
5648 {
5649 return error(GL_INVALID_VALUE);
5650 }
5651
Chris Forbes108f3e12018-08-30 19:41:59 -07005652 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005653
5654 if(context)
5655 {
5656 context->setViewportParams(x, y, width, height);
5657 }
5658}
5659
Nicolas Capens805d7612018-08-02 13:56:32 -04005660static 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 -04005661{
5662 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
5663 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
5664 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
5665 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
5666
5667 switch(filter)
5668 {
5669 case GL_NEAREST:
5670 break;
5671 default:
5672 return error(GL_INVALID_ENUM);
5673 }
5674
5675 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
5676 {
5677 return error(GL_INVALID_VALUE);
5678 }
5679
Chris Forbes108f3e12018-08-30 19:41:59 -07005680 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005681
5682 if(context)
5683 {
5684 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
5685 {
5686 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
5687 return error(GL_INVALID_OPERATION);
5688 }
5689
Alexis Hetub9dda642016-10-06 11:25:32 -04005690 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, false, allowPartialDepthStencilBlit);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005691 }
5692}
5693
Alexis Hetub9dda642016-10-06 11:25:32 -04005694void BlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
5695{
Nicolas Capens805d7612018-08-02 13:56:32 -04005696 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, true);
Alexis Hetub9dda642016-10-06 11:25:32 -04005697}
5698
Nicolas Capens0bac2852016-05-07 06:09:58 -04005699void BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
5700 GLbitfield mask, GLenum filter)
5701{
5702 if(srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
5703 {
5704 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
5705 return error(GL_INVALID_OPERATION);
5706 }
5707
Nicolas Capens805d7612018-08-02 13:56:32 -04005708 BlitFramebufferSW(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, false);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005709}
5710
5711void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
Alexis Hetu53f48092016-06-17 14:08:06 -04005712 GLint border, GLenum format, GLenum type, const GLvoid* data)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005713{
5714 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
5715 "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005716 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5717 target, level, internalformat, width, height, depth, border, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005718
5719 switch(target)
5720 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005721 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005722 switch(format)
5723 {
5724 case GL_DEPTH_COMPONENT:
5725 case GL_DEPTH_STENCIL_OES:
5726 return error(GL_INVALID_OPERATION);
5727 default:
5728 break;
5729 }
5730 break;
5731 default:
5732 return error(GL_INVALID_ENUM);
5733 }
5734
Nicolas Capensc61f46b2017-12-04 16:07:22 -05005735 if(internalformat != format)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005736 {
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005737 return error(GL_INVALID_OPERATION);
5738 }
5739
Nicolas Capens83463112018-06-12 23:55:16 -04005740 GLenum validationError = ValidateTextureFormatType(format, type, internalformat, target);
Nicolas Capense65f5642018-02-26 17:47:06 -05005741 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005742 {
5743 return error(validationError);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005744 }
5745
5746 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5747 {
5748 return error(GL_INVALID_VALUE);
5749 }
5750
Nicolas Capensefdf1032018-05-08 16:03:16 -04005751 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005752 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D))
5753 {
5754 return error(GL_INVALID_VALUE);
5755 }
5756
5757 if(border != 0)
5758 {
5759 return error(GL_INVALID_VALUE);
5760 }
5761
Chris Forbes108f3e12018-08-30 19:41:59 -07005762 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005763
5764 if(context)
5765 {
5766 es2::Texture3D *texture = context->getTexture3D();
5767
5768 if(!texture)
5769 {
5770 return error(GL_INVALID_OPERATION);
5771 }
5772
Nicolas Capens2fc90512018-01-23 22:24:22 +00005773 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005774 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005775 {
5776 return error(validationError);
5777 }
5778
Nicolas Capens894858a2018-03-22 00:55:23 -04005779 GLint sizedInternalFormat = gl::GetSizedInternalFormat(internalformat, type);
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005780 texture->setImage(level, width, height, depth, sizedInternalFormat, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005781 }
5782}
5783
Alexis Hetu53f48092016-06-17 14:08:06 -04005784void 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 -04005785{
5786 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5787 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
Alexis Hetu53f48092016-06-17 14:08:06 -04005788 "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* data = %p)",
5789 target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005790
5791 switch(target)
5792 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005793 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005794 break;
5795 default:
5796 return error(GL_INVALID_ENUM);
5797 }
5798
Nicolas Capens0bac2852016-05-07 06:09:58 -04005799 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5800 {
5801 return error(GL_INVALID_VALUE);
5802 }
5803
5804 if((width < 0) || (height < 0) || (depth < 0))
5805 {
5806 return error(GL_INVALID_VALUE);
5807 }
5808
Chris Forbes108f3e12018-08-30 19:41:59 -07005809 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005810
5811 if(context)
5812 {
5813 es2::Texture3D *texture = context->getTexture3D();
5814
Nicolas Capens83463112018-06-12 23:55:16 -04005815 GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture);
Nicolas Capense65f5642018-02-26 17:47:06 -05005816 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005817 {
5818 return error(validationError);
5819 }
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005820
Nicolas Capens5555af42017-12-14 13:14:03 -05005821 validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, format, type));
Nicolas Capense65f5642018-02-26 17:47:06 -05005822 if(validationError != GL_NO_ERROR)
Nicolas Capensd2faaa92017-12-04 11:15:51 -05005823 {
5824 return error(validationError);
5825 }
5826
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005827 texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackParameters(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005828 }
5829}
5830
5831void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
5832{
5833 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5834 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
5835 target, level, xoffset, yoffset, zoffset, x, y, width, height);
5836
5837 switch(target)
5838 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005839 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005840 break;
5841 default:
5842 return error(GL_INVALID_ENUM);
5843 }
5844
5845 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5846 {
5847 return error(GL_INVALID_VALUE);
5848 }
5849
Chris Forbes108f3e12018-08-30 19:41:59 -07005850 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005851
5852 if(context)
5853 {
5854 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
5855
Alexis Hetu5cd502b2018-03-22 08:29:31 -04005856 if(!framebuffer || (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005857 {
5858 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
5859 }
5860
5861 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
5862
5863 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
5864 {
5865 return error(GL_INVALID_OPERATION);
5866 }
5867
5868 es2::Texture3D *texture = context->getTexture3D();
5869
Nicolas Capens83463112018-06-12 23:55:16 -04005870 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 -05005871 if(validationError != GL_NO_ERROR)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005872 {
5873 return error(validationError);
5874 }
5875
Nicolas Capens1529c2c2018-02-06 14:44:47 -05005876 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005877 }
5878}
5879
5880void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
5881{
5882 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
5883 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
5884 target, level, internalformat, width, height, depth, border, imageSize, data);
5885
5886 switch(target)
5887 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005888 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005889 break;
5890 default:
5891 return error(GL_INVALID_ENUM);
5892 }
5893
5894 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
5895 {
5896 return error(GL_INVALID_VALUE);
5897 }
5898
Nicolas Capensefdf1032018-05-08 16:03:16 -04005899 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE >> level;
Nicolas Capens0bac2852016-05-07 06:09:58 -04005900 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) ||(border != 0) || (imageSize < 0))
5901 {
5902 return error(GL_INVALID_VALUE);
5903 }
5904
Nicolas Capens83463112018-06-12 23:55:16 -04005905 if(!IsCompressed(internalformat))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005906 {
Nicolas Capens03589982018-02-01 17:28:32 -05005907 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005908 }
5909
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005910 if(imageSize != gl::ComputeCompressedSize(width, height, internalformat) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005911 {
5912 return error(GL_INVALID_VALUE);
5913 }
5914
Chris Forbes108f3e12018-08-30 19:41:59 -07005915 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005916
5917 if(context)
5918 {
5919 es2::Texture3D *texture = context->getTexture3D();
5920
5921 if(!texture)
5922 {
5923 return error(GL_INVALID_OPERATION);
5924 }
5925
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005926 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005927
Nicolas Capense65f5642018-02-26 17:47:06 -05005928 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005929 {
5930 return error(validationError);
5931 }
5932
Nicolas Capens0bac2852016-05-07 06:09:58 -04005933 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
5934 }
5935}
5936
5937void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
5938{
5939 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
5940 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
5941 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
5942 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
5943
5944 switch(target)
5945 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05005946 case GL_TEXTURE_3D:
Nicolas Capens0bac2852016-05-07 06:09:58 -04005947 break;
5948 default:
5949 return error(GL_INVALID_ENUM);
5950 }
5951
5952 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5953 {
5954 return error(GL_INVALID_VALUE);
5955 }
5956
5957 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
5958 {
5959 return error(GL_INVALID_VALUE);
5960 }
5961
Nicolas Capens83463112018-06-12 23:55:16 -04005962 if(!IsCompressed(format))
Nicolas Capens0bac2852016-05-07 06:09:58 -04005963 {
Nicolas Capens03589982018-02-01 17:28:32 -05005964 return error(GL_INVALID_ENUM);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005965 }
5966
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005967 if(imageSize != gl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005968 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -05005969 return error(GL_INVALID_VALUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005970 }
5971
Chris Forbes108f3e12018-08-30 19:41:59 -07005972 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04005973
5974 if(context)
5975 {
5976 es2::Texture3D *texture = context->getTexture3D();
5977
5978 if(!texture)
5979 {
5980 return error(GL_INVALID_OPERATION);
5981 }
5982
Nicolas Capens3b4a25c2018-02-22 20:14:07 -05005983 GLenum validationError = context->getPixels(&data, GL_UNSIGNED_BYTE, imageSize);
Nicolas Capense65f5642018-02-26 17:47:06 -05005984 if(validationError != GL_NO_ERROR)
Alexis Hetuf97f6e02017-11-15 13:01:28 -05005985 {
5986 return error(validationError);
5987 }
5988
5989 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -04005990 }
5991}
5992
5993void FramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
5994{
5995 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
5996 "GLuint texture = %d, GLint level = %d, GLint zoffset = %d)", target, attachment, textarget, texture, level, zoffset);
5997
Nicolas Capens6c4564a2018-01-26 01:14:34 +00005998 if(target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER && target != GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04005999 {
6000 return error(GL_INVALID_ENUM);
6001 }
6002
Chris Forbes108f3e12018-08-30 19:41:59 -07006003 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006004
6005 if(context)
6006 {
6007 if(texture == 0)
6008 {
6009 textarget = GL_NONE;
6010 }
6011 else
6012 {
6013 es2::Texture *tex = context->getTexture(texture);
6014
6015 if(!tex)
6016 {
6017 return error(GL_INVALID_OPERATION);
6018 }
6019
Nicolas Capens0bac2852016-05-07 06:09:58 -04006020 switch(textarget)
6021 {
Nicolas Capensc4a3f242017-12-11 15:07:53 -05006022 case GL_TEXTURE_3D:
6023 if(tex->getTarget() != GL_TEXTURE_3D)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006024 {
6025 return error(GL_INVALID_OPERATION);
6026 }
6027 break;
6028 default:
6029 return error(GL_INVALID_ENUM);
6030 }
6031
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006032 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
Nicolas Capens0bac2852016-05-07 06:09:58 -04006033 {
6034 return error(GL_INVALID_VALUE);
6035 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006036
6037 if(tex->isCompressed(textarget, level))
6038 {
6039 return error(GL_INVALID_OPERATION);
6040 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04006041 }
6042
6043 es2::Framebuffer *framebuffer = nullptr;
6044 GLuint framebufferName = 0;
Nicolas Capens6c4564a2018-01-26 01:14:34 +00006045 if(target == GL_READ_FRAMEBUFFER)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006046 {
6047 framebuffer = context->getReadFramebuffer();
6048 framebufferName = context->getReadFramebufferName();
6049 }
6050 else
6051 {
6052 framebuffer = context->getDrawFramebuffer();
6053 framebufferName = context->getDrawFramebufferName();
6054 }
6055
6056 if(framebufferName == 0 || !framebuffer)
6057 {
6058 return error(GL_INVALID_OPERATION);
6059 }
6060
Nicolas Capens0bac2852016-05-07 06:09:58 -04006061 switch(attachment)
6062 {
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006063 case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level); break;
6064 case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;
Nicolas Capens83463112018-06-12 23:55:16 -04006065 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006066 if((attachment - GL_COLOR_ATTACHMENT0) >= MAX_COLOR_ATTACHMENTS)
6067 {
6068 return error(GL_INVALID_ENUM);
6069 }
Nicolas Capens0ccc71d2018-03-23 10:13:06 -04006070 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006071 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006072 }
6073 }
6074}
6075
6076void EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
6077{
6078 if(egl::getClientVersion() == 1)
6079 {
6080 return libGLES_CM->glEGLImageTargetTexture2DOES(target, image);
6081 }
6082
6083 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6084
6085 switch(target)
6086 {
6087 case GL_TEXTURE_2D:
Alexis Hetu46768622018-01-16 22:09:28 -05006088 case GL_TEXTURE_RECTANGLE_ARB:
Nicolas Capens0bac2852016-05-07 06:09:58 -04006089 case GL_TEXTURE_EXTERNAL_OES:
6090 break;
6091 default:
6092 return error(GL_INVALID_ENUM);
6093 }
6094
Chris Forbes108f3e12018-08-30 19:41:59 -07006095 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006096
6097 if(context)
6098 {
Alexis Hetu46768622018-01-16 22:09:28 -05006099 es2::Texture2D *texture = context->getTexture2D(target);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006100
6101 if(!texture)
6102 {
6103 return error(GL_INVALID_OPERATION);
6104 }
6105
Nicolas Capens58df2f62016-06-07 14:48:56 -04006106 egl::Image *eglImage = context->getSharedImage(image);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006107
Nicolas Capens58df2f62016-06-07 14:48:56 -04006108 if(!eglImage)
6109 {
6110 return error(GL_INVALID_OPERATION);
6111 }
6112
6113 texture->setSharedImage(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04006114 }
6115}
6116
6117void EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
6118{
6119 TRACE("(GLenum target = 0x%X, GLeglImageOES image = %p)", target, image);
6120
6121 UNIMPLEMENTED();
6122}
6123
6124GLboolean IsRenderbufferOES(GLuint renderbuffer)
6125{
6126 return IsRenderbuffer(renderbuffer);
6127}
6128
6129void BindRenderbufferOES(GLenum target, GLuint renderbuffer)
6130{
6131 BindRenderbuffer(target, renderbuffer);
6132}
6133
6134void DeleteRenderbuffersOES(GLsizei n, const GLuint* renderbuffers)
6135{
6136 DeleteRenderbuffers(n, renderbuffers);
6137}
6138
6139void GenRenderbuffersOES(GLsizei n, GLuint* renderbuffers)
6140{
6141 GenRenderbuffers(n, renderbuffers);
6142}
6143
6144void RenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
6145{
6146 RenderbufferStorage(target, internalformat, width, height);
6147}
6148
6149void GetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint* params)
6150{
6151 GetRenderbufferParameteriv(target, pname, params);
6152}
6153
6154GLboolean IsFramebufferOES(GLuint framebuffer)
6155{
6156 return IsFramebuffer(framebuffer);
6157}
6158
6159void BindFramebufferOES(GLenum target, GLuint framebuffer)
6160{
6161 BindFramebuffer(target, framebuffer);
6162}
6163
6164void DeleteFramebuffersOES(GLsizei n, const GLuint* framebuffers)
6165{
6166 DeleteFramebuffers(n, framebuffers);
6167}
6168
6169void GenFramebuffersOES(GLsizei n, GLuint* framebuffers)
6170{
6171 GenFramebuffers(n, framebuffers);
6172}
6173
6174GLenum CheckFramebufferStatusOES(GLenum target)
6175{
6176 return CheckFramebufferStatus(target);
6177}
6178
6179void FramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
6180{
6181 FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
6182}
6183
6184void FramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
6185{
6186 FramebufferTexture2D(target, attachment, textarget, texture, level);
6187}
6188
6189void GetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint* params)
6190{
6191 GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
6192}
6193
6194void GenerateMipmapOES(GLenum target)
6195{
6196 GenerateMipmap(target);
6197}
6198
6199void DrawBuffersEXT(GLsizei n, const GLenum *bufs)
6200{
6201 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
6202
6203 if(n < 0 || n > MAX_DRAW_BUFFERS)
6204 {
6205 return error(GL_INVALID_VALUE);
6206 }
6207
Chris Forbes108f3e12018-08-30 19:41:59 -07006208 auto context = es2::getContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04006209
6210 if(context)
6211 {
6212 GLuint drawFramebufferName = context->getDrawFramebufferName();
6213
6214 if((drawFramebufferName == 0) && (n != 1))
6215 {
6216 return error(GL_INVALID_OPERATION);
6217 }
6218
6219 for(unsigned int i = 0; i < (unsigned)n; i++)
6220 {
6221 switch(bufs[i])
6222 {
6223 case GL_BACK:
6224 if(drawFramebufferName != 0)
6225 {
6226 return error(GL_INVALID_OPERATION);
6227 }
6228 break;
6229 case GL_NONE:
6230 break;
6231 case GL_COLOR_ATTACHMENT0_EXT:
6232 case GL_COLOR_ATTACHMENT1_EXT:
6233 case GL_COLOR_ATTACHMENT2_EXT:
6234 case GL_COLOR_ATTACHMENT3_EXT:
6235 case GL_COLOR_ATTACHMENT4_EXT:
6236 case GL_COLOR_ATTACHMENT5_EXT:
6237 case GL_COLOR_ATTACHMENT6_EXT:
6238 case GL_COLOR_ATTACHMENT7_EXT:
6239 case GL_COLOR_ATTACHMENT8_EXT:
6240 case GL_COLOR_ATTACHMENT9_EXT:
6241 case GL_COLOR_ATTACHMENT10_EXT:
6242 case GL_COLOR_ATTACHMENT11_EXT:
6243 case GL_COLOR_ATTACHMENT12_EXT:
6244 case GL_COLOR_ATTACHMENT13_EXT:
6245 case GL_COLOR_ATTACHMENT14_EXT:
6246 case GL_COLOR_ATTACHMENT15_EXT:
6247 {
6248 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0_EXT);
6249
6250 if(index >= MAX_COLOR_ATTACHMENTS)
6251 {
6252 return error(GL_INVALID_OPERATION);
6253 }
6254
6255 if(index != i)
6256 {
6257 return error(GL_INVALID_OPERATION);
6258 }
6259
6260 if(drawFramebufferName == 0)
6261 {
6262 return error(GL_INVALID_OPERATION);
6263 }
6264 }
6265 break;
6266 default:
6267 return error(GL_INVALID_ENUM);
6268 }
6269 }
6270
6271 context->setFramebufferDrawBuffers(n, bufs);
6272 }
6273}
6274
6275}
6276
Nicolas Capens805d7612018-08-02 13:56:32 -04006277#include "entry_points.h"
6278
Nicolas Capens506cc5e2017-07-24 11:30:55 -04006279extern "C" NO_SANITIZE_FUNCTION __eglMustCastToProperFunctionPointerType es2GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006280{
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006281 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04006282 {
6283 const char *name;
6284 __eglMustCastToProperFunctionPointerType address;
6285 };
6286
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006287 static const Function glFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04006288 {
Nicolas Capens805d7612018-08-02 13:56:32 -04006289 #define FUNCTION(name) {"gl" #name, (__eglMustCastToProperFunctionPointerType)gl::name}
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006290
Nicolas Capens805d7612018-08-02 13:56:32 -04006291 FUNCTION(ActiveTexture),
6292 FUNCTION(AttachShader),
6293 FUNCTION(BeginQuery),
6294 FUNCTION(BeginQueryEXT),
6295 FUNCTION(BeginTransformFeedback),
6296 FUNCTION(BindAttribLocation),
6297 FUNCTION(BindBuffer),
6298 FUNCTION(BindBufferBase),
6299 FUNCTION(BindBufferRange),
6300 FUNCTION(BindFramebuffer),
6301 FUNCTION(BindFramebufferOES),
6302 FUNCTION(BindRenderbuffer),
6303 FUNCTION(BindRenderbufferOES),
6304 FUNCTION(BindSampler),
6305 FUNCTION(BindTexture),
6306 FUNCTION(BindTransformFeedback),
6307 FUNCTION(BindVertexArray),
6308 FUNCTION(BindVertexArrayOES),
6309 FUNCTION(BlendColor),
6310 FUNCTION(BlendEquation),
6311 FUNCTION(BlendEquationSeparate),
6312 FUNCTION(BlendFunc),
6313 FUNCTION(BlendFuncSeparate),
6314 FUNCTION(BlitFramebuffer),
6315 FUNCTION(BlitFramebufferANGLE),
6316 FUNCTION(BufferData),
6317 FUNCTION(BufferSubData),
6318 FUNCTION(CheckFramebufferStatus),
6319 FUNCTION(CheckFramebufferStatusOES),
6320 FUNCTION(Clear),
6321 FUNCTION(ClearBufferfi),
6322 FUNCTION(ClearBufferfv),
6323 FUNCTION(ClearBufferiv),
6324 FUNCTION(ClearBufferuiv),
6325 FUNCTION(ClearColor),
6326 FUNCTION(ClearDepthf),
6327 FUNCTION(ClearStencil),
6328 FUNCTION(ClientWaitSync),
6329 FUNCTION(ColorMask),
6330 FUNCTION(CompileShader),
6331 FUNCTION(CompressedTexImage2D),
6332 FUNCTION(CompressedTexImage3D),
6333 FUNCTION(CompressedTexSubImage2D),
6334 FUNCTION(CompressedTexSubImage3D),
6335 FUNCTION(CopyBufferSubData),
6336 FUNCTION(CopyTexImage2D),
6337 FUNCTION(CopyTexSubImage2D),
6338 FUNCTION(CopyTexSubImage3D),
6339 FUNCTION(CreateProgram),
6340 FUNCTION(CreateShader),
6341 FUNCTION(CullFace),
6342 FUNCTION(DeleteBuffers),
6343 FUNCTION(DeleteFencesNV),
6344 FUNCTION(DeleteFramebuffers),
6345 FUNCTION(DeleteFramebuffersOES),
6346 FUNCTION(DeleteProgram),
6347 FUNCTION(DeleteQueries),
6348 FUNCTION(DeleteQueriesEXT),
6349 FUNCTION(DeleteRenderbuffers),
6350 FUNCTION(DeleteRenderbuffersOES),
6351 FUNCTION(DeleteSamplers),
6352 FUNCTION(DeleteShader),
6353 FUNCTION(DeleteSync),
6354 FUNCTION(DeleteTextures),
6355 FUNCTION(DeleteTransformFeedbacks),
6356 FUNCTION(DeleteVertexArrays),
6357 FUNCTION(DeleteVertexArraysOES),
6358 FUNCTION(DepthFunc),
6359 FUNCTION(DepthMask),
6360 FUNCTION(DepthRangef),
6361 FUNCTION(DetachShader),
6362 FUNCTION(Disable),
6363 FUNCTION(DisableVertexAttribArray),
6364 FUNCTION(DrawArrays),
6365 FUNCTION(DrawArraysInstanced),
6366 FUNCTION(DrawBuffers),
6367 FUNCTION(DrawBuffersEXT),
6368 FUNCTION(DrawElements),
6369 FUNCTION(DrawElementsInstanced),
6370 FUNCTION(DrawRangeElements),
6371 FUNCTION(EGLImageTargetRenderbufferStorageOES),
6372 FUNCTION(EGLImageTargetTexture2DOES),
6373 FUNCTION(Enable),
6374 FUNCTION(EnableVertexAttribArray),
6375 FUNCTION(EndQuery),
6376 FUNCTION(EndQueryEXT),
6377 FUNCTION(EndTransformFeedback),
6378 FUNCTION(FenceSync),
6379 FUNCTION(Finish),
6380 FUNCTION(FinishFenceNV),
6381 FUNCTION(Flush),
6382 FUNCTION(FlushMappedBufferRange),
6383 FUNCTION(FramebufferRenderbuffer),
6384 FUNCTION(FramebufferRenderbufferOES),
6385 FUNCTION(FramebufferTexture2D),
6386 FUNCTION(FramebufferTexture2DOES),
6387 FUNCTION(FramebufferTextureLayer),
6388 FUNCTION(FrontFace),
6389 FUNCTION(GenBuffers),
6390 FUNCTION(GenFencesNV),
6391 FUNCTION(GenFramebuffers),
6392 FUNCTION(GenFramebuffersOES),
6393 FUNCTION(GenQueries),
6394 FUNCTION(GenQueriesEXT),
6395 FUNCTION(GenRenderbuffers),
6396 FUNCTION(GenRenderbuffersOES),
6397 FUNCTION(GenSamplers),
6398 FUNCTION(GenTextures),
6399 FUNCTION(GenTransformFeedbacks),
6400 FUNCTION(GenVertexArrays),
6401 FUNCTION(GenVertexArraysOES),
6402 FUNCTION(GenerateMipmap),
6403 FUNCTION(GenerateMipmapOES),
6404 FUNCTION(GetActiveAttrib),
6405 FUNCTION(GetActiveUniform),
6406 FUNCTION(GetActiveUniformBlockName),
6407 FUNCTION(GetActiveUniformBlockiv),
6408 FUNCTION(GetActiveUniformsiv),
6409 FUNCTION(GetAttachedShaders),
6410 FUNCTION(GetAttribLocation),
6411 FUNCTION(GetBooleanv),
6412 FUNCTION(GetBufferParameteri64v),
6413 FUNCTION(GetBufferParameteriv),
6414 FUNCTION(GetBufferPointerv),
6415 FUNCTION(GetError),
6416 FUNCTION(GetFenceivNV),
6417 FUNCTION(GetFloatv),
6418 FUNCTION(GetFragDataLocation),
6419 FUNCTION(GetFramebufferAttachmentParameteriv),
6420 FUNCTION(GetFramebufferAttachmentParameterivOES),
6421 FUNCTION(GetGraphicsResetStatusEXT),
6422 FUNCTION(GetInteger64i_v),
6423 FUNCTION(GetInteger64v),
6424 FUNCTION(GetIntegeri_v),
6425 FUNCTION(GetIntegerv),
6426 FUNCTION(GetInternalformativ),
6427 FUNCTION(GetProgramBinary),
6428 FUNCTION(GetProgramInfoLog),
6429 FUNCTION(GetProgramiv),
6430 FUNCTION(GetQueryObjectuiv),
6431 FUNCTION(GetQueryObjectuivEXT),
6432 FUNCTION(GetQueryiv),
6433 FUNCTION(GetQueryivEXT),
6434 FUNCTION(GetRenderbufferParameteriv),
6435 FUNCTION(GetRenderbufferParameterivOES),
6436 FUNCTION(GetSamplerParameterfv),
6437 FUNCTION(GetSamplerParameteriv),
6438 FUNCTION(GetShaderInfoLog),
6439 FUNCTION(GetShaderPrecisionFormat),
6440 FUNCTION(GetShaderSource),
6441 FUNCTION(GetShaderiv),
6442 FUNCTION(GetString),
6443 FUNCTION(GetStringi),
6444 FUNCTION(GetSynciv),
6445 FUNCTION(GetTexParameterfv),
6446 FUNCTION(GetTexParameteriv),
6447 FUNCTION(GetTransformFeedbackVarying),
6448 FUNCTION(GetUniformBlockIndex),
6449 FUNCTION(GetUniformIndices),
6450 FUNCTION(GetUniformLocation),
6451 FUNCTION(GetUniformfv),
6452 FUNCTION(GetUniformiv),
6453 FUNCTION(GetUniformuiv),
6454 FUNCTION(GetVertexAttribIiv),
6455 FUNCTION(GetVertexAttribIuiv),
6456 FUNCTION(GetVertexAttribPointerv),
6457 FUNCTION(GetVertexAttribfv),
6458 FUNCTION(GetVertexAttribiv),
6459 FUNCTION(GetnUniformfvEXT),
6460 FUNCTION(GetnUniformivEXT),
6461 FUNCTION(Hint),
6462 FUNCTION(InvalidateFramebuffer),
6463 FUNCTION(InvalidateSubFramebuffer),
6464 FUNCTION(IsBuffer),
6465 FUNCTION(IsEnabled),
6466 FUNCTION(IsFenceNV),
6467 FUNCTION(IsFramebuffer),
6468 FUNCTION(IsFramebufferOES),
6469 FUNCTION(IsProgram),
6470 FUNCTION(IsQuery),
6471 FUNCTION(IsQueryEXT),
6472 FUNCTION(IsRenderbuffer),
6473 FUNCTION(IsRenderbufferOES),
6474 FUNCTION(IsSampler),
6475 FUNCTION(IsShader),
6476 FUNCTION(IsSync),
6477 FUNCTION(IsTexture),
6478 FUNCTION(IsTransformFeedback),
6479 FUNCTION(IsVertexArray),
6480 FUNCTION(IsVertexArrayOES),
6481 FUNCTION(LineWidth),
6482 FUNCTION(LinkProgram),
6483 FUNCTION(MapBufferRange),
6484 FUNCTION(PauseTransformFeedback),
6485 FUNCTION(PixelStorei),
6486 FUNCTION(PolygonOffset),
6487 FUNCTION(ProgramBinary),
6488 FUNCTION(ProgramParameteri),
6489 FUNCTION(ReadBuffer),
6490 FUNCTION(ReadPixels),
6491 FUNCTION(ReadnPixelsEXT),
6492 FUNCTION(ReleaseShaderCompiler),
6493 FUNCTION(RenderbufferStorage),
6494 FUNCTION(RenderbufferStorageMultisample),
6495 FUNCTION(RenderbufferStorageMultisampleANGLE),
6496 FUNCTION(RenderbufferStorageOES),
6497 FUNCTION(ResumeTransformFeedback),
6498 FUNCTION(SampleCoverage),
6499 FUNCTION(SamplerParameterf),
6500 FUNCTION(SamplerParameterfv),
6501 FUNCTION(SamplerParameteri),
6502 FUNCTION(SamplerParameteriv),
6503 FUNCTION(Scissor),
6504 FUNCTION(SetFenceNV),
6505 FUNCTION(ShaderBinary),
6506 FUNCTION(ShaderSource),
6507 FUNCTION(StencilFunc),
6508 FUNCTION(StencilFuncSeparate),
6509 FUNCTION(StencilMask),
6510 FUNCTION(StencilMaskSeparate),
6511 FUNCTION(StencilOp),
6512 FUNCTION(StencilOpSeparate),
6513 FUNCTION(TestFenceNV),
6514 FUNCTION(TexImage2D),
6515 FUNCTION(TexImage3D),
6516 FUNCTION(TexImage3DOES),
6517 FUNCTION(TexParameterf),
6518 FUNCTION(TexParameterfv),
6519 FUNCTION(TexParameteri),
6520 FUNCTION(TexParameteriv),
6521 FUNCTION(TexStorage2D),
6522 FUNCTION(TexStorage3D),
6523 FUNCTION(TexSubImage2D),
6524 FUNCTION(TexSubImage3D),
6525 FUNCTION(TransformFeedbackVaryings),
6526 FUNCTION(Uniform1f),
6527 FUNCTION(Uniform1fv),
6528 FUNCTION(Uniform1i),
6529 FUNCTION(Uniform1iv),
6530 FUNCTION(Uniform1ui),
6531 FUNCTION(Uniform1uiv),
6532 FUNCTION(Uniform2f),
6533 FUNCTION(Uniform2fv),
6534 FUNCTION(Uniform2i),
6535 FUNCTION(Uniform2iv),
6536 FUNCTION(Uniform2ui),
6537 FUNCTION(Uniform2uiv),
6538 FUNCTION(Uniform3f),
6539 FUNCTION(Uniform3fv),
6540 FUNCTION(Uniform3i),
6541 FUNCTION(Uniform3iv),
6542 FUNCTION(Uniform3ui),
6543 FUNCTION(Uniform3uiv),
6544 FUNCTION(Uniform4f),
6545 FUNCTION(Uniform4fv),
6546 FUNCTION(Uniform4i),
6547 FUNCTION(Uniform4iv),
6548 FUNCTION(Uniform4ui),
6549 FUNCTION(Uniform4uiv),
6550 FUNCTION(UniformBlockBinding),
6551 FUNCTION(UniformMatrix2fv),
6552 FUNCTION(UniformMatrix2x3fv),
6553 FUNCTION(UniformMatrix2x4fv),
6554 FUNCTION(UniformMatrix3fv),
6555 FUNCTION(UniformMatrix3x2fv),
6556 FUNCTION(UniformMatrix3x4fv),
6557 FUNCTION(UniformMatrix4fv),
6558 FUNCTION(UniformMatrix4x2fv),
6559 FUNCTION(UniformMatrix4x3fv),
6560 FUNCTION(UnmapBuffer),
6561 FUNCTION(UseProgram),
6562 FUNCTION(ValidateProgram),
6563 FUNCTION(VertexAttrib1f),
6564 FUNCTION(VertexAttrib1fv),
6565 FUNCTION(VertexAttrib2f),
6566 FUNCTION(VertexAttrib2fv),
6567 FUNCTION(VertexAttrib3f),
6568 FUNCTION(VertexAttrib3fv),
6569 FUNCTION(VertexAttrib4f),
6570 FUNCTION(VertexAttrib4fv),
6571 FUNCTION(VertexAttribDivisor),
6572 FUNCTION(VertexAttribDivisorANGLE),
6573 FUNCTION(VertexAttribDivisorEXT),
6574 FUNCTION(VertexAttribI4i),
6575 FUNCTION(VertexAttribI4iv),
6576 FUNCTION(VertexAttribI4ui),
6577 FUNCTION(VertexAttribI4uiv),
6578 FUNCTION(VertexAttribIPointer),
6579 FUNCTION(VertexAttribPointer),
6580 FUNCTION(Viewport),
6581 FUNCTION(WaitSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006582
6583 #undef FUNCTION
6584 };
6585
6586 static const size_t numFunctions = sizeof glFunctions / sizeof(Function);
6587 static const Function *const glFunctionsEnd = glFunctions + numFunctions;
6588
Nicolas Capens48908cb2018-01-08 13:07:14 -05006589 // The array must be kept sorted with respect to strcmp(), so that binary search works correctly.
6590 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
6591 #ifndef NDEBUG
6592 for(size_t i = 0; i < numFunctions - 1; i++)
6593 {
6594 ASSERT(strcmp(glFunctions[i].name, glFunctions[i + 1].name) < 0);
6595 }
6596 #endif
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006597
6598 if(procname && strncmp("gl", procname, 2) == 0)
6599 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05006600 struct CompareFunctor
6601 {
6602 bool operator()(const Function &a, const Function &b) const
6603 {
6604 return strcmp(a.name, b.name) < 0;
6605 }
6606 };
6607
6608 Function needle;
6609 needle.name = procname;
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006610 const Function *result = std::lower_bound(glFunctions, glFunctionsEnd, needle, CompareFunctor());
Nicolas Capens48908cb2018-01-08 13:07:14 -05006611
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006612 if(result != glFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04006613 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01006614 return (__eglMustCastToProperFunctionPointerType)result->address;
Nicolas Capens0bac2852016-05-07 06:09:58 -04006615 }
6616 }
6617
6618 return nullptr;
6619}