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