blob: aae97829ef31f47912e72a31fb93d334637f493a [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
689 texture->setImage(context, level, width, height, depth, sizedInternalFormat, 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
732 GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
733 if(validationError == GL_NONE)
734 {
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500735 GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500736 if(validationError != GL_NONE)
737 {
738 return error(validationError);
739 }
740
741 texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400742 }
743 else
744 {
745 return error(validationError);
746 }
747 }
748}
749
750GL_APICALL void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
751{
752 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
753 "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
754 target, level, xoffset, yoffset, zoffset, x, y, width, height);
755
756 switch(target)
757 {
758 case GL_TEXTURE_3D:
759 case GL_TEXTURE_2D_ARRAY:
760 break;
761 default:
762 return error(GL_INVALID_ENUM);
763 }
764
765 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
766 {
767 return error(GL_INVALID_VALUE);
768 }
769
770 if((width < 0) || (height < 0) || (xoffset < 0) || (yoffset < 0) || (zoffset < 0))
771 {
772 return error(GL_INVALID_VALUE);
773 }
774
775 es2::Context *context = es2::getContext();
776
777 if(context)
778 {
779 es2::Framebuffer *framebuffer = context->getReadFramebuffer();
780
781 if(framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
782 {
783 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
784 }
785
786 es2::Renderbuffer *source = framebuffer->getReadColorbuffer();
787
788 if(context->getReadFramebufferName() != 0 && (!source || source->getSamples() > 1))
789 {
790 return error(GL_INVALID_OPERATION);
791 }
792
793 GLenum colorbufferFormat = source->getFormat();
794 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray();
795
796 GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
797 if(validationError != GL_NONE)
798 {
799 return error(validationError);
800 }
801
802 GLenum textureFormat = texture->getFormat(target, level);
803
804 if(!validateColorBufferFormat(textureFormat, colorbufferFormat))
805 {
806 return;
807 }
808
809 texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
810 }
811}
812
813GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
814{
815 TRACE("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
816 "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = %p)",
817 target, level, internalformat, width, height, depth, border, imageSize, data);
818
819 switch(target)
820 {
821 case GL_TEXTURE_3D:
822 case GL_TEXTURE_2D_ARRAY:
823 break;
824 default:
825 return error(GL_INVALID_ENUM);
826 }
827
828 if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
829 {
830 return error(GL_INVALID_VALUE);
831 }
832
833 const GLsizei maxSize3D = es2::IMPLEMENTATION_MAX_TEXTURE_SIZE >> level;
834 if((width < 0) || (height < 0) || (depth < 0) || (width > maxSize3D) || (height > maxSize3D) || (depth > maxSize3D) || (border != 0) || (imageSize < 0))
835 {
836 return error(GL_INVALID_VALUE);
837 }
838
839 switch(internalformat)
840 {
841 case GL_DEPTH_COMPONENT:
842 case GL_DEPTH_COMPONENT16:
843 case GL_DEPTH_COMPONENT32_OES:
844 case GL_DEPTH_STENCIL:
845 case GL_DEPTH24_STENCIL8:
846 return error(GL_INVALID_OPERATION);
847 default:
848 {
849 GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
850 if(validationError != GL_NONE)
851 {
852 return error(validationError);
853 }
854 }
855 }
856
857 if(imageSize != egl::ComputeCompressedSize(width, height, internalformat) * depth)
858 {
859 return error(GL_INVALID_VALUE);
860 }
861
862 es2::Context *context = es2::getContext();
863
864 if(context)
865 {
866 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray();
867
868 if(!texture)
869 {
870 return error(GL_INVALID_OPERATION);
871 }
872
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500873 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500874 if(validationError != GL_NONE)
875 {
876 return error(validationError);
877 }
878
Nicolas Capens0bac2852016-05-07 06:09:58 -0400879 texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data);
880 }
881}
882
883GL_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)
884{
885 TRACE("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
886 "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
887 "GLenum format = 0x%X, GLsizei imageSize = %d, const void *data = %p)",
888 target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
889
890 switch(target)
891 {
892 case GL_TEXTURE_3D:
893 case GL_TEXTURE_2D_ARRAY:
894 break;
895 default:
896 return error(GL_INVALID_ENUM);
897 }
898
899 if(level < 0 || level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
900 {
901 return error(GL_INVALID_VALUE);
902 }
903
904 if(xoffset < 0 || yoffset < 0 || zoffset < 0 || !validImageSize(level, width, height) || depth < 0 || imageSize < 0)
905 {
906 return error(GL_INVALID_VALUE);
907 }
908
909 GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
910 if(validationError != GL_NONE)
911 {
912 return error(validationError);
913 }
914
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500915 if(imageSize != egl::ComputeCompressedSize(width, height, format) * depth)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400916 {
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500917 return error(GL_INVALID_VALUE);
918 }
919
920 bool is_ETC2_EAC = false;
921 switch(format)
922 {
923 case GL_COMPRESSED_R11_EAC:
924 case GL_COMPRESSED_SIGNED_R11_EAC:
925 case GL_COMPRESSED_RG11_EAC:
926 case GL_COMPRESSED_SIGNED_RG11_EAC:
927 case GL_COMPRESSED_RGB8_ETC2:
928 case GL_COMPRESSED_SRGB8_ETC2:
929 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
930 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
931 case GL_COMPRESSED_RGBA8_ETC2_EAC:
932 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
933 if(target != GL_TEXTURE_2D_ARRAY)
934 {
935 return error(GL_INVALID_OPERATION);
936 }
937
938 if(((width % 4) != 0) || ((height % 4) != 0) ||
939 ((xoffset % 4) != 0) || ((yoffset % 4) != 0))
940 {
941 return error(GL_INVALID_OPERATION);
942 }
943
944 is_ETC2_EAC = true;
945 break;
946 default:
947 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400948 }
949
950 es2::Context *context = es2::getContext();
951
952 if(context)
953 {
954 es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray();
955
956 if(!texture)
957 {
958 return error(GL_INVALID_OPERATION);
959 }
960
Alexis Hetu848aa7f2017-11-17 13:15:32 -0500961 GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500962 if(validationError != GL_NONE)
963 {
964 return error(validationError);
965 }
966
Alexis Hetubbb8fc12017-11-21 12:39:41 -0500967 if(is_ETC2_EAC)
968 {
969 if(((width + xoffset) != texture->getWidth(target, level)) ||
970 ((height + yoffset) != texture->getHeight(target, level)))
971 {
972 return error(GL_INVALID_OPERATION);
973 }
974 }
975
Alexis Hetuf97f6e02017-11-15 13:01:28 -0500976 texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400977 }
978}
979
980GL_APICALL void GL_APIENTRY glGenQueries(GLsizei n, GLuint *ids)
981{
982 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
983
984 if(n < 0)
985 {
986 return error(GL_INVALID_VALUE);
987 }
988
989 es2::Context *context = es2::getContext();
990
991 if(context)
992 {
993 for(int i = 0; i < n; i++)
994 {
995 ids[i] = context->createQuery();
996 }
997 }
998}
999
1000GL_APICALL void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint *ids)
1001{
1002 TRACE("(GLsizei n = %d, GLuint* ids = %p)", n, ids);
1003
1004 if(n < 0)
1005 {
1006 return error(GL_INVALID_VALUE);
1007 }
1008
1009 es2::Context *context = es2::getContext();
1010
1011 if(context)
1012 {
1013 for(int i = 0; i < n; i++)
1014 {
1015 context->deleteQuery(ids[i]);
1016 }
1017 }
1018}
1019
1020GL_APICALL GLboolean GL_APIENTRY glIsQuery(GLuint id)
1021{
1022 TRACE("(GLuint id = %d)", id);
1023
1024 if(id == 0)
1025 {
1026 return GL_FALSE;
1027 }
1028
1029 es2::Context *context = es2::getContext();
1030
1031 if(context)
1032 {
1033 es2::Query *queryObject = context->getQuery(id);
1034
1035 if(queryObject)
1036 {
1037 return GL_TRUE;
1038 }
1039 }
1040
1041 return GL_FALSE;
1042}
1043
1044GL_APICALL void GL_APIENTRY glBeginQuery(GLenum target, GLuint id)
1045{
1046 TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);
1047
1048 if(!ValidateQueryTarget(target))
1049 {
1050 return error(GL_INVALID_ENUM);
1051 }
1052
1053 if(id == 0)
1054 {
1055 return error(GL_INVALID_OPERATION);
1056 }
1057
1058 es2::Context *context = es2::getContext();
1059
1060 if(context)
1061 {
1062 context->beginQuery(target, id);
1063 }
1064}
1065
1066GL_APICALL void GL_APIENTRY glEndQuery(GLenum target)
1067{
1068 TRACE("(GLenum target = 0x%X)", target);
1069
1070 if(!ValidateQueryTarget(target))
1071 {
1072 return error(GL_INVALID_ENUM);
1073 }
1074
1075 es2::Context *context = es2::getContext();
1076
1077 if(context)
1078 {
1079 context->endQuery(target);
1080 }
1081}
1082
1083GL_APICALL void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint *params)
1084{
1085 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)",
1086 target, pname, params);
1087
1088 if(!ValidateQueryTarget(target) || (pname != GL_CURRENT_QUERY))
1089 {
1090 return error(GL_INVALID_ENUM);
1091 }
1092
1093 es2::Context *context = es2::getContext();
1094
1095 if(context)
1096 {
1097 params[0] = context->getActiveQuery(target);
1098 }
1099}
1100
1101GL_APICALL void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
1102{
1103 TRACE("(GLuint id = %d, GLenum pname = 0x%X, GLint *params = %p)",
1104 id, pname, params);
1105
1106 switch(pname)
1107 {
1108 case GL_QUERY_RESULT:
1109 case GL_QUERY_RESULT_AVAILABLE:
1110 break;
1111 default:
1112 return error(GL_INVALID_ENUM);
1113 }
1114
1115 es2::Context *context = es2::getContext();
1116
1117 if(context)
1118 {
1119 es2::Query *queryObject = context->getQuery(id);
1120
1121 if(!queryObject)
1122 {
1123 return error(GL_INVALID_OPERATION);
1124 }
1125
1126 if(context->getActiveQuery(queryObject->getType()) == id)
1127 {
1128 return error(GL_INVALID_OPERATION);
1129 }
1130
1131 switch(pname)
1132 {
1133 case GL_QUERY_RESULT:
1134 params[0] = queryObject->getResult();
1135 break;
1136 case GL_QUERY_RESULT_AVAILABLE:
1137 params[0] = queryObject->isResultAvailable();
1138 break;
1139 default:
1140 ASSERT(false);
1141 }
1142 }
1143}
1144
1145GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
1146{
1147 TRACE("(GLenum target = 0x%X)", target);
1148
1149 es2::Context *context = es2::getContext();
1150
1151 if(context)
1152 {
1153 es2::Buffer *buffer = nullptr;
1154 if(!context->getBuffer(target, &buffer))
1155 {
1156 return error(GL_INVALID_ENUM, GL_TRUE);
1157 }
1158
1159 if(!buffer)
1160 {
1161 // A null buffer means that "0" is bound to the requested buffer target
1162 return error(GL_INVALID_OPERATION, GL_TRUE);
1163 }
1164
Alexis Hetu6e864492017-11-14 15:27:00 -05001165 if(!buffer->isMapped())
1166 {
1167 // Already unmapped
1168 return error(GL_INVALID_OPERATION, GL_TRUE);
1169 }
1170
Nicolas Capens0bac2852016-05-07 06:09:58 -04001171 return buffer->unmap() ? GL_TRUE : GL_FALSE;
1172 }
1173
1174 return GL_TRUE;
1175}
1176
1177GL_APICALL void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params)
1178{
1179 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = %p)",
1180 target, pname, params);
1181
1182 if(pname != GL_BUFFER_MAP_POINTER)
1183 {
1184 return error(GL_INVALID_ENUM);
1185 }
1186
1187 es2::Context *context = es2::getContext();
1188
1189 if(context)
1190 {
1191 es2::Buffer *buffer = nullptr;
1192 if(!context->getBuffer(target, &buffer))
1193 {
1194 return error(GL_INVALID_ENUM);
1195 }
1196
1197 if(!buffer)
1198 {
1199 // A null buffer means that "0" is bound to the requested buffer target
1200 return error(GL_INVALID_OPERATION);
1201 }
1202
1203 *params = buffer->isMapped() ? (void*)(((const char*)buffer->data()) + buffer->offset()) : nullptr;
1204 }
1205}
1206
1207GL_APICALL void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs)
1208{
1209 TRACE("(GLsizei n = %d, const GLenum *bufs = %p)", n, bufs);
1210
1211 if(n < 0 || n > MAX_DRAW_BUFFERS)
1212 {
1213 return error(GL_INVALID_VALUE);
1214 }
1215
1216 es2::Context *context = es2::getContext();
1217
1218 if(context)
1219 {
1220 GLuint drawFramebufferName = context->getDrawFramebufferName();
1221
1222 if((drawFramebufferName == 0) && (n != 1))
1223 {
1224 return error(GL_INVALID_OPERATION);
1225 }
1226
1227 for(unsigned int i = 0; i < (unsigned)n; i++)
1228 {
1229 switch(bufs[i])
1230 {
1231 case GL_BACK:
1232 if(drawFramebufferName != 0)
1233 {
1234 return error(GL_INVALID_OPERATION);
1235 }
1236 break;
1237 case GL_NONE:
1238 break;
1239 case GL_COLOR_ATTACHMENT0:
1240 case GL_COLOR_ATTACHMENT1:
1241 case GL_COLOR_ATTACHMENT2:
1242 case GL_COLOR_ATTACHMENT3:
1243 case GL_COLOR_ATTACHMENT4:
1244 case GL_COLOR_ATTACHMENT5:
1245 case GL_COLOR_ATTACHMENT6:
1246 case GL_COLOR_ATTACHMENT7:
1247 case GL_COLOR_ATTACHMENT8:
1248 case GL_COLOR_ATTACHMENT9:
1249 case GL_COLOR_ATTACHMENT10:
1250 case GL_COLOR_ATTACHMENT11:
1251 case GL_COLOR_ATTACHMENT12:
1252 case GL_COLOR_ATTACHMENT13:
1253 case GL_COLOR_ATTACHMENT14:
1254 case GL_COLOR_ATTACHMENT15:
1255 case GL_COLOR_ATTACHMENT16:
1256 case GL_COLOR_ATTACHMENT17:
1257 case GL_COLOR_ATTACHMENT18:
1258 case GL_COLOR_ATTACHMENT19:
1259 case GL_COLOR_ATTACHMENT20:
1260 case GL_COLOR_ATTACHMENT21:
1261 case GL_COLOR_ATTACHMENT22:
1262 case GL_COLOR_ATTACHMENT23:
1263 case GL_COLOR_ATTACHMENT24:
1264 case GL_COLOR_ATTACHMENT25:
1265 case GL_COLOR_ATTACHMENT26:
1266 case GL_COLOR_ATTACHMENT27:
1267 case GL_COLOR_ATTACHMENT28:
1268 case GL_COLOR_ATTACHMENT29:
1269 case GL_COLOR_ATTACHMENT30:
1270 case GL_COLOR_ATTACHMENT31:
1271 {
1272 GLuint index = (bufs[i] - GL_COLOR_ATTACHMENT0);
1273
1274 if(index >= MAX_COLOR_ATTACHMENTS)
1275 {
1276 return error(GL_INVALID_OPERATION);
1277 }
1278
1279 if(index != i)
1280 {
1281 return error(GL_INVALID_OPERATION);
1282 }
1283
1284 if(drawFramebufferName == 0)
1285 {
1286 return error(GL_INVALID_OPERATION);
1287 }
1288 }
1289 break;
1290 default:
1291 return error(GL_INVALID_ENUM);
1292 }
1293 }
1294
1295 context->setFramebufferDrawBuffers(n, bufs);
1296 }
1297}
1298
1299GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1300{
1301 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1302
1303 if(count < 0)
1304 {
1305 return error(GL_INVALID_VALUE);
1306 }
1307
1308 if(location == -1)
1309 {
1310 return;
1311 }
1312
1313 es2::Context *context = es2::getContext();
1314
1315 if(context)
1316 {
1317 es2::Program *program = context->getCurrentProgram();
1318
1319 if(!program)
1320 {
1321 return error(GL_INVALID_OPERATION);
1322 }
1323
1324 if(!program->setUniformMatrix2x3fv(location, count, transpose, value))
1325 {
1326 return error(GL_INVALID_OPERATION);
1327 }
1328 }
1329}
1330
1331GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1332{
1333 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1334
1335 if(count < 0)
1336 {
1337 return error(GL_INVALID_VALUE);
1338 }
1339
1340 if(location == -1)
1341 {
1342 return;
1343 }
1344
1345 es2::Context *context = es2::getContext();
1346
1347 if(context)
1348 {
1349 es2::Program *program = context->getCurrentProgram();
1350
1351 if(!program)
1352 {
1353 return error(GL_INVALID_OPERATION);
1354 }
1355
1356 if(!program->setUniformMatrix3x2fv(location, count, transpose, value))
1357 {
1358 return error(GL_INVALID_OPERATION);
1359 }
1360 }
1361}
1362
1363GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1364{
1365 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1366
1367 if(count < 0)
1368 {
1369 return error(GL_INVALID_VALUE);
1370 }
1371
1372 if(location == -1)
1373 {
1374 return;
1375 }
1376
1377 es2::Context *context = es2::getContext();
1378
1379 if(context)
1380 {
1381 es2::Program *program = context->getCurrentProgram();
1382
1383 if(!program)
1384 {
1385 return error(GL_INVALID_OPERATION);
1386 }
1387
1388 if(!program->setUniformMatrix2x4fv(location, count, transpose, value))
1389 {
1390 return error(GL_INVALID_OPERATION);
1391 }
1392 }
1393}
1394
1395GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1396{
1397 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1398
1399 if(count < 0)
1400 {
1401 return error(GL_INVALID_VALUE);
1402 }
1403
1404 if(location == -1)
1405 {
1406 return;
1407 }
1408
1409 es2::Context *context = es2::getContext();
1410
1411 if(context)
1412 {
1413 es2::Program *program = context->getCurrentProgram();
1414
1415 if(!program)
1416 {
1417 return error(GL_INVALID_OPERATION);
1418 }
1419
1420 if(!program->setUniformMatrix4x2fv(location, count, transpose, value))
1421 {
1422 return error(GL_INVALID_OPERATION);
1423 }
1424 }
1425}
1426
1427GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1428{
1429 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1430
1431 if(count < 0)
1432 {
1433 return error(GL_INVALID_VALUE);
1434 }
1435
1436 if(location == -1)
1437 {
1438 return;
1439 }
1440
1441 es2::Context *context = es2::getContext();
1442
1443 if(context)
1444 {
1445 es2::Program *program = context->getCurrentProgram();
1446
1447 if(!program)
1448 {
1449 return error(GL_INVALID_OPERATION);
1450 }
1451
1452 if(!program->setUniformMatrix3x4fv(location, count, transpose, value))
1453 {
1454 return error(GL_INVALID_OPERATION);
1455 }
1456 }
1457}
1458
1459GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
1460{
1461 TRACE("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat *value = %p)", location, count, transpose, value);
1462
1463 if(count < 0)
1464 {
1465 return error(GL_INVALID_VALUE);
1466 }
1467
1468 if(location == -1)
1469 {
1470 return;
1471 }
1472
1473 es2::Context *context = es2::getContext();
1474
1475 if(context)
1476 {
1477 es2::Program *program = context->getCurrentProgram();
1478
1479 if(!program)
1480 {
1481 return error(GL_INVALID_OPERATION);
1482 }
1483
1484 if(!program->setUniformMatrix4x3fv(location, count, transpose, value))
1485 {
1486 return error(GL_INVALID_OPERATION);
1487 }
1488 }
1489}
1490
1491GL_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)
1492{
1493 TRACE("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
1494 "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
1495 "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
1496 srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
1497
1498 switch(filter)
1499 {
1500 case GL_NEAREST:
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05001501 break;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001502 case GL_LINEAR:
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05001503 if((mask & GL_DEPTH_BUFFER_BIT) || (mask & GL_STENCIL_BUFFER_BIT))
1504 {
1505 return error(GL_INVALID_OPERATION);
1506 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001507 break;
1508 default:
1509 return error(GL_INVALID_ENUM);
1510 }
1511
1512 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1513 {
1514 return error(GL_INVALID_VALUE);
1515 }
1516
1517 es2::Context *context = es2::getContext();
1518
1519 if(context)
1520 {
1521 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
1522 {
1523 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
1524 return error(GL_INVALID_OPERATION);
1525 }
1526
Alexis Hetub9dda642016-10-06 11:25:32 -04001527 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter == GL_LINEAR, true);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001528 }
1529}
1530
Nicolas Capens0bac2852016-05-07 06:09:58 -04001531GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
1532{
1533 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",
1534 target, attachment, texture, level, layer);
1535
1536 // GLES 3.0.4 spec, p.209, section 4.4.2
1537 // If texture is zero, any image or array of images attached to the attachment point
1538 // named by attachment is detached. Any additional parameters(level, textarget,
1539 // and / or layer) are ignored when texture is zero.
1540 if(texture != 0 && (layer < 0 || level < 0))
1541 {
1542 return error(GL_INVALID_VALUE);
1543 }
1544
1545 es2::Context *context = es2::getContext();
1546
1547 if(context)
1548 {
1549 Texture* textureObject = context->getTexture(texture);
1550 GLenum textarget = GL_NONE;
1551 if(texture != 0)
1552 {
1553 if(!textureObject)
1554 {
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05001555 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001556 }
1557
1558 textarget = textureObject->getTarget();
1559 switch(textarget)
1560 {
1561 case GL_TEXTURE_3D:
1562 case GL_TEXTURE_2D_ARRAY:
1563 if(layer >= es2::IMPLEMENTATION_MAX_TEXTURE_SIZE || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1564 {
1565 return error(GL_INVALID_VALUE);
1566 }
1567 break;
1568 default:
1569 return error(GL_INVALID_OPERATION);
1570 }
1571
1572 if(textureObject->isCompressed(textarget, level))
1573 {
1574 return error(GL_INVALID_OPERATION);
1575 }
1576 }
1577
1578 es2::Framebuffer *framebuffer = nullptr;
1579 switch(target)
1580 {
1581 case GL_DRAW_FRAMEBUFFER:
1582 case GL_FRAMEBUFFER:
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05001583 if(context->getDrawFramebufferName() == 0)
1584 {
1585 return error(GL_INVALID_OPERATION);
1586 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001587 framebuffer = context->getDrawFramebuffer();
1588 break;
1589 case GL_READ_FRAMEBUFFER:
Alexis Hetu1c93b6c2017-11-20 14:52:03 -05001590 if(context->getReadFramebufferName() == 0)
1591 {
1592 return error(GL_INVALID_OPERATION);
1593 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001594 framebuffer = context->getReadFramebuffer();
1595 break;
1596 default:
1597 return error(GL_INVALID_ENUM);
1598 }
1599
1600 if(!framebuffer)
1601 {
1602 return error(GL_INVALID_OPERATION);
1603 }
1604
1605 switch(attachment)
1606 {
1607 case GL_COLOR_ATTACHMENT0:
1608 case GL_COLOR_ATTACHMENT1:
1609 case GL_COLOR_ATTACHMENT2:
1610 case GL_COLOR_ATTACHMENT3:
1611 case GL_COLOR_ATTACHMENT4:
1612 case GL_COLOR_ATTACHMENT5:
1613 case GL_COLOR_ATTACHMENT6:
1614 case GL_COLOR_ATTACHMENT7:
1615 case GL_COLOR_ATTACHMENT8:
1616 case GL_COLOR_ATTACHMENT9:
1617 case GL_COLOR_ATTACHMENT10:
1618 case GL_COLOR_ATTACHMENT11:
1619 case GL_COLOR_ATTACHMENT12:
1620 case GL_COLOR_ATTACHMENT13:
1621 case GL_COLOR_ATTACHMENT14:
1622 case GL_COLOR_ATTACHMENT15:
1623 case GL_COLOR_ATTACHMENT16:
1624 case GL_COLOR_ATTACHMENT17:
1625 case GL_COLOR_ATTACHMENT18:
1626 case GL_COLOR_ATTACHMENT19:
1627 case GL_COLOR_ATTACHMENT20:
1628 case GL_COLOR_ATTACHMENT21:
1629 case GL_COLOR_ATTACHMENT22:
1630 case GL_COLOR_ATTACHMENT23:
1631 case GL_COLOR_ATTACHMENT24:
1632 case GL_COLOR_ATTACHMENT25:
1633 case GL_COLOR_ATTACHMENT26:
1634 case GL_COLOR_ATTACHMENT27:
1635 case GL_COLOR_ATTACHMENT28:
1636 case GL_COLOR_ATTACHMENT29:
1637 case GL_COLOR_ATTACHMENT30:
1638 case GL_COLOR_ATTACHMENT31:
1639 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level, layer);
1640 break;
1641 case GL_DEPTH_ATTACHMENT:
1642 framebuffer->setDepthbuffer(textarget, texture, level, layer);
1643 break;
1644 case GL_STENCIL_ATTACHMENT:
1645 framebuffer->setStencilbuffer(textarget, texture, level, layer);
1646 break;
1647 case GL_DEPTH_STENCIL_ATTACHMENT:
1648 framebuffer->setDepthbuffer(textarget, texture, level, layer);
1649 framebuffer->setStencilbuffer(textarget, texture, level, layer);
1650 break;
1651 default:
1652 return error(GL_INVALID_ENUM);
1653 }
1654 }
1655}
1656
1657GL_APICALL void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
1658{
1659 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",
1660 target, offset, length, access);
1661
Alexis Hetu6e864492017-11-14 15:27:00 -05001662 if((offset < 0) || (length < 0))
1663 {
1664 return error(GL_INVALID_VALUE, nullptr);
1665 }
1666
1667 if(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)))
1668 {
1669 // Must be able to read or write the buffer
1670 return error(GL_INVALID_OPERATION, nullptr);
1671 }
1672 else if((access & GL_MAP_READ_BIT) && (access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT)))
1673 {
1674 // GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT and GL_MAP_UNSYNCHRONIZED_BIT can't be used with GL_MAP_READ_BIT
1675 return error(GL_INVALID_OPERATION, nullptr);
1676 }
1677 else if((!(access & GL_MAP_WRITE_BIT)) && (access & GL_MAP_FLUSH_EXPLICIT_BIT))
1678 {
1679 // GL_MAP_FLUSH_EXPLICIT_BIT can't be used without GL_MAP_WRITE_BIT
1680 return error(GL_INVALID_OPERATION, nullptr);
1681 }
1682
Nicolas Capens0bac2852016-05-07 06:09:58 -04001683 es2::Context *context = es2::getContext();
1684
1685 if(context)
1686 {
1687 es2::Buffer *buffer = nullptr;
1688 if(!context->getBuffer(target, &buffer))
1689 {
1690 return error(GL_INVALID_ENUM, nullptr);
1691 }
1692
1693 if(!buffer)
1694 {
1695 // A null buffer means that "0" is bound to the requested buffer target
1696 return error(GL_INVALID_OPERATION, nullptr);
1697 }
1698
Alexis Hetu1b4eb7f2017-11-14 13:24:37 -05001699 if(buffer->isMapped())
1700 {
1701 // It is an invalid operation to map an already mapped buffer
1702 return error(GL_INVALID_OPERATION, nullptr);
1703 }
1704
Nicolas Capens0bac2852016-05-07 06:09:58 -04001705 GLsizeiptr bufferSize = buffer->size();
Alexis Hetu6e864492017-11-14 15:27:00 -05001706 if((offset + length) > bufferSize)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001707 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001708 return error(GL_INVALID_VALUE, nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001709 }
1710
1711 if((access & ~(GL_MAP_READ_BIT |
1712 GL_MAP_WRITE_BIT |
1713 GL_MAP_INVALIDATE_RANGE_BIT |
1714 GL_MAP_INVALIDATE_BUFFER_BIT |
1715 GL_MAP_FLUSH_EXPLICIT_BIT |
1716 GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
1717 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001718 return error(GL_INVALID_VALUE, nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001719 }
1720
1721 return buffer->mapRange(offset, length, access);
1722 }
1723
1724 return nullptr;
1725}
1726
1727GL_APICALL void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
1728{
1729 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)",
1730 target, offset, length);
1731
Alexis Hetu6e864492017-11-14 15:27:00 -05001732 if((offset < 0) || (length < 0))
1733 {
1734 return error(GL_INVALID_VALUE);
1735 }
1736
Nicolas Capens0bac2852016-05-07 06:09:58 -04001737 es2::Context *context = es2::getContext();
1738
1739 if(context)
1740 {
1741 es2::Buffer *buffer = nullptr;
1742 if(!context->getBuffer(target, &buffer))
1743 {
1744 return error(GL_INVALID_ENUM);
1745 }
1746
1747 if(!buffer)
1748 {
1749 // A null buffer means that "0" is bound to the requested buffer target
1750 return error(GL_INVALID_OPERATION);
1751 }
1752
Alexis Hetu6e864492017-11-14 15:27:00 -05001753 if(!buffer->isMapped())
Nicolas Capens0bac2852016-05-07 06:09:58 -04001754 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001755 // Buffer must be mapped
1756 return error(GL_INVALID_OPERATION);
1757 }
1758
1759 GLsizeiptr bufferSize = buffer->length();
1760 if((offset + length) > bufferSize)
1761 {
1762 return error(GL_INVALID_VALUE);
1763 }
1764
1765 if(!(buffer->usage() & GL_MAP_FLUSH_EXPLICIT_BIT))
1766 {
1767 // Flush must be explicitly allowed
1768 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001769 }
1770
1771 buffer->flushMappedRange(offset, length);
1772 }
1773}
1774
1775GL_APICALL void GL_APIENTRY glBindVertexArray(GLuint array)
1776{
1777 TRACE("(GLuint array = %d)", array);
1778
Nicolas Capens0bac2852016-05-07 06:09:58 -04001779 es2::Context *context = es2::getContext();
1780
1781 if(context)
1782 {
1783 if(!context->isVertexArray(array))
1784 {
1785 return error(GL_INVALID_OPERATION);
1786 }
1787
1788 context->bindVertexArray(array);
1789 }
1790}
1791
1792GL_APICALL void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
1793{
1794 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1795
1796 if(n < 0)
1797 {
1798 return error(GL_INVALID_VALUE);
1799 }
1800
1801 es2::Context *context = es2::getContext();
1802
1803 if(context)
1804 {
1805 for(int i = 0; i < n; i++)
1806 {
1807 context->deleteVertexArray(arrays[i]);
1808 }
1809 }
1810}
1811
1812GL_APICALL void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
1813{
1814 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1815
1816 if(n < 0)
1817 {
1818 return error(GL_INVALID_VALUE);
1819 }
1820
1821 es2::Context *context = es2::getContext();
1822
1823 if(context)
1824 {
1825 for(int i = 0; i < n; i++)
1826 {
1827 arrays[i] = context->createVertexArray();
1828 }
1829 }
1830}
1831
1832GL_APICALL GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
1833{
1834 TRACE("(GLuint array = %d)", array);
1835
1836 if(array == 0)
1837 {
1838 return GL_FALSE;
1839 }
1840
1841 es2::Context *context = es2::getContext();
1842
1843 if(context)
1844 {
1845 es2::VertexArray *arrayObject = context->getVertexArray(array);
1846
1847 if(arrayObject)
1848 {
1849 return GL_TRUE;
1850 }
1851 }
1852
1853 return GL_FALSE;
1854}
1855
1856GL_APICALL void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)
1857{
1858 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint* data = %p)",
1859 target, index, data);
1860
1861 es2::Context *context = es2::getContext();
1862
1863 if(context)
1864 {
1865 if(!context->getTransformFeedbackiv(index, target, data) &&
1866 !context->getUniformBufferiv(index, target, data) &&
1867 !context->getIntegerv(target, data))
1868 {
1869 GLenum nativeType;
1870 unsigned int numParams = 0;
1871 if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
1872 return error(GL_INVALID_ENUM);
1873
1874 if(numParams == 0)
1875 return; // it is known that target is valid, but there are no parameters to return
1876
1877 if(nativeType == GL_BOOL)
1878 {
1879 GLboolean *boolParams = nullptr;
1880 boolParams = new GLboolean[numParams];
1881
1882 context->getBooleanv(target, boolParams);
1883
1884 for(unsigned int i = 0; i < numParams; ++i)
1885 {
1886 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
1887 }
1888
1889 delete[] boolParams;
1890 }
1891 else if(nativeType == GL_FLOAT)
1892 {
1893 GLfloat *floatParams = nullptr;
1894 floatParams = new GLfloat[numParams];
1895
1896 context->getFloatv(target, floatParams);
1897
1898 for(unsigned int i = 0; i < numParams; ++i)
1899 {
1900 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
1901 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04001902 data[i] = convert_float_int(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001903 }
1904 else
1905 {
1906 data[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
1907 }
1908 }
1909
1910 delete[] floatParams;
1911 }
1912 }
1913 }
1914}
1915
1916GL_APICALL void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
1917{
1918 TRACE("(GLenum primitiveMode = 0x%X)", primitiveMode);
1919
1920 switch(primitiveMode)
1921 {
1922 case GL_POINTS:
1923 case GL_LINES:
1924 case GL_TRIANGLES:
1925 break;
1926 default:
1927 return error(GL_INVALID_ENUM);
1928 }
1929
1930 es2::Context *context = es2::getContext();
1931
1932 if(context)
1933 {
1934 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1935
1936 if(transformFeedbackObject)
1937 {
1938 if(transformFeedbackObject->isActive())
1939 {
1940 return error(GL_INVALID_OPERATION);
1941 }
1942 transformFeedbackObject->begin(primitiveMode);
1943 }
1944 else
1945 {
1946 return error(GL_INVALID_OPERATION);
1947 }
1948 }
1949}
1950
1951GL_APICALL void GL_APIENTRY glEndTransformFeedback(void)
1952{
1953 TRACE("()");
1954
1955 es2::Context *context = es2::getContext();
1956
1957 if(context)
1958 {
1959 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1960
1961 if(transformFeedbackObject)
1962 {
1963 if(!transformFeedbackObject->isActive())
1964 {
1965 return error(GL_INVALID_OPERATION);
1966 }
1967 transformFeedbackObject->end();
1968 }
1969 else
1970 {
1971 return error(GL_INVALID_OPERATION);
1972 }
1973 }
1974}
1975
1976GL_APICALL void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
1977{
1978 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)",
1979 target, index, buffer, offset, size);
1980
1981 if(buffer != 0 && size <= 0)
1982 {
1983 return error(GL_INVALID_VALUE);
1984 }
1985
1986 es2::Context *context = es2::getContext();
1987
1988 if(context)
1989 {
1990 switch(target)
1991 {
1992 case GL_TRANSFORM_FEEDBACK_BUFFER:
1993 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
1994 {
1995 return error(GL_INVALID_VALUE);
1996 }
1997 if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4
1998 {
1999 return error(GL_INVALID_VALUE);
2000 }
2001 context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
2002 context->bindGenericTransformFeedbackBuffer(buffer);
2003 break;
2004 case GL_UNIFORM_BUFFER:
2005 if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
2006 {
2007 return error(GL_INVALID_VALUE);
2008 }
2009 if(offset % UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0)
2010 {
2011 return error(GL_INVALID_VALUE);
2012 }
2013 context->bindIndexedUniformBuffer(buffer, index, offset, size);
2014 context->bindGenericUniformBuffer(buffer);
2015 break;
2016 default:
2017 return error(GL_INVALID_ENUM);
2018 }
2019 }
2020}
2021
2022GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
2023{
2024 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)",
2025 target, index, buffer);
2026
2027 es2::Context *context = es2::getContext();
2028
2029 if(context)
2030 {
2031 switch(target)
2032 {
2033 case GL_TRANSFORM_FEEDBACK_BUFFER:
2034 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2035 {
2036 return error(GL_INVALID_VALUE);
2037 }
2038 context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
2039 context->bindGenericTransformFeedbackBuffer(buffer);
2040 break;
2041 case GL_UNIFORM_BUFFER:
2042 if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
2043 {
2044 return error(GL_INVALID_VALUE);
2045 }
2046 context->bindIndexedUniformBuffer(buffer, index, 0, 0);
2047 context->bindGenericUniformBuffer(buffer);
2048 break;
2049 default:
2050 return error(GL_INVALID_ENUM);
2051 }
2052 }
2053}
2054
2055GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
2056{
2057 TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = %p, GLenum bufferMode = 0x%X)",
2058 program, count, varyings, bufferMode);
2059
2060 switch(bufferMode)
2061 {
2062 case GL_SEPARATE_ATTRIBS:
2063 if(count > MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2064 {
2065 return error(GL_INVALID_VALUE);
2066 }
2067 case GL_INTERLEAVED_ATTRIBS:
2068 break;
2069 default:
2070 return error(GL_INVALID_ENUM);
2071 }
2072
2073 es2::Context *context = es2::getContext();
2074
2075 if(context)
2076 {
2077 es2::Program *programObject = context->getProgram(program);
2078
2079 if(!programObject)
2080 {
2081 return error(GL_INVALID_VALUE);
2082 }
2083
2084 programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
2085 }
2086}
2087
2088GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
2089{
2090 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2091 program, index, bufSize, length, size, type, name);
2092
2093 if(bufSize < 0)
2094 {
2095 return error(GL_INVALID_VALUE);
2096 }
2097
2098 es2::Context *context = es2::getContext();
2099
2100 if(context)
2101 {
2102 es2::Program *programObject = context->getProgram(program);
2103
2104 if(!programObject)
2105 {
2106 return error(GL_INVALID_VALUE);
2107 }
2108
2109 if(index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
2110 {
2111 return error(GL_INVALID_VALUE);
2112 }
2113
2114 programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
2115 }
2116}
2117
2118GL_APICALL void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
2119{
2120 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2121 index, size, type, stride, pointer);
2122
2123 if(index >= es2::MAX_VERTEX_ATTRIBS)
2124 {
2125 return error(GL_INVALID_VALUE);
2126 }
2127
2128 if(size < 1 || size > 4 || stride < 0)
2129 {
2130 return error(GL_INVALID_VALUE);
2131 }
2132
2133 switch(type)
2134 {
2135 case GL_BYTE:
2136 case GL_UNSIGNED_BYTE:
2137 case GL_SHORT:
2138 case GL_UNSIGNED_SHORT:
2139 case GL_INT:
2140 case GL_UNSIGNED_INT:
2141 break;
2142 default:
2143 return error(GL_INVALID_ENUM);
2144 }
2145
2146 es2::Context *context = es2::getContext();
2147
2148 if(context)
2149 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05002150 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
2151 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && pointer)
2152 {
2153 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
2154 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
2155 return error(GL_INVALID_OPERATION);
2156 }
2157
Nicolas Capens0bac2852016-05-07 06:09:58 -04002158 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, stride, pointer);
2159 }
2160}
2161
2162GL_APICALL void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
2163{
2164 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = %p)",
2165 index, pname, params);
2166
2167 es2::Context *context = es2::getContext();
2168
2169 if(context)
2170 {
2171 if(index >= es2::MAX_VERTEX_ATTRIBS)
2172 {
2173 return error(GL_INVALID_VALUE);
2174 }
2175
2176 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2177
2178 switch(pname)
2179 {
2180 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2181 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2182 break;
2183 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2184 *params = attribState.mSize;
2185 break;
2186 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2187 *params = attribState.mStride;
2188 break;
2189 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2190 *params = attribState.mType;
2191 break;
2192 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2193 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2194 break;
2195 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2196 *params = attribState.mBoundBuffer.name();
2197 break;
2198 case GL_CURRENT_VERTEX_ATTRIB:
2199 {
2200 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2201 for(int i = 0; i < 4; ++i)
2202 {
2203 params[i] = attrib.getCurrentValueI(i);
2204 }
2205 }
2206 break;
2207 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2208 switch(attribState.mType)
2209 {
2210 case GL_BYTE:
2211 case GL_UNSIGNED_BYTE:
2212 case GL_SHORT:
2213 case GL_UNSIGNED_SHORT:
2214 case GL_INT:
2215 case GL_INT_2_10_10_10_REV:
2216 case GL_UNSIGNED_INT:
2217 case GL_FIXED:
2218 *params = GL_TRUE;
2219 break;
2220 default:
2221 *params = GL_FALSE;
2222 break;
2223 }
2224 break;
2225 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2226 *params = attribState.mDivisor;
2227 break;
2228 default: return error(GL_INVALID_ENUM);
2229 }
2230 }
2231}
2232
2233GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
2234{
2235 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = %p)",
2236 index, pname, params);
2237
2238 es2::Context *context = es2::getContext();
2239
2240 if(context)
2241 {
2242 if(index >= es2::MAX_VERTEX_ATTRIBS)
2243 {
2244 return error(GL_INVALID_VALUE);
2245 }
2246
2247 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2248
2249 switch(pname)
2250 {
2251 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2252 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2253 break;
2254 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2255 *params = attribState.mSize;
2256 break;
2257 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2258 *params = attribState.mStride;
2259 break;
2260 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2261 *params = attribState.mType;
2262 break;
2263 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2264 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2265 break;
2266 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2267 *params = attribState.mBoundBuffer.name();
2268 break;
2269 case GL_CURRENT_VERTEX_ATTRIB:
2270 {
2271 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2272 for(int i = 0; i < 4; ++i)
2273 {
2274 params[i] = attrib.getCurrentValueUI(i);
2275 }
2276 }
2277 break;
2278 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2279 switch(attribState.mType)
2280 {
2281 case GL_BYTE:
2282 case GL_UNSIGNED_BYTE:
2283 case GL_SHORT:
2284 case GL_UNSIGNED_SHORT:
2285 case GL_INT:
2286 case GL_INT_2_10_10_10_REV:
2287 case GL_UNSIGNED_INT:
2288 case GL_FIXED:
2289 *params = GL_TRUE;
2290 break;
2291 default:
2292 *params = GL_FALSE;
2293 break;
2294 }
2295 break;
2296 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2297 *params = attribState.mDivisor;
2298 break;
2299 default: return error(GL_INVALID_ENUM);
2300 }
2301 }
2302}
2303
2304GL_APICALL void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
2305{
2306 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2307 index, x, y, z, w);
2308
2309 if(index >= es2::MAX_VERTEX_ATTRIBS)
2310 {
2311 return error(GL_INVALID_VALUE);
2312 }
2313
2314 es2::Context *context = es2::getContext();
2315
2316 if(context)
2317 {
2318 GLint vals[4] = { x, y, z, w };
2319 context->setVertexAttrib(index, vals);
2320 }
2321}
2322
2323GL_APICALL void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
2324{
2325 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2326 index, x, y, z, w);
2327
2328 if(index >= es2::MAX_VERTEX_ATTRIBS)
2329 {
2330 return error(GL_INVALID_VALUE);
2331 }
2332
2333 es2::Context *context = es2::getContext();
2334
2335 if(context)
2336 {
2337 GLuint vals[4] = { x, y, z, w };
2338 context->setVertexAttrib(index, vals);
2339 }
2340}
2341
2342GL_APICALL void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)
2343{
2344 TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2345
2346 if(index >= es2::MAX_VERTEX_ATTRIBS)
2347 {
2348 return error(GL_INVALID_VALUE);
2349 }
2350
2351 es2::Context *context = es2::getContext();
2352
2353 if(context)
2354 {
2355 context->setVertexAttrib(index, v);
2356 }
2357}
2358
2359GL_APICALL void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)
2360{
2361 TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2362
2363 if(index >= es2::MAX_VERTEX_ATTRIBS)
2364 {
2365 return error(GL_INVALID_VALUE);
2366 }
2367
2368 es2::Context *context = es2::getContext();
2369
2370 if(context)
2371 {
2372 context->setVertexAttrib(index, v);
2373 }
2374}
2375
2376GL_APICALL void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)
2377{
2378 TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = %p)",
2379 program, location, params);
2380
2381 es2::Context *context = es2::getContext();
2382
2383 if(context)
2384 {
2385 if(program == 0)
2386 {
2387 return error(GL_INVALID_VALUE);
2388 }
2389
2390 es2::Program *programObject = context->getProgram(program);
2391
2392 if(!programObject || !programObject->isLinked())
2393 {
2394 return error(GL_INVALID_OPERATION);
2395 }
2396
2397 if(!programObject)
2398 {
2399 return error(GL_INVALID_OPERATION);
2400 }
2401
2402 if(!programObject->getUniformuiv(location, nullptr, params))
2403 {
2404 return error(GL_INVALID_OPERATION);
2405 }
2406 }
2407}
2408
2409GL_APICALL GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
2410{
2411 TRACE("(GLuint program = %d, const GLchar *name = %p)", program, name);
2412
2413 es2::Context *context = es2::getContext();
2414
Nicolas Capens0bac2852016-05-07 06:09:58 -04002415 if(context)
2416 {
2417 es2::Program *programObject = context->getProgram(program);
2418
2419 if(!programObject)
2420 {
2421 if(context->getShader(program))
2422 {
2423 return error(GL_INVALID_OPERATION, -1);
2424 }
2425 else
2426 {
2427 return error(GL_INVALID_VALUE, -1);
2428 }
2429 }
2430
2431 if(!programObject->isLinked())
2432 {
2433 return error(GL_INVALID_OPERATION, -1);
2434 }
Alexis Hetub3f5ed72017-08-16 16:37:19 -04002435
2436 return programObject->getFragDataLocation(name);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002437 }
2438
Nicolas Capens0bac2852016-05-07 06:09:58 -04002439 return -1;
2440}
2441
2442GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
2443{
2444 glUniform1uiv(location, 1, &v0);
2445}
2446
2447GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
2448{
2449 GLuint xy[2] = { v0, v1 };
2450
2451 glUniform2uiv(location, 1, (GLuint*)&xy);
2452}
2453
2454GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
2455{
2456 GLuint xyz[3] = { v0, v1, v2 };
2457
2458 glUniform3uiv(location, 1, (GLuint*)&xyz);
2459}
2460
2461GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
2462{
2463 GLuint xyzw[4] = { v0, v1, v2, v3 };
2464
2465 glUniform4uiv(location, 1, (GLuint*)&xyzw);
2466}
2467
2468GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
2469{
2470 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2471 location, count, value);
2472
2473 if(count < 0)
2474 {
2475 return error(GL_INVALID_VALUE);
2476 }
2477
2478 if(location == -1)
2479 {
2480 return;
2481 }
2482
2483 es2::Context *context = es2::getContext();
2484
2485 if(context)
2486 {
2487 es2::Program *program = context->getCurrentProgram();
2488
2489 if(!program)
2490 {
2491 return error(GL_INVALID_OPERATION);
2492 }
2493
2494 if(!program->setUniform1uiv(location, count, value))
2495 {
2496 return error(GL_INVALID_OPERATION);
2497 }
2498 }
2499}
2500
2501GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
2502{
2503 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2504 location, count, value);
2505
2506 if(count < 0)
2507 {
2508 return error(GL_INVALID_VALUE);
2509 }
2510
2511 if(location == -1)
2512 {
2513 return;
2514 }
2515
2516 es2::Context *context = es2::getContext();
2517
2518 if(context)
2519 {
2520 es2::Program *program = context->getCurrentProgram();
2521
2522 if(!program)
2523 {
2524 return error(GL_INVALID_OPERATION);
2525 }
2526
2527 if(!program->setUniform2uiv(location, count, value))
2528 {
2529 return error(GL_INVALID_OPERATION);
2530 }
2531 }
2532}
2533
2534GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
2535{
2536 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2537 location, count, value);
2538
2539 if(count < 0)
2540 {
2541 return error(GL_INVALID_VALUE);
2542 }
2543
2544 if(location == -1)
2545 {
2546 return;
2547 }
2548
2549 es2::Context *context = es2::getContext();
2550
2551 if(context)
2552 {
2553 es2::Program *program = context->getCurrentProgram();
2554
2555 if(!program)
2556 {
2557 return error(GL_INVALID_OPERATION);
2558 }
2559
2560 if(!program->setUniform3uiv(location, count, value))
2561 {
2562 return error(GL_INVALID_OPERATION);
2563 }
2564 }
2565}
2566
2567GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
2568{
2569 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2570 location, count, value);
2571
2572 if(count < 0)
2573 {
2574 return error(GL_INVALID_VALUE);
2575 }
2576
2577 if(location == -1)
2578 {
2579 return;
2580 }
2581
2582 es2::Context *context = es2::getContext();
2583
2584 if(context)
2585 {
2586 es2::Program *program = context->getCurrentProgram();
2587
2588 if(!program)
2589 {
2590 return error(GL_INVALID_OPERATION);
2591 }
2592
2593 if(!program->setUniform4uiv(location, count, value))
2594 {
2595 return error(GL_INVALID_OPERATION);
2596 }
2597 }
2598}
2599
2600GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
2601{
2602 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
2603 buffer, drawbuffer, value);
2604
2605 es2::Context *context = es2::getContext();
2606
2607 if(context)
2608 {
2609 switch(buffer)
2610 {
2611 case GL_COLOR:
2612 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2613 {
2614 return error(GL_INVALID_VALUE);
2615 }
2616 else
2617 {
2618 context->clearColorBuffer(drawbuffer, value);
2619 }
2620 break;
2621 case GL_STENCIL:
2622 if(drawbuffer != 0)
2623 {
2624 return error(GL_INVALID_VALUE);
2625 }
2626 else
2627 {
2628 context->clearStencilBuffer(value[0]);
2629 }
2630 break;
2631 default:
2632 return error(GL_INVALID_ENUM);
2633 }
2634 }
2635}
2636
2637GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
2638{
2639 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
2640 buffer, drawbuffer, value);
2641
2642 es2::Context *context = es2::getContext();
2643
2644 if(context)
2645 {
2646 switch(buffer)
2647 {
2648 case GL_COLOR:
2649 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2650 {
2651 return error(GL_INVALID_VALUE);
2652 }
2653 else
2654 {
2655 context->clearColorBuffer(drawbuffer, value);
2656 }
2657 break;
2658 default:
2659 return error(GL_INVALID_ENUM);
2660 }
2661 }
2662}
2663
2664GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
2665{
2666 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
2667 buffer, drawbuffer, value);
2668
2669 es2::Context *context = es2::getContext();
2670
2671 if(context)
2672 {
2673 switch(buffer)
2674 {
2675 case GL_COLOR:
2676 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2677 {
2678 return error(GL_INVALID_VALUE);
2679 }
2680 else
2681 {
2682 context->clearColorBuffer(drawbuffer, value);
2683 }
2684 break;
2685 case GL_DEPTH:
2686 if(drawbuffer != 0)
2687 {
2688 return error(GL_INVALID_VALUE);
2689 }
2690 else
2691 {
2692 context->clearDepthBuffer(value[0]);
2693 }
2694 break;
2695 default:
2696 return error(GL_INVALID_ENUM);
2697 }
2698 }
2699}
2700
2701GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
2702{
2703 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
2704 buffer, drawbuffer, depth, stencil);
2705
2706 es2::Context *context = es2::getContext();
2707
2708 if(context)
2709 {
2710 switch(buffer)
2711 {
2712 case GL_DEPTH_STENCIL:
2713 if(drawbuffer != 0)
2714 {
2715 return error(GL_INVALID_VALUE);
2716 }
2717 else
2718 {
2719 context->clearDepthBuffer(depth);
2720 context->clearStencilBuffer(stencil);
2721 }
2722 break;
2723 default:
2724 return error(GL_INVALID_ENUM);
2725 }
2726 }
2727}
2728
2729GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
2730{
2731 TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index);
2732
2733 es2::Context *context = es2::getContext();
2734 if(context)
2735 {
2736 GLuint numExtensions;
2737 context->getExtensions(0, &numExtensions);
2738
2739 if(index >= numExtensions)
2740 {
2741 return error(GL_INVALID_VALUE, (GLubyte*)nullptr);
2742 }
2743
2744 switch(name)
2745 {
2746 case GL_EXTENSIONS:
2747 return context->getExtensions(index);
2748 default:
2749 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
2750 }
2751 }
2752
2753 return (GLubyte*)nullptr;
2754}
2755
2756GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
2757{
2758 TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
2759 readTarget, writeTarget, readOffset, writeOffset, size);
2760
2761 if(readOffset < 0 || writeOffset < 0 || size < 0)
2762 {
2763 return error(GL_INVALID_VALUE);
2764 }
2765
2766 es2::Context *context = es2::getContext();
2767
2768 if(context)
2769 {
2770 es2::Buffer *readBuffer = nullptr, *writeBuffer = nullptr;
2771 if(!context->getBuffer(readTarget, &readBuffer) || !context->getBuffer(writeTarget, &writeBuffer))
2772 {
2773 return error(GL_INVALID_ENUM);
2774 }
2775 if(!readBuffer || readBuffer->isMapped() || !writeBuffer || writeBuffer->isMapped())
2776 {
2777 return error(GL_INVALID_OPERATION);
2778 }
2779 if(readBuffer == writeBuffer)
2780 {
2781 // If same buffer, check for overlap
2782 if(((readOffset >= writeOffset) && (readOffset < (writeOffset + size))) ||
2783 ((writeOffset >= readOffset) && (writeOffset < (readOffset + size))))
2784 {
2785 return error(GL_INVALID_VALUE);
2786 }
2787 }
2788
2789 if((static_cast<size_t>(readOffset + size) > readBuffer->size()) ||
2790 (static_cast<size_t>(writeOffset + size) > writeBuffer->size()))
2791 {
2792 return error(GL_INVALID_VALUE);
2793 }
2794
2795 writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset);
2796 }
2797}
2798
2799GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
2800{
2801 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)",
2802 program, uniformCount, uniformNames, uniformIndices);
2803
2804 if(uniformCount < 0)
2805 {
2806 return error(GL_INVALID_VALUE);
2807 }
2808
2809 es2::Context *context = es2::getContext();
2810
2811 if(context)
2812 {
2813 es2::Program *programObject = context->getProgram(program);
2814
2815 if(!programObject)
2816 {
2817 return error(GL_INVALID_OPERATION);
2818 }
2819
2820 if(!programObject->isLinked())
2821 {
2822 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2823 {
2824 uniformIndices[uniformId] = GL_INVALID_INDEX;
2825 }
2826 }
2827 else
2828 {
2829 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2830 {
2831 uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
2832 }
2833 }
2834 }
2835}
2836
2837GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
2838{
2839 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLenum pname = 0x%X, GLuint *uniformIndices = %p)",
2840 program, uniformCount, uniformIndices, pname, uniformIndices);
2841
2842 switch(pname)
2843 {
2844 case GL_UNIFORM_TYPE:
2845 case GL_UNIFORM_SIZE:
2846 case GL_UNIFORM_NAME_LENGTH:
2847 case GL_UNIFORM_BLOCK_INDEX:
2848 case GL_UNIFORM_OFFSET:
2849 case GL_UNIFORM_ARRAY_STRIDE:
2850 case GL_UNIFORM_MATRIX_STRIDE:
2851 case GL_UNIFORM_IS_ROW_MAJOR:
2852 break;
2853 default:
2854 return error(GL_INVALID_ENUM);
2855 }
2856
2857 if(uniformCount < 0)
2858 {
2859 return error(GL_INVALID_VALUE);
2860 }
2861
2862 es2::Context *context = es2::getContext();
2863
2864 if(context)
2865 {
2866 es2::Program *programObject = context->getProgram(program);
2867
2868 if(!programObject)
2869 {
2870 return error(GL_INVALID_OPERATION);
2871 }
2872
2873 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2874 {
2875 const GLuint index = uniformIndices[uniformId];
2876
2877 if(index >= programObject->getActiveUniformCount())
2878 {
2879 return error(GL_INVALID_VALUE);
2880 }
2881 }
2882
2883 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2884 {
2885 const GLuint index = uniformIndices[uniformId];
2886 params[uniformId] = programObject->getActiveUniformi(index, pname);
2887 }
2888 }
2889}
2890
2891GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
2892{
2893 TRACE("(GLuint program = %d, const GLchar *uniformBlockName = %p)",
2894 program, uniformBlockName);
2895
2896 es2::Context *context = es2::getContext();
2897
2898 if(context)
2899 {
2900 es2::Program *programObject = context->getProgram(program);
2901
2902 if(!programObject)
2903 {
2904 return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
2905 }
2906
2907 return programObject->getUniformBlockIndex(uniformBlockName);
2908 }
2909
2910 return GL_INVALID_INDEX;
2911}
2912
2913GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
2914{
2915 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)",
2916 program, uniformBlockIndex, pname, params);
2917
2918 es2::Context *context = es2::getContext();
2919
2920 if(context)
2921 {
2922 es2::Program *programObject = context->getProgram(program);
2923
2924 if(!programObject)
2925 {
2926 return error(GL_INVALID_OPERATION);
2927 }
2928
2929 switch(pname)
2930 {
2931 case GL_UNIFORM_BLOCK_BINDING:
2932 *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
2933 break;
2934 case GL_UNIFORM_BLOCK_DATA_SIZE:
2935 case GL_UNIFORM_BLOCK_NAME_LENGTH:
2936 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2937 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2938 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2939 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2940 programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
2941 break;
2942 default:
2943 return error(GL_INVALID_ENUM);
2944 }
2945 }
2946}
2947
2948GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
2949{
2950 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLchar *uniformBlockName = %p)",
2951 program, uniformBlockIndex, bufSize, length, uniformBlockName);
2952
2953 if(bufSize < 0)
2954 {
2955 return error(GL_INVALID_VALUE);
2956 }
2957
2958 es2::Context *context = es2::getContext();
2959
2960 if(context)
2961 {
2962 es2::Program *programObject = context->getProgram(program);
2963
2964 if(!programObject)
2965 {
2966 return error(GL_INVALID_OPERATION);
2967 }
2968
2969 programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
2970 }
2971}
2972
2973GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2974{
2975 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",
2976 program, uniformBlockIndex, uniformBlockBinding);
2977
2978 if(uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS)
2979 {
2980 return error(GL_INVALID_VALUE);
2981 }
2982
2983 es2::Context *context = es2::getContext();
2984
2985 if(context)
2986 {
2987 es2::Program *programObject = context->getProgram(program);
2988
2989 if(!programObject)
2990 {
2991 return error(GL_INVALID_VALUE);
2992 }
2993
Nicolas Capens65dcbbd2016-08-12 16:59:04 -04002994 programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002995 }
2996}
2997
2998GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
2999{
3000 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
3001 mode, first, count, instanceCount);
3002
3003 switch(mode)
3004 {
3005 case GL_POINTS:
3006 case GL_LINES:
3007 case GL_LINE_LOOP:
3008 case GL_LINE_STRIP:
3009 case GL_TRIANGLES:
3010 case GL_TRIANGLE_FAN:
3011 case GL_TRIANGLE_STRIP:
3012 break;
3013 default:
3014 return error(GL_INVALID_ENUM);
3015 }
3016
3017 if(count < 0 || instanceCount < 0)
3018 {
3019 return error(GL_INVALID_VALUE);
3020 }
3021
3022 es2::Context *context = es2::getContext();
3023
3024 if(context)
3025 {
3026 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
3027 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
3028 {
3029 return error(GL_INVALID_OPERATION);
3030 }
3031
3032 context->drawArrays(mode, first, count, instanceCount);
3033 }
3034}
3035
3036GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
3037{
3038 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
3039 mode, count, type, indices, instanceCount);
3040
3041 switch(mode)
3042 {
3043 case GL_POINTS:
3044 case GL_LINES:
3045 case GL_LINE_LOOP:
3046 case GL_LINE_STRIP:
3047 case GL_TRIANGLES:
3048 case GL_TRIANGLE_FAN:
3049 case GL_TRIANGLE_STRIP:
3050 break;
3051 default:
3052 return error(GL_INVALID_ENUM);
3053 }
3054
3055 switch(type)
3056 {
3057 case GL_UNSIGNED_BYTE:
3058 case GL_UNSIGNED_SHORT:
3059 case GL_UNSIGNED_INT:
3060 break;
3061 default:
3062 return error(GL_INVALID_ENUM);
3063 }
3064
3065 if(count < 0 || instanceCount < 0)
3066 {
3067 return error(GL_INVALID_VALUE);
3068 }
3069
3070 es2::Context *context = es2::getContext();
3071
3072 if(context)
3073 {
3074 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
3075 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
3076 {
3077 return error(GL_INVALID_OPERATION);
3078 }
3079
3080 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
3081 }
3082}
3083
3084GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
3085{
3086 TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags);
3087
3088 switch(condition)
3089 {
3090 case GL_SYNC_GPU_COMMANDS_COMPLETE:
3091 break;
3092 default:
3093 return error(GL_INVALID_ENUM, nullptr);
3094 }
3095
3096 if(flags != 0)
3097 {
3098 return error(GL_INVALID_VALUE, nullptr);
3099 }
3100
3101 es2::Context *context = es2::getContext();
3102
3103 if(context)
3104 {
3105 return context->createFenceSync(condition, flags);
3106 }
3107
3108 return nullptr;
3109}
3110
3111GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync)
3112{
3113 TRACE("(GLsync sync = %p)", sync);
3114
3115 es2::Context *context = es2::getContext();
3116
3117 if(context)
3118 {
3119 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3120
3121 if(fenceSyncObject)
3122 {
3123 return GL_TRUE;
3124 }
3125 }
3126
3127 return GL_FALSE;
3128}
3129
3130GL_APICALL void GL_APIENTRY glDeleteSync(GLsync sync)
3131{
3132 TRACE("(GLsync sync = %p)", sync);
3133
Alexis Hetuadd96ad2017-11-14 17:22:46 -05003134 if(!sync)
3135 {
3136 return;
3137 }
3138
Nicolas Capens0bac2852016-05-07 06:09:58 -04003139 es2::Context *context = es2::getContext();
3140
3141 if(context)
3142 {
Alexis Hetuadd96ad2017-11-14 17:22:46 -05003143 if(!context->getFenceSync(sync))
3144 {
3145 return error(GL_INVALID_VALUE);
3146 }
3147
Nicolas Capens0bac2852016-05-07 06:09:58 -04003148 context->deleteFenceSync(sync);
3149 }
3150}
3151
3152GL_APICALL GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3153{
3154 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3155
3156 if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3157 {
Alexis Hetu6e864492017-11-14 15:27:00 -05003158 return error(GL_INVALID_VALUE, GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003159 }
3160
3161 es2::Context *context = es2::getContext();
3162
3163 if(context)
3164 {
3165 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3166
3167 if(fenceSyncObject)
3168 {
3169 return fenceSyncObject->clientWait(flags, timeout);
3170 }
3171 else
3172 {
3173 return error(GL_INVALID_VALUE, GL_FALSE);
3174 }
3175 }
3176
3177 return GL_FALSE;
3178}
3179
3180GL_APICALL void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3181{
3182 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3183
3184 if(flags != 0)
3185 {
3186 return error(GL_INVALID_VALUE);
3187 }
3188
3189 if(timeout != GL_TIMEOUT_IGNORED)
3190 {
3191 return error(GL_INVALID_VALUE);
3192 }
3193
3194 es2::Context *context = es2::getContext();
3195
3196 if(context)
3197 {
3198 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3199
3200 if(fenceSyncObject)
3201 {
3202 fenceSyncObject->serverWait(flags, timeout);
3203 }
3204 else
3205 {
3206 return error(GL_INVALID_VALUE);
3207 }
3208 }
3209}
3210
3211GL_APICALL void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *data)
3212{
3213 TRACE("(GLenum pname = 0x%X, GLint64 *data = %p)", pname, data);
3214
3215 es2::Context *context = es2::getContext();
3216
3217 if(context)
3218 {
3219 if(!(context->getIntegerv(pname, data)))
3220 {
3221 GLenum nativeType;
3222 unsigned int numParams = 0;
3223 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3224 return error(GL_INVALID_ENUM);
3225
3226 if(numParams == 0)
3227 return; // it is known that pname is valid, but there are no parameters to return
3228
3229 if(nativeType == GL_BOOL)
3230 {
3231 GLboolean *boolParams = nullptr;
3232 boolParams = new GLboolean[numParams];
3233
3234 context->getBooleanv(pname, boolParams);
3235
3236 for(unsigned int i = 0; i < numParams; ++i)
3237 {
3238 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3239 }
3240
3241 delete[] boolParams;
3242 }
3243 else if(nativeType == GL_FLOAT)
3244 {
3245 GLfloat *floatParams = nullptr;
3246 floatParams = new GLfloat[numParams];
3247
3248 context->getFloatv(pname, floatParams);
3249
3250 for(unsigned int i = 0; i < numParams; ++i)
3251 {
3252 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3253 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003254 data[i] = (GLint64)(convert_float_int(floatParams[i]));
Nicolas Capens0bac2852016-05-07 06:09:58 -04003255 }
3256 else
3257 {
3258 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3259 }
3260 }
3261
3262 delete[] floatParams;
3263 }
3264 }
3265 }
3266}
3267
3268GL_APICALL void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
3269{
3270 TRACE("(GLsync sync = %p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = %p, GLint *values = %p)",
3271 sync, pname, bufSize, length, values);
3272
3273 if(bufSize < 0)
3274 {
3275 return error(GL_INVALID_VALUE);
3276 }
3277
Alexis Hetu0f7c7b82017-02-17 17:07:50 -05003278 es2::Context *context = es2::getContext();
3279
3280 if(context)
3281 {
3282 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3283 if(!fenceSyncObject)
3284 {
3285 return error(GL_INVALID_VALUE);
3286 }
3287
3288 fenceSyncObject->getSynciv(pname, length, values);
3289 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003290}
3291
3292GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
3293{
3294 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint64 *data = %p)", target, index, data);
3295
3296 es2::Context *context = es2::getContext();
3297
3298 if(context)
3299 {
3300 if(!context->getTransformFeedbackiv(index, target, data) &&
3301 !context->getUniformBufferiv(index, target, data) &&
3302 !context->getIntegerv(target, data))
3303 {
3304 GLenum nativeType;
3305 unsigned int numParams = 0;
3306 if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
3307 return error(GL_INVALID_ENUM);
3308
3309 if(numParams == 0)
3310 return; // it is known that target is valid, but there are no parameters to return
3311
3312 if(nativeType == GL_BOOL)
3313 {
3314 GLboolean *boolParams = nullptr;
3315 boolParams = new GLboolean[numParams];
3316
3317 context->getBooleanv(target, boolParams);
3318
3319 for(unsigned int i = 0; i < numParams; ++i)
3320 {
3321 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3322 }
3323
3324 delete[] boolParams;
3325 }
3326 else if(nativeType == GL_FLOAT)
3327 {
3328 GLfloat *floatParams = nullptr;
3329 floatParams = new GLfloat[numParams];
3330
3331 context->getFloatv(target, floatParams);
3332
3333 for(unsigned int i = 0; i < numParams; ++i)
3334 {
3335 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
3336 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003337 data[i] = (GLint64)(convert_float_int(floatParams[i]));
Nicolas Capens0bac2852016-05-07 06:09:58 -04003338 }
3339 else
3340 {
3341 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3342 }
3343 }
3344
3345 delete[] floatParams;
3346 }
3347 }
3348 }
3349}
3350
3351GL_APICALL void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
3352{
3353 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = %p)", target, pname, params);
3354
3355 es2::Context *context = es2::getContext();
3356
3357 if(context)
3358 {
3359 es2::Buffer *buffer = nullptr;
3360
3361 if(!context->getBuffer(target, &buffer))
3362 {
3363 return error(GL_INVALID_ENUM);
3364 }
3365
3366 if(!buffer)
3367 {
3368 // A null buffer means that "0" is bound to the requested buffer target
3369 return error(GL_INVALID_OPERATION);
3370 }
3371
3372 switch(pname)
3373 {
3374 case GL_BUFFER_USAGE:
3375 *params = buffer->usage();
3376 break;
3377 case GL_BUFFER_SIZE:
3378 *params = buffer->size();
3379 break;
3380 case GL_BUFFER_ACCESS_FLAGS:
3381 *params = buffer->access();
3382 break;
3383 case GL_BUFFER_MAPPED:
3384 *params = buffer->isMapped();
3385 break;
3386 case GL_BUFFER_MAP_LENGTH:
3387 *params = buffer->length();
3388 break;
3389 case GL_BUFFER_MAP_OFFSET:
3390 *params = buffer->offset();
3391 break;
3392 default:
3393 return error(GL_INVALID_ENUM);
3394 }
3395 }
3396}
3397
3398GL_APICALL void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)
3399{
3400 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3401
3402 if(count < 0)
3403 {
3404 return error(GL_INVALID_VALUE);
3405 }
3406
3407 es2::Context *context = es2::getContext();
3408
3409 if(context)
3410 {
3411 for(int i = 0; i < count; i++)
3412 {
3413 samplers[i] = context->createSampler();
3414 }
3415 }
3416}
3417
3418GL_APICALL void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
3419{
3420 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3421
3422 if(count < 0)
3423 {
3424 return error(GL_INVALID_VALUE);
3425 }
3426
3427 es2::Context *context = es2::getContext();
3428
3429 if(context)
3430 {
3431 for(int i = 0; i < count; i++)
3432 {
3433 context->deleteSampler(samplers[i]);
3434 }
3435 }
3436}
3437
3438GL_APICALL GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
3439{
3440 TRACE("(GLuint sampler = %d)", sampler);
3441
3442 if(sampler == 0)
3443 {
3444 return GL_FALSE;
3445 }
3446
3447 es2::Context *context = es2::getContext();
3448
3449 if(context)
3450 {
3451 if(context->isSampler(sampler))
3452 {
3453 return GL_TRUE;
3454 }
3455 }
3456
3457 return GL_FALSE;
3458}
3459
3460GL_APICALL void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
3461{
3462 TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler);
3463
3464 if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3465 {
3466 return error(GL_INVALID_VALUE);
3467 }
3468
3469 es2::Context *context = es2::getContext();
3470
3471 if(context)
3472 {
3473 if(sampler != 0 && !context->isSampler(sampler))
3474 {
3475 return error(GL_INVALID_OPERATION);
3476 }
3477
3478 context->bindSampler(unit, sampler);
3479 }
3480}
3481
3482GL_APICALL void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
3483{
3484 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint param = %d)",
3485 sampler, pname, param);
3486
3487 glSamplerParameteriv(sampler, pname, &param);
3488}
3489
3490GL_APICALL void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
3491{
3492 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = %p)",
3493 sampler, pname, param);
3494
3495 if(!ValidateSamplerObjectParameter(pname))
3496 {
3497 return error(GL_INVALID_ENUM);
3498 }
3499
3500 if(!ValidateTexParamParameters(pname, *param))
3501 {
3502 return;
3503 }
3504
3505 es2::Context *context = es2::getContext();
3506
3507 if(context)
3508 {
3509 if(!context->isSampler(sampler))
3510 {
3511 return error(GL_INVALID_OPERATION);
3512 }
3513
3514 context->samplerParameteri(sampler, pname, *param);
3515 }
3516}
3517
3518GL_APICALL void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
3519{
3520 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat param = %f)",
3521 sampler, pname, param);
3522
3523 glSamplerParameterfv(sampler, pname, &param);
3524}
3525
3526GL_APICALL void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
3527{
3528 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = %p)",
3529 sampler, pname, param);
3530
3531 if(!ValidateSamplerObjectParameter(pname))
3532 {
3533 return error(GL_INVALID_ENUM);
3534 }
3535
Alexis Hetub34591a2016-06-28 15:48:35 -04003536 if(!ValidateTexParamParameters(pname, static_cast<GLint>(roundf(*param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04003537 {
3538 return;
3539 }
3540
3541 es2::Context *context = es2::getContext();
3542
3543 if(context)
3544 {
3545 if(!context->isSampler(sampler))
3546 {
3547 return error(GL_INVALID_OPERATION);
3548 }
3549
3550 context->samplerParameterf(sampler, pname, *param);
3551 }
3552}
3553
3554GL_APICALL void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
3555{
3556 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = %p)",
3557 sampler, pname, params);
3558
3559 if(!ValidateSamplerObjectParameter(pname))
3560 {
3561 return error(GL_INVALID_ENUM);
3562 }
3563
3564 es2::Context *context = es2::getContext();
3565
3566 if(context)
3567 {
3568 if(!context->isSampler(sampler))
3569 {
3570 return error(GL_INVALID_VALUE);
3571 }
3572
3573 *params = context->getSamplerParameteri(sampler, pname);
3574 }
3575}
3576
3577GL_APICALL void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
3578{
3579 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = %p)",
3580 sampler, pname, params);
3581
3582 if(!ValidateSamplerObjectParameter(pname))
3583 {
3584 return error(GL_INVALID_ENUM);
3585 }
3586
3587 es2::Context *context = es2::getContext();
3588
3589 if(context)
3590 {
3591 if(!context->isSampler(sampler))
3592 {
3593 return error(GL_INVALID_VALUE);
3594 }
3595
3596 *params = context->getSamplerParameterf(sampler, pname);
3597 }
3598}
3599
3600GL_APICALL void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
3601{
3602 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
3603
3604 es2::Context *context = es2::getContext();
3605
3606 if(context)
3607 {
3608 if(index >= es2::MAX_VERTEX_ATTRIBS)
3609 {
3610 return error(GL_INVALID_VALUE);
3611 }
3612
3613 context->setVertexAttribDivisor(index, divisor);
3614 }
3615}
3616
3617GL_APICALL void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
3618{
3619 TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);
3620
3621 if(target != GL_TRANSFORM_FEEDBACK)
3622 {
3623 return error(GL_INVALID_ENUM);
3624 }
3625
3626 es2::Context *context = es2::getContext();
3627
3628 if(context)
3629 {
3630 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3631
3632 if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused())
3633 {
3634 return error(GL_INVALID_OPERATION);
3635 }
3636
Alexis Hetu5bf97082017-11-14 11:06:03 -05003637 if(!context->isTransformFeedback(id))
3638 {
3639 return error(GL_INVALID_OPERATION);
3640 }
3641
Nicolas Capens0bac2852016-05-07 06:09:58 -04003642 context->bindTransformFeedback(id);
3643 }
3644}
3645
3646GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
3647{
3648 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3649
3650 if(n < 0)
3651 {
3652 return error(GL_INVALID_VALUE);
3653 }
3654
3655 es2::Context *context = es2::getContext();
3656
3657 if(context)
3658 {
3659 for(int i = 0; i < n; i++)
3660 {
3661 if(ids[i] != 0)
3662 {
Alexis Hetu5bf97082017-11-14 11:06:03 -05003663 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(ids[i]);
3664
3665 if(transformFeedbackObject && transformFeedbackObject->isActive())
3666 {
3667 return error(GL_INVALID_OPERATION);
3668 }
3669
Nicolas Capens0bac2852016-05-07 06:09:58 -04003670 context->deleteTransformFeedback(ids[i]);
3671 }
3672 }
3673 }
3674}
3675
3676GL_APICALL void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
3677{
3678 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3679
3680 if(n < 0)
3681 {
3682 return error(GL_INVALID_VALUE);
3683 }
3684
3685 es2::Context *context = es2::getContext();
3686
3687 if(context)
3688 {
3689 for(int i = 0; i < n; i++)
3690 {
3691 ids[i] = context->createTransformFeedback();
3692 }
3693 }
3694}
3695
3696GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
3697{
3698 TRACE("(GLuint id = %d)", id);
3699
3700 if(id == 0)
3701 {
3702 return GL_FALSE;
3703 }
3704
3705 es2::Context *context = es2::getContext();
3706
3707 if(context)
3708 {
3709 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id);
3710
3711 if(transformFeedbackObject)
3712 {
3713 return GL_TRUE;
3714 }
3715 }
3716
3717 return GL_FALSE;
3718}
3719
3720GL_APICALL void GL_APIENTRY glPauseTransformFeedback(void)
3721{
3722 TRACE("()");
3723
3724 es2::Context *context = es2::getContext();
3725
3726 if(context)
3727 {
3728 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3729
3730 if(transformFeedbackObject)
3731 {
3732 if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused())
3733 {
3734 return error(GL_INVALID_OPERATION);
3735 }
3736 transformFeedbackObject->setPaused(true);
3737 }
3738 }
3739}
3740
3741GL_APICALL void GL_APIENTRY glResumeTransformFeedback(void)
3742{
3743 TRACE("()");
3744
3745 es2::Context *context = es2::getContext();
3746
3747 if(context)
3748 {
3749 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3750
3751 if(transformFeedbackObject)
3752 {
3753 if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused())
3754 {
3755 return error(GL_INVALID_OPERATION);
3756 }
3757 transformFeedbackObject->setPaused(false);
3758 }
3759 }
3760}
3761
3762GL_APICALL void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
3763{
3764 TRACE("(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLenum *binaryFormat = %p, void *binary = %p)",
3765 program, bufSize, length, binaryFormat, binary);
3766
3767 if(bufSize < 0)
3768 {
3769 return error(GL_INVALID_VALUE);
3770 }
3771
3772 UNIMPLEMENTED();
3773}
3774
3775GL_APICALL void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
3776{
3777 TRACE("(GLuint program = %d, GLenum binaryFormat = 0x%X, const void *binary = %p, GLsizei length = %d)",
3778 program, binaryFormat, binaryFormat, length);
3779
3780 if(length < 0)
3781 {
3782 return error(GL_INVALID_VALUE);
3783 }
3784
3785 UNIMPLEMENTED();
3786}
3787
3788GL_APICALL void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
3789{
3790 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint value = %d)",
3791 program, pname, value);
3792
3793 es2::Context *context = es2::getContext();
3794
3795 if(context)
3796 {
3797 es2::Program *programObject = context->getProgram(program);
3798
3799 if(!programObject)
3800 {
3801 return error(GL_INVALID_OPERATION);
3802 }
3803
3804 switch(pname)
3805 {
3806 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3807 programObject->setBinaryRetrievable(value != GL_FALSE);
3808 break;
3809 default:
3810 return error(GL_INVALID_ENUM);
3811 }
3812 }
3813}
3814
3815GL_APICALL void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
3816{
3817 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p)",
3818 target, numAttachments, attachments);
3819
3820 glInvalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, std::numeric_limits<GLsizei>::max(), std::numeric_limits<GLsizei>::max());
3821}
3822
3823GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
3824{
3825 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
3826 target, numAttachments, attachments, x, y, width, height);
3827
3828 es2::Context *context = es2::getContext();
3829
3830 if(context)
3831 {
3832 if(numAttachments < 0 || width < 0 || height < 0)
3833 {
3834 return error(GL_INVALID_VALUE);
3835 }
3836
3837 es2::Framebuffer *framebuffer = nullptr;
3838 switch(target)
3839 {
3840 case GL_DRAW_FRAMEBUFFER:
3841 case GL_FRAMEBUFFER:
3842 framebuffer = context->getDrawFramebuffer();
3843 case GL_READ_FRAMEBUFFER:
3844 framebuffer = context->getReadFramebuffer();
3845 break;
3846 default:
3847 return error(GL_INVALID_ENUM);
3848 }
3849
3850 if(framebuffer)
3851 {
3852 for(int i = 0; i < numAttachments; i++)
3853 {
3854 switch(attachments[i])
3855 {
3856 case GL_COLOR:
3857 case GL_DEPTH:
3858 case GL_STENCIL:
3859 if(!framebuffer->isDefaultFramebuffer())
3860 {
3861 return error(GL_INVALID_ENUM);
3862 }
3863 break;
3864 case GL_DEPTH_ATTACHMENT:
3865 case GL_STENCIL_ATTACHMENT:
3866 case GL_DEPTH_STENCIL_ATTACHMENT:
3867 break;
3868 default:
3869 if(attachments[i] >= GL_COLOR_ATTACHMENT0 &&
3870 attachments[i] <= GL_COLOR_ATTACHMENT31)
3871 {
3872 if(attachments[i] - GL_COLOR_ATTACHMENT0 >= MAX_DRAW_BUFFERS)
3873 {
3874 return error(GL_INVALID_OPERATION);
3875 }
3876 }
3877 else
3878 {
3879 return error(GL_INVALID_ENUM);
3880 }
3881 break;
3882 }
3883 }
3884 }
3885
3886 // UNIMPLEMENTED(); // It is valid for this function to be treated as a no-op
3887 }
3888}
3889
3890GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
3891{
3892 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
3893 target, levels, internalformat, width, height);
3894
3895 if(width < 1 || height < 1 || levels < 1)
3896 {
3897 return error(GL_INVALID_VALUE);
3898 }
3899
3900 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
3901 {
3902 return error(GL_INVALID_OPERATION);
3903 }
3904
3905 GLenum type;
3906 if(!GetStorageType(internalformat, type))
3907 {
3908 return error(GL_INVALID_ENUM);
3909 }
3910
3911 es2::Context *context = es2::getContext();
3912
3913 if(context)
3914 {
3915 switch(target)
3916 {
3917 case GL_TEXTURE_2D:
3918 {
3919 es2::Texture2D *texture = context->getTexture2D();
3920 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3921 {
3922 return error(GL_INVALID_OPERATION);
3923 }
3924
3925 for(int level = 0; level < levels; ++level)
3926 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003927 texture->setImage(context, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003928 width = std::max(1, (width / 2));
3929 height = std::max(1, (height / 2));
3930 }
3931 texture->makeImmutable(levels);
3932 }
3933 break;
3934 case GL_TEXTURE_CUBE_MAP:
3935 {
3936 es2::TextureCubeMap *texture = context->getTextureCubeMap();
3937 if(!texture || texture->name == 0 || texture->getImmutableFormat())
3938 {
3939 return error(GL_INVALID_OPERATION);
3940 }
3941
3942 for(int level = 0; level < levels; ++level)
3943 {
3944 for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
3945 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003946 texture->setImage(context, face, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003947 }
3948 width = std::max(1, (width / 2));
3949 height = std::max(1, (height / 2));
3950 }
3951 texture->makeImmutable(levels);
3952 }
3953 break;
3954 default:
3955 return error(GL_INVALID_ENUM);
3956 }
3957 }
3958}
3959
3960GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
3961{
3962 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d)",
3963 target, levels, internalformat, width, height, depth);
3964
3965 if(width < 1 || height < 1 || depth < 1 || levels < 1)
3966 {
3967 return error(GL_INVALID_VALUE);
3968 }
3969
3970 GLenum type;
3971 if(!GetStorageType(internalformat, type))
3972 {
3973 return error(GL_INVALID_ENUM);
3974 }
3975
3976 es2::Context *context = es2::getContext();
3977
3978 if(context)
3979 {
3980 switch(target)
3981 {
3982 case GL_TEXTURE_3D:
3983 {
3984 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1))
3985 {
3986 return error(GL_INVALID_OPERATION);
3987 }
3988
3989 es2::Texture3D *texture = context->getTexture3D();
3990 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3991 {
3992 return error(GL_INVALID_OPERATION);
3993 }
3994
3995 for(int level = 0; level < levels; ++level)
3996 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003997 texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003998 width = std::max(1, (width / 2));
3999 height = std::max(1, (height / 2));
4000 depth = std::max(1, (depth / 2));
4001 }
4002 texture->makeImmutable(levels);
4003 }
4004 break;
4005 case GL_TEXTURE_2D_ARRAY:
4006 {
4007 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
4008 {
4009 return error(GL_INVALID_OPERATION);
4010 }
4011
4012 es2::Texture3D *texture = context->getTexture2DArray();
4013 if(!texture || texture->name == 0 || texture->getImmutableFormat())
4014 {
4015 return error(GL_INVALID_OPERATION);
4016 }
4017
4018 for(int level = 0; level < levels; ++level)
4019 {
4020 for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
4021 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04004022 texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004023 }
4024 width = std::max(1, (width / 2));
4025 height = std::max(1, (height / 2));
4026 }
4027 texture->makeImmutable(levels);
4028 }
4029 break;
4030 default:
4031 return error(GL_INVALID_ENUM);
4032 }
4033 }
4034}
4035
4036GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)
4037{
4038 TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLint *params = %p)",
4039 target, internalformat, pname, bufSize, params);
4040
4041 if(bufSize < 0)
4042 {
4043 return error(GL_INVALID_VALUE);
4044 }
4045
4046 if(bufSize == 0)
4047 {
4048 return;
4049 }
4050
Nicolas Capens400667e2017-03-29 14:40:14 -04004051 if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) &&
4052 !IsDepthRenderable(internalformat, egl::getClientVersion()) &&
4053 !IsStencilRenderable(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004054 {
4055 return error(GL_INVALID_ENUM);
4056 }
4057
4058 switch(target)
4059 {
4060 case GL_RENDERBUFFER:
4061 break;
4062 default:
4063 return error(GL_INVALID_ENUM);
4064 }
4065
4066 // Integer types have no multisampling
4067 GLint numMultisampleCounts = NUM_MULTISAMPLE_COUNTS;
4068 switch(internalformat)
4069 {
4070 case GL_R8UI:
4071 case GL_R8I:
4072 case GL_R16UI:
4073 case GL_R16I:
4074 case GL_R32UI:
4075 case GL_R32I:
4076 case GL_RG8UI:
4077 case GL_RG8I:
4078 case GL_RG16UI:
4079 case GL_RG16I:
4080 case GL_RG32UI:
4081 case GL_RG32I:
4082 case GL_RGB8UI:
4083 case GL_RGB8I:
4084 case GL_RGB16UI:
4085 case GL_RGB16I:
4086 case GL_RGB32UI:
4087 case GL_RGB32I:
4088 case GL_RGBA8UI:
4089 case GL_RGBA8I:
4090 case GL_RGB10_A2UI:
4091 case GL_RGBA16UI:
4092 case GL_RGBA16I:
4093 case GL_RGBA32UI:
4094 case GL_RGBA32I:
4095 numMultisampleCounts = 0;
4096 break;
4097 default:
4098 break;
4099 }
4100
4101 switch(pname)
4102 {
4103 case GL_NUM_SAMPLE_COUNTS:
4104 *params = numMultisampleCounts;
4105 break;
4106 case GL_SAMPLES:
4107 for(int i = 0; i < numMultisampleCounts && i < bufSize; i++)
4108 {
4109 params[i] = multisampleCount[i];
4110 }
4111 break;
4112 default:
4113 return error(GL_INVALID_ENUM);
4114 }
4115}
4116
4117}