blob: 92813e2afe294ed47e8cc4c444f03d9b5f0538b5 [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:
1501 case GL_LINEAR:
1502 break;
1503 default:
1504 return error(GL_INVALID_ENUM);
1505 }
1506
1507 if((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1508 {
1509 return error(GL_INVALID_VALUE);
1510 }
1511
1512 es2::Context *context = es2::getContext();
1513
1514 if(context)
1515 {
1516 if(context->getReadFramebufferName() == context->getDrawFramebufferName())
1517 {
1518 ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
1519 return error(GL_INVALID_OPERATION);
1520 }
1521
Alexis Hetub9dda642016-10-06 11:25:32 -04001522 context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter == GL_LINEAR, true);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001523 }
1524}
1525
Nicolas Capens0bac2852016-05-07 06:09:58 -04001526GL_APICALL void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
1527{
1528 TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",
1529 target, attachment, texture, level, layer);
1530
1531 // GLES 3.0.4 spec, p.209, section 4.4.2
1532 // If texture is zero, any image or array of images attached to the attachment point
1533 // named by attachment is detached. Any additional parameters(level, textarget,
1534 // and / or layer) are ignored when texture is zero.
1535 if(texture != 0 && (layer < 0 || level < 0))
1536 {
1537 return error(GL_INVALID_VALUE);
1538 }
1539
1540 es2::Context *context = es2::getContext();
1541
1542 if(context)
1543 {
1544 Texture* textureObject = context->getTexture(texture);
1545 GLenum textarget = GL_NONE;
1546 if(texture != 0)
1547 {
1548 if(!textureObject)
1549 {
1550 return error(GL_INVALID_VALUE);
1551 }
1552
1553 textarget = textureObject->getTarget();
1554 switch(textarget)
1555 {
1556 case GL_TEXTURE_3D:
1557 case GL_TEXTURE_2D_ARRAY:
1558 if(layer >= es2::IMPLEMENTATION_MAX_TEXTURE_SIZE || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
1559 {
1560 return error(GL_INVALID_VALUE);
1561 }
1562 break;
1563 default:
1564 return error(GL_INVALID_OPERATION);
1565 }
1566
1567 if(textureObject->isCompressed(textarget, level))
1568 {
1569 return error(GL_INVALID_OPERATION);
1570 }
1571 }
1572
1573 es2::Framebuffer *framebuffer = nullptr;
1574 switch(target)
1575 {
1576 case GL_DRAW_FRAMEBUFFER:
1577 case GL_FRAMEBUFFER:
1578 framebuffer = context->getDrawFramebuffer();
1579 break;
1580 case GL_READ_FRAMEBUFFER:
1581 framebuffer = context->getReadFramebuffer();
1582 break;
1583 default:
1584 return error(GL_INVALID_ENUM);
1585 }
1586
1587 if(!framebuffer)
1588 {
1589 return error(GL_INVALID_OPERATION);
1590 }
1591
1592 switch(attachment)
1593 {
1594 case GL_COLOR_ATTACHMENT0:
1595 case GL_COLOR_ATTACHMENT1:
1596 case GL_COLOR_ATTACHMENT2:
1597 case GL_COLOR_ATTACHMENT3:
1598 case GL_COLOR_ATTACHMENT4:
1599 case GL_COLOR_ATTACHMENT5:
1600 case GL_COLOR_ATTACHMENT6:
1601 case GL_COLOR_ATTACHMENT7:
1602 case GL_COLOR_ATTACHMENT8:
1603 case GL_COLOR_ATTACHMENT9:
1604 case GL_COLOR_ATTACHMENT10:
1605 case GL_COLOR_ATTACHMENT11:
1606 case GL_COLOR_ATTACHMENT12:
1607 case GL_COLOR_ATTACHMENT13:
1608 case GL_COLOR_ATTACHMENT14:
1609 case GL_COLOR_ATTACHMENT15:
1610 case GL_COLOR_ATTACHMENT16:
1611 case GL_COLOR_ATTACHMENT17:
1612 case GL_COLOR_ATTACHMENT18:
1613 case GL_COLOR_ATTACHMENT19:
1614 case GL_COLOR_ATTACHMENT20:
1615 case GL_COLOR_ATTACHMENT21:
1616 case GL_COLOR_ATTACHMENT22:
1617 case GL_COLOR_ATTACHMENT23:
1618 case GL_COLOR_ATTACHMENT24:
1619 case GL_COLOR_ATTACHMENT25:
1620 case GL_COLOR_ATTACHMENT26:
1621 case GL_COLOR_ATTACHMENT27:
1622 case GL_COLOR_ATTACHMENT28:
1623 case GL_COLOR_ATTACHMENT29:
1624 case GL_COLOR_ATTACHMENT30:
1625 case GL_COLOR_ATTACHMENT31:
1626 framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level, layer);
1627 break;
1628 case GL_DEPTH_ATTACHMENT:
1629 framebuffer->setDepthbuffer(textarget, texture, level, layer);
1630 break;
1631 case GL_STENCIL_ATTACHMENT:
1632 framebuffer->setStencilbuffer(textarget, texture, level, layer);
1633 break;
1634 case GL_DEPTH_STENCIL_ATTACHMENT:
1635 framebuffer->setDepthbuffer(textarget, texture, level, layer);
1636 framebuffer->setStencilbuffer(textarget, texture, level, layer);
1637 break;
1638 default:
1639 return error(GL_INVALID_ENUM);
1640 }
1641 }
1642}
1643
1644GL_APICALL void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
1645{
1646 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",
1647 target, offset, length, access);
1648
Alexis Hetu6e864492017-11-14 15:27:00 -05001649 if((offset < 0) || (length < 0))
1650 {
1651 return error(GL_INVALID_VALUE, nullptr);
1652 }
1653
1654 if(!(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)))
1655 {
1656 // Must be able to read or write the buffer
1657 return error(GL_INVALID_OPERATION, nullptr);
1658 }
1659 else if((access & GL_MAP_READ_BIT) && (access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT)))
1660 {
1661 // GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT and GL_MAP_UNSYNCHRONIZED_BIT can't be used with GL_MAP_READ_BIT
1662 return error(GL_INVALID_OPERATION, nullptr);
1663 }
1664 else if((!(access & GL_MAP_WRITE_BIT)) && (access & GL_MAP_FLUSH_EXPLICIT_BIT))
1665 {
1666 // GL_MAP_FLUSH_EXPLICIT_BIT can't be used without GL_MAP_WRITE_BIT
1667 return error(GL_INVALID_OPERATION, nullptr);
1668 }
1669
Nicolas Capens0bac2852016-05-07 06:09:58 -04001670 es2::Context *context = es2::getContext();
1671
1672 if(context)
1673 {
1674 es2::Buffer *buffer = nullptr;
1675 if(!context->getBuffer(target, &buffer))
1676 {
1677 return error(GL_INVALID_ENUM, nullptr);
1678 }
1679
1680 if(!buffer)
1681 {
1682 // A null buffer means that "0" is bound to the requested buffer target
1683 return error(GL_INVALID_OPERATION, nullptr);
1684 }
1685
Alexis Hetu1b4eb7f2017-11-14 13:24:37 -05001686 if(buffer->isMapped())
1687 {
1688 // It is an invalid operation to map an already mapped buffer
1689 return error(GL_INVALID_OPERATION, nullptr);
1690 }
1691
Nicolas Capens0bac2852016-05-07 06:09:58 -04001692 GLsizeiptr bufferSize = buffer->size();
Alexis Hetu6e864492017-11-14 15:27:00 -05001693 if((offset + length) > bufferSize)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001694 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001695 return error(GL_INVALID_VALUE, nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001696 }
1697
1698 if((access & ~(GL_MAP_READ_BIT |
1699 GL_MAP_WRITE_BIT |
1700 GL_MAP_INVALIDATE_RANGE_BIT |
1701 GL_MAP_INVALIDATE_BUFFER_BIT |
1702 GL_MAP_FLUSH_EXPLICIT_BIT |
1703 GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
1704 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001705 return error(GL_INVALID_VALUE, nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001706 }
1707
1708 return buffer->mapRange(offset, length, access);
1709 }
1710
1711 return nullptr;
1712}
1713
1714GL_APICALL void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
1715{
1716 TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)",
1717 target, offset, length);
1718
Alexis Hetu6e864492017-11-14 15:27:00 -05001719 if((offset < 0) || (length < 0))
1720 {
1721 return error(GL_INVALID_VALUE);
1722 }
1723
Nicolas Capens0bac2852016-05-07 06:09:58 -04001724 es2::Context *context = es2::getContext();
1725
1726 if(context)
1727 {
1728 es2::Buffer *buffer = nullptr;
1729 if(!context->getBuffer(target, &buffer))
1730 {
1731 return error(GL_INVALID_ENUM);
1732 }
1733
1734 if(!buffer)
1735 {
1736 // A null buffer means that "0" is bound to the requested buffer target
1737 return error(GL_INVALID_OPERATION);
1738 }
1739
Alexis Hetu6e864492017-11-14 15:27:00 -05001740 if(!buffer->isMapped())
Nicolas Capens0bac2852016-05-07 06:09:58 -04001741 {
Alexis Hetu6e864492017-11-14 15:27:00 -05001742 // Buffer must be mapped
1743 return error(GL_INVALID_OPERATION);
1744 }
1745
1746 GLsizeiptr bufferSize = buffer->length();
1747 if((offset + length) > bufferSize)
1748 {
1749 return error(GL_INVALID_VALUE);
1750 }
1751
1752 if(!(buffer->usage() & GL_MAP_FLUSH_EXPLICIT_BIT))
1753 {
1754 // Flush must be explicitly allowed
1755 return error(GL_INVALID_OPERATION);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001756 }
1757
1758 buffer->flushMappedRange(offset, length);
1759 }
1760}
1761
1762GL_APICALL void GL_APIENTRY glBindVertexArray(GLuint array)
1763{
1764 TRACE("(GLuint array = %d)", array);
1765
Nicolas Capens0bac2852016-05-07 06:09:58 -04001766 es2::Context *context = es2::getContext();
1767
1768 if(context)
1769 {
1770 if(!context->isVertexArray(array))
1771 {
1772 return error(GL_INVALID_OPERATION);
1773 }
1774
1775 context->bindVertexArray(array);
1776 }
1777}
1778
1779GL_APICALL void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
1780{
1781 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1782
1783 if(n < 0)
1784 {
1785 return error(GL_INVALID_VALUE);
1786 }
1787
1788 es2::Context *context = es2::getContext();
1789
1790 if(context)
1791 {
1792 for(int i = 0; i < n; i++)
1793 {
1794 context->deleteVertexArray(arrays[i]);
1795 }
1796 }
1797}
1798
1799GL_APICALL void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
1800{
1801 TRACE("(GLsizei n = %d, const GLuint *arrays = %p)", n, arrays);
1802
1803 if(n < 0)
1804 {
1805 return error(GL_INVALID_VALUE);
1806 }
1807
1808 es2::Context *context = es2::getContext();
1809
1810 if(context)
1811 {
1812 for(int i = 0; i < n; i++)
1813 {
1814 arrays[i] = context->createVertexArray();
1815 }
1816 }
1817}
1818
1819GL_APICALL GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
1820{
1821 TRACE("(GLuint array = %d)", array);
1822
1823 if(array == 0)
1824 {
1825 return GL_FALSE;
1826 }
1827
1828 es2::Context *context = es2::getContext();
1829
1830 if(context)
1831 {
1832 es2::VertexArray *arrayObject = context->getVertexArray(array);
1833
1834 if(arrayObject)
1835 {
1836 return GL_TRUE;
1837 }
1838 }
1839
1840 return GL_FALSE;
1841}
1842
1843GL_APICALL void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)
1844{
1845 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint* data = %p)",
1846 target, index, data);
1847
1848 es2::Context *context = es2::getContext();
1849
1850 if(context)
1851 {
1852 if(!context->getTransformFeedbackiv(index, target, data) &&
1853 !context->getUniformBufferiv(index, target, data) &&
1854 !context->getIntegerv(target, data))
1855 {
1856 GLenum nativeType;
1857 unsigned int numParams = 0;
1858 if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
1859 return error(GL_INVALID_ENUM);
1860
1861 if(numParams == 0)
1862 return; // it is known that target is valid, but there are no parameters to return
1863
1864 if(nativeType == GL_BOOL)
1865 {
1866 GLboolean *boolParams = nullptr;
1867 boolParams = new GLboolean[numParams];
1868
1869 context->getBooleanv(target, boolParams);
1870
1871 for(unsigned int i = 0; i < numParams; ++i)
1872 {
1873 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
1874 }
1875
1876 delete[] boolParams;
1877 }
1878 else if(nativeType == GL_FLOAT)
1879 {
1880 GLfloat *floatParams = nullptr;
1881 floatParams = new GLfloat[numParams];
1882
1883 context->getFloatv(target, floatParams);
1884
1885 for(unsigned int i = 0; i < numParams; ++i)
1886 {
1887 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
1888 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04001889 data[i] = convert_float_int(floatParams[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001890 }
1891 else
1892 {
1893 data[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
1894 }
1895 }
1896
1897 delete[] floatParams;
1898 }
1899 }
1900 }
1901}
1902
1903GL_APICALL void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
1904{
1905 TRACE("(GLenum primitiveMode = 0x%X)", primitiveMode);
1906
1907 switch(primitiveMode)
1908 {
1909 case GL_POINTS:
1910 case GL_LINES:
1911 case GL_TRIANGLES:
1912 break;
1913 default:
1914 return error(GL_INVALID_ENUM);
1915 }
1916
1917 es2::Context *context = es2::getContext();
1918
1919 if(context)
1920 {
1921 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1922
1923 if(transformFeedbackObject)
1924 {
1925 if(transformFeedbackObject->isActive())
1926 {
1927 return error(GL_INVALID_OPERATION);
1928 }
1929 transformFeedbackObject->begin(primitiveMode);
1930 }
1931 else
1932 {
1933 return error(GL_INVALID_OPERATION);
1934 }
1935 }
1936}
1937
1938GL_APICALL void GL_APIENTRY glEndTransformFeedback(void)
1939{
1940 TRACE("()");
1941
1942 es2::Context *context = es2::getContext();
1943
1944 if(context)
1945 {
1946 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
1947
1948 if(transformFeedbackObject)
1949 {
1950 if(!transformFeedbackObject->isActive())
1951 {
1952 return error(GL_INVALID_OPERATION);
1953 }
1954 transformFeedbackObject->end();
1955 }
1956 else
1957 {
1958 return error(GL_INVALID_OPERATION);
1959 }
1960 }
1961}
1962
1963GL_APICALL void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
1964{
1965 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)",
1966 target, index, buffer, offset, size);
1967
1968 if(buffer != 0 && size <= 0)
1969 {
1970 return error(GL_INVALID_VALUE);
1971 }
1972
1973 es2::Context *context = es2::getContext();
1974
1975 if(context)
1976 {
1977 switch(target)
1978 {
1979 case GL_TRANSFORM_FEEDBACK_BUFFER:
1980 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
1981 {
1982 return error(GL_INVALID_VALUE);
1983 }
1984 if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4
1985 {
1986 return error(GL_INVALID_VALUE);
1987 }
1988 context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
1989 context->bindGenericTransformFeedbackBuffer(buffer);
1990 break;
1991 case GL_UNIFORM_BUFFER:
1992 if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
1993 {
1994 return error(GL_INVALID_VALUE);
1995 }
1996 if(offset % UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0)
1997 {
1998 return error(GL_INVALID_VALUE);
1999 }
2000 context->bindIndexedUniformBuffer(buffer, index, offset, size);
2001 context->bindGenericUniformBuffer(buffer);
2002 break;
2003 default:
2004 return error(GL_INVALID_ENUM);
2005 }
2006 }
2007}
2008
2009GL_APICALL void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
2010{
2011 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)",
2012 target, index, buffer);
2013
2014 es2::Context *context = es2::getContext();
2015
2016 if(context)
2017 {
2018 switch(target)
2019 {
2020 case GL_TRANSFORM_FEEDBACK_BUFFER:
2021 if(index >= MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2022 {
2023 return error(GL_INVALID_VALUE);
2024 }
2025 context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
2026 context->bindGenericTransformFeedbackBuffer(buffer);
2027 break;
2028 case GL_UNIFORM_BUFFER:
2029 if(index >= MAX_UNIFORM_BUFFER_BINDINGS)
2030 {
2031 return error(GL_INVALID_VALUE);
2032 }
2033 context->bindIndexedUniformBuffer(buffer, index, 0, 0);
2034 context->bindGenericUniformBuffer(buffer);
2035 break;
2036 default:
2037 return error(GL_INVALID_ENUM);
2038 }
2039 }
2040}
2041
2042GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
2043{
2044 TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = %p, GLenum bufferMode = 0x%X)",
2045 program, count, varyings, bufferMode);
2046
2047 switch(bufferMode)
2048 {
2049 case GL_SEPARATE_ATTRIBS:
2050 if(count > MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
2051 {
2052 return error(GL_INVALID_VALUE);
2053 }
2054 case GL_INTERLEAVED_ATTRIBS:
2055 break;
2056 default:
2057 return error(GL_INVALID_ENUM);
2058 }
2059
2060 es2::Context *context = es2::getContext();
2061
2062 if(context)
2063 {
2064 es2::Program *programObject = context->getProgram(program);
2065
2066 if(!programObject)
2067 {
2068 return error(GL_INVALID_VALUE);
2069 }
2070
2071 programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
2072 }
2073}
2074
2075GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
2076{
2077 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2078 program, index, bufSize, length, size, type, name);
2079
2080 if(bufSize < 0)
2081 {
2082 return error(GL_INVALID_VALUE);
2083 }
2084
2085 es2::Context *context = es2::getContext();
2086
2087 if(context)
2088 {
2089 es2::Program *programObject = context->getProgram(program);
2090
2091 if(!programObject)
2092 {
2093 return error(GL_INVALID_VALUE);
2094 }
2095
2096 if(index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
2097 {
2098 return error(GL_INVALID_VALUE);
2099 }
2100
2101 programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
2102 }
2103}
2104
2105GL_APICALL void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
2106{
2107 TRACE("(GLuint program = %d, GLuint index = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLsizei *size = %p, GLenum *type = %p, GLchar *name = %p)",
2108 index, size, type, stride, pointer);
2109
2110 if(index >= es2::MAX_VERTEX_ATTRIBS)
2111 {
2112 return error(GL_INVALID_VALUE);
2113 }
2114
2115 if(size < 1 || size > 4 || stride < 0)
2116 {
2117 return error(GL_INVALID_VALUE);
2118 }
2119
2120 switch(type)
2121 {
2122 case GL_BYTE:
2123 case GL_UNSIGNED_BYTE:
2124 case GL_SHORT:
2125 case GL_UNSIGNED_SHORT:
2126 case GL_INT:
2127 case GL_UNSIGNED_INT:
2128 break;
2129 default:
2130 return error(GL_INVALID_ENUM);
2131 }
2132
2133 es2::Context *context = es2::getContext();
2134
2135 if(context)
2136 {
Alexis Hetuc1ef1ad2017-11-15 10:50:10 -05002137 es2::VertexArray* vertexArray = context->getCurrentVertexArray();
2138 if((context->getArrayBufferName() == 0) && vertexArray && (vertexArray->name != 0) && pointer)
2139 {
2140 // GL_INVALID_OPERATION is generated if a non-zero vertex array object is bound, zero is bound
2141 // to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL.
2142 return error(GL_INVALID_OPERATION);
2143 }
2144
Nicolas Capens0bac2852016-05-07 06:09:58 -04002145 context->setVertexAttribState(index, context->getArrayBuffer(), size, type, false, stride, pointer);
2146 }
2147}
2148
2149GL_APICALL void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
2150{
2151 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLint *params = %p)",
2152 index, pname, params);
2153
2154 es2::Context *context = es2::getContext();
2155
2156 if(context)
2157 {
2158 if(index >= es2::MAX_VERTEX_ATTRIBS)
2159 {
2160 return error(GL_INVALID_VALUE);
2161 }
2162
2163 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2164
2165 switch(pname)
2166 {
2167 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2168 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2169 break;
2170 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2171 *params = attribState.mSize;
2172 break;
2173 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2174 *params = attribState.mStride;
2175 break;
2176 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2177 *params = attribState.mType;
2178 break;
2179 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2180 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2181 break;
2182 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2183 *params = attribState.mBoundBuffer.name();
2184 break;
2185 case GL_CURRENT_VERTEX_ATTRIB:
2186 {
2187 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2188 for(int i = 0; i < 4; ++i)
2189 {
2190 params[i] = attrib.getCurrentValueI(i);
2191 }
2192 }
2193 break;
2194 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2195 switch(attribState.mType)
2196 {
2197 case GL_BYTE:
2198 case GL_UNSIGNED_BYTE:
2199 case GL_SHORT:
2200 case GL_UNSIGNED_SHORT:
2201 case GL_INT:
2202 case GL_INT_2_10_10_10_REV:
2203 case GL_UNSIGNED_INT:
2204 case GL_FIXED:
2205 *params = GL_TRUE;
2206 break;
2207 default:
2208 *params = GL_FALSE;
2209 break;
2210 }
2211 break;
2212 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2213 *params = attribState.mDivisor;
2214 break;
2215 default: return error(GL_INVALID_ENUM);
2216 }
2217 }
2218}
2219
2220GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
2221{
2222 TRACE("(GLuint index = %d, GLenum pname = 0x%X, GLuint *params = %p)",
2223 index, pname, params);
2224
2225 es2::Context *context = es2::getContext();
2226
2227 if(context)
2228 {
2229 if(index >= es2::MAX_VERTEX_ATTRIBS)
2230 {
2231 return error(GL_INVALID_VALUE);
2232 }
2233
2234 const es2::VertexAttribute &attribState = context->getVertexAttribState(index);
2235
2236 switch(pname)
2237 {
2238 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
2239 *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE);
2240 break;
2241 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
2242 *params = attribState.mSize;
2243 break;
2244 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
2245 *params = attribState.mStride;
2246 break;
2247 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
2248 *params = attribState.mType;
2249 break;
2250 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
2251 *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE);
2252 break;
2253 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2254 *params = attribState.mBoundBuffer.name();
2255 break;
2256 case GL_CURRENT_VERTEX_ATTRIB:
2257 {
2258 const VertexAttribute& attrib = context->getCurrentVertexAttributes()[index];
2259 for(int i = 0; i < 4; ++i)
2260 {
2261 params[i] = attrib.getCurrentValueUI(i);
2262 }
2263 }
2264 break;
2265 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2266 switch(attribState.mType)
2267 {
2268 case GL_BYTE:
2269 case GL_UNSIGNED_BYTE:
2270 case GL_SHORT:
2271 case GL_UNSIGNED_SHORT:
2272 case GL_INT:
2273 case GL_INT_2_10_10_10_REV:
2274 case GL_UNSIGNED_INT:
2275 case GL_FIXED:
2276 *params = GL_TRUE;
2277 break;
2278 default:
2279 *params = GL_FALSE;
2280 break;
2281 }
2282 break;
2283 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
2284 *params = attribState.mDivisor;
2285 break;
2286 default: return error(GL_INVALID_ENUM);
2287 }
2288 }
2289}
2290
2291GL_APICALL void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
2292{
2293 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2294 index, x, y, z, w);
2295
2296 if(index >= es2::MAX_VERTEX_ATTRIBS)
2297 {
2298 return error(GL_INVALID_VALUE);
2299 }
2300
2301 es2::Context *context = es2::getContext();
2302
2303 if(context)
2304 {
2305 GLint vals[4] = { x, y, z, w };
2306 context->setVertexAttrib(index, vals);
2307 }
2308}
2309
2310GL_APICALL void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
2311{
2312 TRACE("(GLuint index = %d, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
2313 index, x, y, z, w);
2314
2315 if(index >= es2::MAX_VERTEX_ATTRIBS)
2316 {
2317 return error(GL_INVALID_VALUE);
2318 }
2319
2320 es2::Context *context = es2::getContext();
2321
2322 if(context)
2323 {
2324 GLuint vals[4] = { x, y, z, w };
2325 context->setVertexAttrib(index, vals);
2326 }
2327}
2328
2329GL_APICALL void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)
2330{
2331 TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2332
2333 if(index >= es2::MAX_VERTEX_ATTRIBS)
2334 {
2335 return error(GL_INVALID_VALUE);
2336 }
2337
2338 es2::Context *context = es2::getContext();
2339
2340 if(context)
2341 {
2342 context->setVertexAttrib(index, v);
2343 }
2344}
2345
2346GL_APICALL void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)
2347{
2348 TRACE("(GLuint index = %d, GLint *v = %p)", index, v);
2349
2350 if(index >= es2::MAX_VERTEX_ATTRIBS)
2351 {
2352 return error(GL_INVALID_VALUE);
2353 }
2354
2355 es2::Context *context = es2::getContext();
2356
2357 if(context)
2358 {
2359 context->setVertexAttrib(index, v);
2360 }
2361}
2362
2363GL_APICALL void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)
2364{
2365 TRACE("(GLuint program = %d, GLint location = %d, GLuint *params = %p)",
2366 program, location, params);
2367
2368 es2::Context *context = es2::getContext();
2369
2370 if(context)
2371 {
2372 if(program == 0)
2373 {
2374 return error(GL_INVALID_VALUE);
2375 }
2376
2377 es2::Program *programObject = context->getProgram(program);
2378
2379 if(!programObject || !programObject->isLinked())
2380 {
2381 return error(GL_INVALID_OPERATION);
2382 }
2383
2384 if(!programObject)
2385 {
2386 return error(GL_INVALID_OPERATION);
2387 }
2388
2389 if(!programObject->getUniformuiv(location, nullptr, params))
2390 {
2391 return error(GL_INVALID_OPERATION);
2392 }
2393 }
2394}
2395
2396GL_APICALL GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
2397{
2398 TRACE("(GLuint program = %d, const GLchar *name = %p)", program, name);
2399
2400 es2::Context *context = es2::getContext();
2401
Nicolas Capens0bac2852016-05-07 06:09:58 -04002402 if(context)
2403 {
2404 es2::Program *programObject = context->getProgram(program);
2405
2406 if(!programObject)
2407 {
2408 if(context->getShader(program))
2409 {
2410 return error(GL_INVALID_OPERATION, -1);
2411 }
2412 else
2413 {
2414 return error(GL_INVALID_VALUE, -1);
2415 }
2416 }
2417
2418 if(!programObject->isLinked())
2419 {
2420 return error(GL_INVALID_OPERATION, -1);
2421 }
Alexis Hetub3f5ed72017-08-16 16:37:19 -04002422
2423 return programObject->getFragDataLocation(name);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002424 }
2425
Nicolas Capens0bac2852016-05-07 06:09:58 -04002426 return -1;
2427}
2428
2429GL_APICALL void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
2430{
2431 glUniform1uiv(location, 1, &v0);
2432}
2433
2434GL_APICALL void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
2435{
2436 GLuint xy[2] = { v0, v1 };
2437
2438 glUniform2uiv(location, 1, (GLuint*)&xy);
2439}
2440
2441GL_APICALL void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
2442{
2443 GLuint xyz[3] = { v0, v1, v2 };
2444
2445 glUniform3uiv(location, 1, (GLuint*)&xyz);
2446}
2447
2448GL_APICALL void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
2449{
2450 GLuint xyzw[4] = { v0, v1, v2, v3 };
2451
2452 glUniform4uiv(location, 1, (GLuint*)&xyzw);
2453}
2454
2455GL_APICALL void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
2456{
2457 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2458 location, count, value);
2459
2460 if(count < 0)
2461 {
2462 return error(GL_INVALID_VALUE);
2463 }
2464
2465 if(location == -1)
2466 {
2467 return;
2468 }
2469
2470 es2::Context *context = es2::getContext();
2471
2472 if(context)
2473 {
2474 es2::Program *program = context->getCurrentProgram();
2475
2476 if(!program)
2477 {
2478 return error(GL_INVALID_OPERATION);
2479 }
2480
2481 if(!program->setUniform1uiv(location, count, value))
2482 {
2483 return error(GL_INVALID_OPERATION);
2484 }
2485 }
2486}
2487
2488GL_APICALL void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
2489{
2490 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2491 location, count, value);
2492
2493 if(count < 0)
2494 {
2495 return error(GL_INVALID_VALUE);
2496 }
2497
2498 if(location == -1)
2499 {
2500 return;
2501 }
2502
2503 es2::Context *context = es2::getContext();
2504
2505 if(context)
2506 {
2507 es2::Program *program = context->getCurrentProgram();
2508
2509 if(!program)
2510 {
2511 return error(GL_INVALID_OPERATION);
2512 }
2513
2514 if(!program->setUniform2uiv(location, count, value))
2515 {
2516 return error(GL_INVALID_OPERATION);
2517 }
2518 }
2519}
2520
2521GL_APICALL void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
2522{
2523 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2524 location, count, value);
2525
2526 if(count < 0)
2527 {
2528 return error(GL_INVALID_VALUE);
2529 }
2530
2531 if(location == -1)
2532 {
2533 return;
2534 }
2535
2536 es2::Context *context = es2::getContext();
2537
2538 if(context)
2539 {
2540 es2::Program *program = context->getCurrentProgram();
2541
2542 if(!program)
2543 {
2544 return error(GL_INVALID_OPERATION);
2545 }
2546
2547 if(!program->setUniform3uiv(location, count, value))
2548 {
2549 return error(GL_INVALID_OPERATION);
2550 }
2551 }
2552}
2553
2554GL_APICALL void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
2555{
2556 TRACE("(GLint location = %d, GLsizei count = %d, const GLuint *value = %p)",
2557 location, count, value);
2558
2559 if(count < 0)
2560 {
2561 return error(GL_INVALID_VALUE);
2562 }
2563
2564 if(location == -1)
2565 {
2566 return;
2567 }
2568
2569 es2::Context *context = es2::getContext();
2570
2571 if(context)
2572 {
2573 es2::Program *program = context->getCurrentProgram();
2574
2575 if(!program)
2576 {
2577 return error(GL_INVALID_OPERATION);
2578 }
2579
2580 if(!program->setUniform4uiv(location, count, value))
2581 {
2582 return error(GL_INVALID_OPERATION);
2583 }
2584 }
2585}
2586
2587GL_APICALL void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
2588{
2589 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = %p)",
2590 buffer, drawbuffer, value);
2591
2592 es2::Context *context = es2::getContext();
2593
2594 if(context)
2595 {
2596 switch(buffer)
2597 {
2598 case GL_COLOR:
2599 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2600 {
2601 return error(GL_INVALID_VALUE);
2602 }
2603 else
2604 {
2605 context->clearColorBuffer(drawbuffer, value);
2606 }
2607 break;
2608 case GL_STENCIL:
2609 if(drawbuffer != 0)
2610 {
2611 return error(GL_INVALID_VALUE);
2612 }
2613 else
2614 {
2615 context->clearStencilBuffer(value[0]);
2616 }
2617 break;
2618 default:
2619 return error(GL_INVALID_ENUM);
2620 }
2621 }
2622}
2623
2624GL_APICALL void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
2625{
2626 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = %p)",
2627 buffer, drawbuffer, value);
2628
2629 es2::Context *context = es2::getContext();
2630
2631 if(context)
2632 {
2633 switch(buffer)
2634 {
2635 case GL_COLOR:
2636 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2637 {
2638 return error(GL_INVALID_VALUE);
2639 }
2640 else
2641 {
2642 context->clearColorBuffer(drawbuffer, value);
2643 }
2644 break;
2645 default:
2646 return error(GL_INVALID_ENUM);
2647 }
2648 }
2649}
2650
2651GL_APICALL void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
2652{
2653 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = %p)",
2654 buffer, drawbuffer, value);
2655
2656 es2::Context *context = es2::getContext();
2657
2658 if(context)
2659 {
2660 switch(buffer)
2661 {
2662 case GL_COLOR:
2663 if(drawbuffer < 0 || drawbuffer >= MAX_DRAW_BUFFERS)
2664 {
2665 return error(GL_INVALID_VALUE);
2666 }
2667 else
2668 {
2669 context->clearColorBuffer(drawbuffer, value);
2670 }
2671 break;
2672 case GL_DEPTH:
2673 if(drawbuffer != 0)
2674 {
2675 return error(GL_INVALID_VALUE);
2676 }
2677 else
2678 {
2679 context->clearDepthBuffer(value[0]);
2680 }
2681 break;
2682 default:
2683 return error(GL_INVALID_ENUM);
2684 }
2685 }
2686}
2687
2688GL_APICALL void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
2689{
2690 TRACE("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
2691 buffer, drawbuffer, depth, stencil);
2692
2693 es2::Context *context = es2::getContext();
2694
2695 if(context)
2696 {
2697 switch(buffer)
2698 {
2699 case GL_DEPTH_STENCIL:
2700 if(drawbuffer != 0)
2701 {
2702 return error(GL_INVALID_VALUE);
2703 }
2704 else
2705 {
2706 context->clearDepthBuffer(depth);
2707 context->clearStencilBuffer(stencil);
2708 }
2709 break;
2710 default:
2711 return error(GL_INVALID_ENUM);
2712 }
2713 }
2714}
2715
2716GL_APICALL const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
2717{
2718 TRACE("(GLenum name = 0x%X, GLuint index = %d)", name, index);
2719
2720 es2::Context *context = es2::getContext();
2721 if(context)
2722 {
2723 GLuint numExtensions;
2724 context->getExtensions(0, &numExtensions);
2725
2726 if(index >= numExtensions)
2727 {
2728 return error(GL_INVALID_VALUE, (GLubyte*)nullptr);
2729 }
2730
2731 switch(name)
2732 {
2733 case GL_EXTENSIONS:
2734 return context->getExtensions(index);
2735 default:
2736 return error(GL_INVALID_ENUM, (GLubyte*)nullptr);
2737 }
2738 }
2739
2740 return (GLubyte*)nullptr;
2741}
2742
2743GL_APICALL void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
2744{
2745 TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
2746 readTarget, writeTarget, readOffset, writeOffset, size);
2747
2748 if(readOffset < 0 || writeOffset < 0 || size < 0)
2749 {
2750 return error(GL_INVALID_VALUE);
2751 }
2752
2753 es2::Context *context = es2::getContext();
2754
2755 if(context)
2756 {
2757 es2::Buffer *readBuffer = nullptr, *writeBuffer = nullptr;
2758 if(!context->getBuffer(readTarget, &readBuffer) || !context->getBuffer(writeTarget, &writeBuffer))
2759 {
2760 return error(GL_INVALID_ENUM);
2761 }
2762 if(!readBuffer || readBuffer->isMapped() || !writeBuffer || writeBuffer->isMapped())
2763 {
2764 return error(GL_INVALID_OPERATION);
2765 }
2766 if(readBuffer == writeBuffer)
2767 {
2768 // If same buffer, check for overlap
2769 if(((readOffset >= writeOffset) && (readOffset < (writeOffset + size))) ||
2770 ((writeOffset >= readOffset) && (writeOffset < (readOffset + size))))
2771 {
2772 return error(GL_INVALID_VALUE);
2773 }
2774 }
2775
2776 if((static_cast<size_t>(readOffset + size) > readBuffer->size()) ||
2777 (static_cast<size_t>(writeOffset + size) > writeBuffer->size()))
2778 {
2779 return error(GL_INVALID_VALUE);
2780 }
2781
2782 writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset);
2783 }
2784}
2785
2786GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
2787{
2788 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)",
2789 program, uniformCount, uniformNames, uniformIndices);
2790
2791 if(uniformCount < 0)
2792 {
2793 return error(GL_INVALID_VALUE);
2794 }
2795
2796 es2::Context *context = es2::getContext();
2797
2798 if(context)
2799 {
2800 es2::Program *programObject = context->getProgram(program);
2801
2802 if(!programObject)
2803 {
2804 return error(GL_INVALID_OPERATION);
2805 }
2806
2807 if(!programObject->isLinked())
2808 {
2809 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2810 {
2811 uniformIndices[uniformId] = GL_INVALID_INDEX;
2812 }
2813 }
2814 else
2815 {
2816 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2817 {
2818 uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
2819 }
2820 }
2821 }
2822}
2823
2824GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
2825{
2826 TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLenum pname = 0x%X, GLuint *uniformIndices = %p)",
2827 program, uniformCount, uniformIndices, pname, uniformIndices);
2828
2829 switch(pname)
2830 {
2831 case GL_UNIFORM_TYPE:
2832 case GL_UNIFORM_SIZE:
2833 case GL_UNIFORM_NAME_LENGTH:
2834 case GL_UNIFORM_BLOCK_INDEX:
2835 case GL_UNIFORM_OFFSET:
2836 case GL_UNIFORM_ARRAY_STRIDE:
2837 case GL_UNIFORM_MATRIX_STRIDE:
2838 case GL_UNIFORM_IS_ROW_MAJOR:
2839 break;
2840 default:
2841 return error(GL_INVALID_ENUM);
2842 }
2843
2844 if(uniformCount < 0)
2845 {
2846 return error(GL_INVALID_VALUE);
2847 }
2848
2849 es2::Context *context = es2::getContext();
2850
2851 if(context)
2852 {
2853 es2::Program *programObject = context->getProgram(program);
2854
2855 if(!programObject)
2856 {
2857 return error(GL_INVALID_OPERATION);
2858 }
2859
2860 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2861 {
2862 const GLuint index = uniformIndices[uniformId];
2863
2864 if(index >= programObject->getActiveUniformCount())
2865 {
2866 return error(GL_INVALID_VALUE);
2867 }
2868 }
2869
2870 for(int uniformId = 0; uniformId < uniformCount; uniformId++)
2871 {
2872 const GLuint index = uniformIndices[uniformId];
2873 params[uniformId] = programObject->getActiveUniformi(index, pname);
2874 }
2875 }
2876}
2877
2878GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
2879{
2880 TRACE("(GLuint program = %d, const GLchar *uniformBlockName = %p)",
2881 program, uniformBlockName);
2882
2883 es2::Context *context = es2::getContext();
2884
2885 if(context)
2886 {
2887 es2::Program *programObject = context->getProgram(program);
2888
2889 if(!programObject)
2890 {
2891 return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
2892 }
2893
2894 return programObject->getUniformBlockIndex(uniformBlockName);
2895 }
2896
2897 return GL_INVALID_INDEX;
2898}
2899
2900GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
2901{
2902 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)",
2903 program, uniformBlockIndex, pname, params);
2904
2905 es2::Context *context = es2::getContext();
2906
2907 if(context)
2908 {
2909 es2::Program *programObject = context->getProgram(program);
2910
2911 if(!programObject)
2912 {
2913 return error(GL_INVALID_OPERATION);
2914 }
2915
2916 switch(pname)
2917 {
2918 case GL_UNIFORM_BLOCK_BINDING:
2919 *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
2920 break;
2921 case GL_UNIFORM_BLOCK_DATA_SIZE:
2922 case GL_UNIFORM_BLOCK_NAME_LENGTH:
2923 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2924 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2925 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2926 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2927 programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
2928 break;
2929 default:
2930 return error(GL_INVALID_ENUM);
2931 }
2932 }
2933}
2934
2935GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
2936{
2937 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLchar *uniformBlockName = %p)",
2938 program, uniformBlockIndex, bufSize, length, uniformBlockName);
2939
2940 if(bufSize < 0)
2941 {
2942 return error(GL_INVALID_VALUE);
2943 }
2944
2945 es2::Context *context = es2::getContext();
2946
2947 if(context)
2948 {
2949 es2::Program *programObject = context->getProgram(program);
2950
2951 if(!programObject)
2952 {
2953 return error(GL_INVALID_OPERATION);
2954 }
2955
2956 programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
2957 }
2958}
2959
2960GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2961{
2962 TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",
2963 program, uniformBlockIndex, uniformBlockBinding);
2964
2965 if(uniformBlockBinding >= MAX_UNIFORM_BUFFER_BINDINGS)
2966 {
2967 return error(GL_INVALID_VALUE);
2968 }
2969
2970 es2::Context *context = es2::getContext();
2971
2972 if(context)
2973 {
2974 es2::Program *programObject = context->getProgram(program);
2975
2976 if(!programObject)
2977 {
2978 return error(GL_INVALID_VALUE);
2979 }
2980
Nicolas Capens65dcbbd2016-08-12 16:59:04 -04002981 programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002982 }
2983}
2984
2985GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
2986{
2987 TRACE("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
2988 mode, first, count, instanceCount);
2989
2990 switch(mode)
2991 {
2992 case GL_POINTS:
2993 case GL_LINES:
2994 case GL_LINE_LOOP:
2995 case GL_LINE_STRIP:
2996 case GL_TRIANGLES:
2997 case GL_TRIANGLE_FAN:
2998 case GL_TRIANGLE_STRIP:
2999 break;
3000 default:
3001 return error(GL_INVALID_ENUM);
3002 }
3003
3004 if(count < 0 || instanceCount < 0)
3005 {
3006 return error(GL_INVALID_VALUE);
3007 }
3008
3009 es2::Context *context = es2::getContext();
3010
3011 if(context)
3012 {
3013 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
3014 if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
3015 {
3016 return error(GL_INVALID_OPERATION);
3017 }
3018
3019 context->drawArrays(mode, first, count, instanceCount);
3020 }
3021}
3022
3023GL_APICALL void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount)
3024{
3025 TRACE("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = %p, GLsizei instanceCount = %d)",
3026 mode, count, type, indices, instanceCount);
3027
3028 switch(mode)
3029 {
3030 case GL_POINTS:
3031 case GL_LINES:
3032 case GL_LINE_LOOP:
3033 case GL_LINE_STRIP:
3034 case GL_TRIANGLES:
3035 case GL_TRIANGLE_FAN:
3036 case GL_TRIANGLE_STRIP:
3037 break;
3038 default:
3039 return error(GL_INVALID_ENUM);
3040 }
3041
3042 switch(type)
3043 {
3044 case GL_UNSIGNED_BYTE:
3045 case GL_UNSIGNED_SHORT:
3046 case GL_UNSIGNED_INT:
3047 break;
3048 default:
3049 return error(GL_INVALID_ENUM);
3050 }
3051
3052 if(count < 0 || instanceCount < 0)
3053 {
3054 return error(GL_INVALID_VALUE);
3055 }
3056
3057 es2::Context *context = es2::getContext();
3058
3059 if(context)
3060 {
3061 es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
3062 if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
3063 {
3064 return error(GL_INVALID_OPERATION);
3065 }
3066
3067 context->drawElements(mode, 0, MAX_ELEMENT_INDEX, count, type, indices, instanceCount);
3068 }
3069}
3070
3071GL_APICALL GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
3072{
3073 TRACE("(GLenum condition = 0x%X, GLbitfield flags = %X)", condition, flags);
3074
3075 switch(condition)
3076 {
3077 case GL_SYNC_GPU_COMMANDS_COMPLETE:
3078 break;
3079 default:
3080 return error(GL_INVALID_ENUM, nullptr);
3081 }
3082
3083 if(flags != 0)
3084 {
3085 return error(GL_INVALID_VALUE, nullptr);
3086 }
3087
3088 es2::Context *context = es2::getContext();
3089
3090 if(context)
3091 {
3092 return context->createFenceSync(condition, flags);
3093 }
3094
3095 return nullptr;
3096}
3097
3098GL_APICALL GLboolean GL_APIENTRY glIsSync(GLsync sync)
3099{
3100 TRACE("(GLsync sync = %p)", sync);
3101
3102 es2::Context *context = es2::getContext();
3103
3104 if(context)
3105 {
3106 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3107
3108 if(fenceSyncObject)
3109 {
3110 return GL_TRUE;
3111 }
3112 }
3113
3114 return GL_FALSE;
3115}
3116
3117GL_APICALL void GL_APIENTRY glDeleteSync(GLsync sync)
3118{
3119 TRACE("(GLsync sync = %p)", sync);
3120
Alexis Hetuadd96ad2017-11-14 17:22:46 -05003121 if(!sync)
3122 {
3123 return;
3124 }
3125
Nicolas Capens0bac2852016-05-07 06:09:58 -04003126 es2::Context *context = es2::getContext();
3127
3128 if(context)
3129 {
Alexis Hetuadd96ad2017-11-14 17:22:46 -05003130 if(!context->getFenceSync(sync))
3131 {
3132 return error(GL_INVALID_VALUE);
3133 }
3134
Nicolas Capens0bac2852016-05-07 06:09:58 -04003135 context->deleteFenceSync(sync);
3136 }
3137}
3138
3139GL_APICALL GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3140{
3141 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3142
3143 if((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3144 {
Alexis Hetu6e864492017-11-14 15:27:00 -05003145 return error(GL_INVALID_VALUE, GL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003146 }
3147
3148 es2::Context *context = es2::getContext();
3149
3150 if(context)
3151 {
3152 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3153
3154 if(fenceSyncObject)
3155 {
3156 return fenceSyncObject->clientWait(flags, timeout);
3157 }
3158 else
3159 {
3160 return error(GL_INVALID_VALUE, GL_FALSE);
3161 }
3162 }
3163
3164 return GL_FALSE;
3165}
3166
3167GL_APICALL void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
3168{
3169 TRACE("(GLsync sync = %p, GLbitfield flags = %X, GLuint64 timeout = %llu)", sync, flags, timeout);
3170
3171 if(flags != 0)
3172 {
3173 return error(GL_INVALID_VALUE);
3174 }
3175
3176 if(timeout != GL_TIMEOUT_IGNORED)
3177 {
3178 return error(GL_INVALID_VALUE);
3179 }
3180
3181 es2::Context *context = es2::getContext();
3182
3183 if(context)
3184 {
3185 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3186
3187 if(fenceSyncObject)
3188 {
3189 fenceSyncObject->serverWait(flags, timeout);
3190 }
3191 else
3192 {
3193 return error(GL_INVALID_VALUE);
3194 }
3195 }
3196}
3197
3198GL_APICALL void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *data)
3199{
3200 TRACE("(GLenum pname = 0x%X, GLint64 *data = %p)", pname, data);
3201
3202 es2::Context *context = es2::getContext();
3203
3204 if(context)
3205 {
3206 if(!(context->getIntegerv(pname, data)))
3207 {
3208 GLenum nativeType;
3209 unsigned int numParams = 0;
3210 if(!context->getQueryParameterInfo(pname, &nativeType, &numParams))
3211 return error(GL_INVALID_ENUM);
3212
3213 if(numParams == 0)
3214 return; // it is known that pname is valid, but there are no parameters to return
3215
3216 if(nativeType == GL_BOOL)
3217 {
3218 GLboolean *boolParams = nullptr;
3219 boolParams = new GLboolean[numParams];
3220
3221 context->getBooleanv(pname, boolParams);
3222
3223 for(unsigned int i = 0; i < numParams; ++i)
3224 {
3225 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3226 }
3227
3228 delete[] boolParams;
3229 }
3230 else if(nativeType == GL_FLOAT)
3231 {
3232 GLfloat *floatParams = nullptr;
3233 floatParams = new GLfloat[numParams];
3234
3235 context->getFloatv(pname, floatParams);
3236
3237 for(unsigned int i = 0; i < numParams; ++i)
3238 {
3239 if(pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
3240 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003241 data[i] = (GLint64)(convert_float_int(floatParams[i]));
Nicolas Capens0bac2852016-05-07 06:09:58 -04003242 }
3243 else
3244 {
3245 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3246 }
3247 }
3248
3249 delete[] floatParams;
3250 }
3251 }
3252 }
3253}
3254
3255GL_APICALL void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
3256{
3257 TRACE("(GLsync sync = %p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = %p, GLint *values = %p)",
3258 sync, pname, bufSize, length, values);
3259
3260 if(bufSize < 0)
3261 {
3262 return error(GL_INVALID_VALUE);
3263 }
3264
Alexis Hetu0f7c7b82017-02-17 17:07:50 -05003265 es2::Context *context = es2::getContext();
3266
3267 if(context)
3268 {
3269 es2::FenceSync *fenceSyncObject = context->getFenceSync(sync);
3270 if(!fenceSyncObject)
3271 {
3272 return error(GL_INVALID_VALUE);
3273 }
3274
3275 fenceSyncObject->getSynciv(pname, length, values);
3276 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04003277}
3278
3279GL_APICALL void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
3280{
3281 TRACE("(GLenum target = 0x%X, GLuint index = %d, GLint64 *data = %p)", target, index, data);
3282
3283 es2::Context *context = es2::getContext();
3284
3285 if(context)
3286 {
3287 if(!context->getTransformFeedbackiv(index, target, data) &&
3288 !context->getUniformBufferiv(index, target, data) &&
3289 !context->getIntegerv(target, data))
3290 {
3291 GLenum nativeType;
3292 unsigned int numParams = 0;
3293 if(!context->getQueryParameterInfo(target, &nativeType, &numParams))
3294 return error(GL_INVALID_ENUM);
3295
3296 if(numParams == 0)
3297 return; // it is known that target is valid, but there are no parameters to return
3298
3299 if(nativeType == GL_BOOL)
3300 {
3301 GLboolean *boolParams = nullptr;
3302 boolParams = new GLboolean[numParams];
3303
3304 context->getBooleanv(target, boolParams);
3305
3306 for(unsigned int i = 0; i < numParams; ++i)
3307 {
3308 data[i] = (boolParams[i] == GL_FALSE) ? 0 : 1;
3309 }
3310
3311 delete[] boolParams;
3312 }
3313 else if(nativeType == GL_FLOAT)
3314 {
3315 GLfloat *floatParams = nullptr;
3316 floatParams = new GLfloat[numParams];
3317
3318 context->getFloatv(target, floatParams);
3319
3320 for(unsigned int i = 0; i < numParams; ++i)
3321 {
3322 if(target == GL_DEPTH_RANGE || target == GL_COLOR_CLEAR_VALUE || target == GL_DEPTH_CLEAR_VALUE || target == GL_BLEND_COLOR)
3323 {
Nicolas Capens53318fa2016-04-11 17:41:39 -04003324 data[i] = (GLint64)(convert_float_int(floatParams[i]));
Nicolas Capens0bac2852016-05-07 06:09:58 -04003325 }
3326 else
3327 {
3328 data[i] = (GLint64)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5));
3329 }
3330 }
3331
3332 delete[] floatParams;
3333 }
3334 }
3335 }
3336}
3337
3338GL_APICALL void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
3339{
3340 TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = %p)", target, pname, params);
3341
3342 es2::Context *context = es2::getContext();
3343
3344 if(context)
3345 {
3346 es2::Buffer *buffer = nullptr;
3347
3348 if(!context->getBuffer(target, &buffer))
3349 {
3350 return error(GL_INVALID_ENUM);
3351 }
3352
3353 if(!buffer)
3354 {
3355 // A null buffer means that "0" is bound to the requested buffer target
3356 return error(GL_INVALID_OPERATION);
3357 }
3358
3359 switch(pname)
3360 {
3361 case GL_BUFFER_USAGE:
3362 *params = buffer->usage();
3363 break;
3364 case GL_BUFFER_SIZE:
3365 *params = buffer->size();
3366 break;
3367 case GL_BUFFER_ACCESS_FLAGS:
3368 *params = buffer->access();
3369 break;
3370 case GL_BUFFER_MAPPED:
3371 *params = buffer->isMapped();
3372 break;
3373 case GL_BUFFER_MAP_LENGTH:
3374 *params = buffer->length();
3375 break;
3376 case GL_BUFFER_MAP_OFFSET:
3377 *params = buffer->offset();
3378 break;
3379 default:
3380 return error(GL_INVALID_ENUM);
3381 }
3382 }
3383}
3384
3385GL_APICALL void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)
3386{
3387 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3388
3389 if(count < 0)
3390 {
3391 return error(GL_INVALID_VALUE);
3392 }
3393
3394 es2::Context *context = es2::getContext();
3395
3396 if(context)
3397 {
3398 for(int i = 0; i < count; i++)
3399 {
3400 samplers[i] = context->createSampler();
3401 }
3402 }
3403}
3404
3405GL_APICALL void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
3406{
3407 TRACE("(GLsizei count = %d, GLuint *samplers = %p)", count, samplers);
3408
3409 if(count < 0)
3410 {
3411 return error(GL_INVALID_VALUE);
3412 }
3413
3414 es2::Context *context = es2::getContext();
3415
3416 if(context)
3417 {
3418 for(int i = 0; i < count; i++)
3419 {
3420 context->deleteSampler(samplers[i]);
3421 }
3422 }
3423}
3424
3425GL_APICALL GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
3426{
3427 TRACE("(GLuint sampler = %d)", sampler);
3428
3429 if(sampler == 0)
3430 {
3431 return GL_FALSE;
3432 }
3433
3434 es2::Context *context = es2::getContext();
3435
3436 if(context)
3437 {
3438 if(context->isSampler(sampler))
3439 {
3440 return GL_TRUE;
3441 }
3442 }
3443
3444 return GL_FALSE;
3445}
3446
3447GL_APICALL void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
3448{
3449 TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler);
3450
3451 if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3452 {
3453 return error(GL_INVALID_VALUE);
3454 }
3455
3456 es2::Context *context = es2::getContext();
3457
3458 if(context)
3459 {
3460 if(sampler != 0 && !context->isSampler(sampler))
3461 {
3462 return error(GL_INVALID_OPERATION);
3463 }
3464
3465 context->bindSampler(unit, sampler);
3466 }
3467}
3468
3469GL_APICALL void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
3470{
3471 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint param = %d)",
3472 sampler, pname, param);
3473
3474 glSamplerParameteriv(sampler, pname, &param);
3475}
3476
3477GL_APICALL void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
3478{
3479 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = %p)",
3480 sampler, pname, param);
3481
3482 if(!ValidateSamplerObjectParameter(pname))
3483 {
3484 return error(GL_INVALID_ENUM);
3485 }
3486
3487 if(!ValidateTexParamParameters(pname, *param))
3488 {
3489 return;
3490 }
3491
3492 es2::Context *context = es2::getContext();
3493
3494 if(context)
3495 {
3496 if(!context->isSampler(sampler))
3497 {
3498 return error(GL_INVALID_OPERATION);
3499 }
3500
3501 context->samplerParameteri(sampler, pname, *param);
3502 }
3503}
3504
3505GL_APICALL void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
3506{
3507 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat param = %f)",
3508 sampler, pname, param);
3509
3510 glSamplerParameterfv(sampler, pname, &param);
3511}
3512
3513GL_APICALL void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
3514{
3515 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = %p)",
3516 sampler, pname, param);
3517
3518 if(!ValidateSamplerObjectParameter(pname))
3519 {
3520 return error(GL_INVALID_ENUM);
3521 }
3522
Alexis Hetub34591a2016-06-28 15:48:35 -04003523 if(!ValidateTexParamParameters(pname, static_cast<GLint>(roundf(*param))))
Nicolas Capens0bac2852016-05-07 06:09:58 -04003524 {
3525 return;
3526 }
3527
3528 es2::Context *context = es2::getContext();
3529
3530 if(context)
3531 {
3532 if(!context->isSampler(sampler))
3533 {
3534 return error(GL_INVALID_OPERATION);
3535 }
3536
3537 context->samplerParameterf(sampler, pname, *param);
3538 }
3539}
3540
3541GL_APICALL void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
3542{
3543 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = %p)",
3544 sampler, pname, params);
3545
3546 if(!ValidateSamplerObjectParameter(pname))
3547 {
3548 return error(GL_INVALID_ENUM);
3549 }
3550
3551 es2::Context *context = es2::getContext();
3552
3553 if(context)
3554 {
3555 if(!context->isSampler(sampler))
3556 {
3557 return error(GL_INVALID_VALUE);
3558 }
3559
3560 *params = context->getSamplerParameteri(sampler, pname);
3561 }
3562}
3563
3564GL_APICALL void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
3565{
3566 TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = %p)",
3567 sampler, pname, params);
3568
3569 if(!ValidateSamplerObjectParameter(pname))
3570 {
3571 return error(GL_INVALID_ENUM);
3572 }
3573
3574 es2::Context *context = es2::getContext();
3575
3576 if(context)
3577 {
3578 if(!context->isSampler(sampler))
3579 {
3580 return error(GL_INVALID_VALUE);
3581 }
3582
3583 *params = context->getSamplerParameterf(sampler, pname);
3584 }
3585}
3586
3587GL_APICALL void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
3588{
3589 TRACE("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
3590
3591 es2::Context *context = es2::getContext();
3592
3593 if(context)
3594 {
3595 if(index >= es2::MAX_VERTEX_ATTRIBS)
3596 {
3597 return error(GL_INVALID_VALUE);
3598 }
3599
3600 context->setVertexAttribDivisor(index, divisor);
3601 }
3602}
3603
3604GL_APICALL void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
3605{
3606 TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);
3607
3608 if(target != GL_TRANSFORM_FEEDBACK)
3609 {
3610 return error(GL_INVALID_ENUM);
3611 }
3612
3613 es2::Context *context = es2::getContext();
3614
3615 if(context)
3616 {
3617 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3618
3619 if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused())
3620 {
3621 return error(GL_INVALID_OPERATION);
3622 }
3623
Alexis Hetu5bf97082017-11-14 11:06:03 -05003624 if(!context->isTransformFeedback(id))
3625 {
3626 return error(GL_INVALID_OPERATION);
3627 }
3628
Nicolas Capens0bac2852016-05-07 06:09:58 -04003629 context->bindTransformFeedback(id);
3630 }
3631}
3632
3633GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
3634{
3635 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3636
3637 if(n < 0)
3638 {
3639 return error(GL_INVALID_VALUE);
3640 }
3641
3642 es2::Context *context = es2::getContext();
3643
3644 if(context)
3645 {
3646 for(int i = 0; i < n; i++)
3647 {
3648 if(ids[i] != 0)
3649 {
Alexis Hetu5bf97082017-11-14 11:06:03 -05003650 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(ids[i]);
3651
3652 if(transformFeedbackObject && transformFeedbackObject->isActive())
3653 {
3654 return error(GL_INVALID_OPERATION);
3655 }
3656
Nicolas Capens0bac2852016-05-07 06:09:58 -04003657 context->deleteTransformFeedback(ids[i]);
3658 }
3659 }
3660 }
3661}
3662
3663GL_APICALL void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
3664{
3665 TRACE("(GLsizei n = %d, const GLuint *ids = %p)", n, ids);
3666
3667 if(n < 0)
3668 {
3669 return error(GL_INVALID_VALUE);
3670 }
3671
3672 es2::Context *context = es2::getContext();
3673
3674 if(context)
3675 {
3676 for(int i = 0; i < n; i++)
3677 {
3678 ids[i] = context->createTransformFeedback();
3679 }
3680 }
3681}
3682
3683GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
3684{
3685 TRACE("(GLuint id = %d)", id);
3686
3687 if(id == 0)
3688 {
3689 return GL_FALSE;
3690 }
3691
3692 es2::Context *context = es2::getContext();
3693
3694 if(context)
3695 {
3696 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id);
3697
3698 if(transformFeedbackObject)
3699 {
3700 return GL_TRUE;
3701 }
3702 }
3703
3704 return GL_FALSE;
3705}
3706
3707GL_APICALL void GL_APIENTRY glPauseTransformFeedback(void)
3708{
3709 TRACE("()");
3710
3711 es2::Context *context = es2::getContext();
3712
3713 if(context)
3714 {
3715 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3716
3717 if(transformFeedbackObject)
3718 {
3719 if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused())
3720 {
3721 return error(GL_INVALID_OPERATION);
3722 }
3723 transformFeedbackObject->setPaused(true);
3724 }
3725 }
3726}
3727
3728GL_APICALL void GL_APIENTRY glResumeTransformFeedback(void)
3729{
3730 TRACE("()");
3731
3732 es2::Context *context = es2::getContext();
3733
3734 if(context)
3735 {
3736 es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
3737
3738 if(transformFeedbackObject)
3739 {
3740 if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused())
3741 {
3742 return error(GL_INVALID_OPERATION);
3743 }
3744 transformFeedbackObject->setPaused(false);
3745 }
3746 }
3747}
3748
3749GL_APICALL void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
3750{
3751 TRACE("(GLuint program = %d, GLsizei bufSize = %d, GLsizei *length = %p, GLenum *binaryFormat = %p, void *binary = %p)",
3752 program, bufSize, length, binaryFormat, binary);
3753
3754 if(bufSize < 0)
3755 {
3756 return error(GL_INVALID_VALUE);
3757 }
3758
3759 UNIMPLEMENTED();
3760}
3761
3762GL_APICALL void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
3763{
3764 TRACE("(GLuint program = %d, GLenum binaryFormat = 0x%X, const void *binary = %p, GLsizei length = %d)",
3765 program, binaryFormat, binaryFormat, length);
3766
3767 if(length < 0)
3768 {
3769 return error(GL_INVALID_VALUE);
3770 }
3771
3772 UNIMPLEMENTED();
3773}
3774
3775GL_APICALL void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
3776{
3777 TRACE("(GLuint program = %d, GLenum pname = 0x%X, GLint value = %d)",
3778 program, pname, value);
3779
3780 es2::Context *context = es2::getContext();
3781
3782 if(context)
3783 {
3784 es2::Program *programObject = context->getProgram(program);
3785
3786 if(!programObject)
3787 {
3788 return error(GL_INVALID_OPERATION);
3789 }
3790
3791 switch(pname)
3792 {
3793 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3794 programObject->setBinaryRetrievable(value != GL_FALSE);
3795 break;
3796 default:
3797 return error(GL_INVALID_ENUM);
3798 }
3799 }
3800}
3801
3802GL_APICALL void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
3803{
3804 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p)",
3805 target, numAttachments, attachments);
3806
3807 glInvalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, std::numeric_limits<GLsizei>::max(), std::numeric_limits<GLsizei>::max());
3808}
3809
3810GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
3811{
3812 TRACE("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = %p, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
3813 target, numAttachments, attachments, x, y, width, height);
3814
3815 es2::Context *context = es2::getContext();
3816
3817 if(context)
3818 {
3819 if(numAttachments < 0 || width < 0 || height < 0)
3820 {
3821 return error(GL_INVALID_VALUE);
3822 }
3823
3824 es2::Framebuffer *framebuffer = nullptr;
3825 switch(target)
3826 {
3827 case GL_DRAW_FRAMEBUFFER:
3828 case GL_FRAMEBUFFER:
3829 framebuffer = context->getDrawFramebuffer();
3830 case GL_READ_FRAMEBUFFER:
3831 framebuffer = context->getReadFramebuffer();
3832 break;
3833 default:
3834 return error(GL_INVALID_ENUM);
3835 }
3836
3837 if(framebuffer)
3838 {
3839 for(int i = 0; i < numAttachments; i++)
3840 {
3841 switch(attachments[i])
3842 {
3843 case GL_COLOR:
3844 case GL_DEPTH:
3845 case GL_STENCIL:
3846 if(!framebuffer->isDefaultFramebuffer())
3847 {
3848 return error(GL_INVALID_ENUM);
3849 }
3850 break;
3851 case GL_DEPTH_ATTACHMENT:
3852 case GL_STENCIL_ATTACHMENT:
3853 case GL_DEPTH_STENCIL_ATTACHMENT:
3854 break;
3855 default:
3856 if(attachments[i] >= GL_COLOR_ATTACHMENT0 &&
3857 attachments[i] <= GL_COLOR_ATTACHMENT31)
3858 {
3859 if(attachments[i] - GL_COLOR_ATTACHMENT0 >= MAX_DRAW_BUFFERS)
3860 {
3861 return error(GL_INVALID_OPERATION);
3862 }
3863 }
3864 else
3865 {
3866 return error(GL_INVALID_ENUM);
3867 }
3868 break;
3869 }
3870 }
3871 }
3872
3873 // UNIMPLEMENTED(); // It is valid for this function to be treated as a no-op
3874 }
3875}
3876
3877GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
3878{
3879 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
3880 target, levels, internalformat, width, height);
3881
3882 if(width < 1 || height < 1 || levels < 1)
3883 {
3884 return error(GL_INVALID_VALUE);
3885 }
3886
3887 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
3888 {
3889 return error(GL_INVALID_OPERATION);
3890 }
3891
3892 GLenum type;
3893 if(!GetStorageType(internalformat, type))
3894 {
3895 return error(GL_INVALID_ENUM);
3896 }
3897
3898 es2::Context *context = es2::getContext();
3899
3900 if(context)
3901 {
3902 switch(target)
3903 {
3904 case GL_TEXTURE_2D:
3905 {
3906 es2::Texture2D *texture = context->getTexture2D();
3907 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3908 {
3909 return error(GL_INVALID_OPERATION);
3910 }
3911
3912 for(int level = 0; level < levels; ++level)
3913 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003914 texture->setImage(context, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003915 width = std::max(1, (width / 2));
3916 height = std::max(1, (height / 2));
3917 }
3918 texture->makeImmutable(levels);
3919 }
3920 break;
3921 case GL_TEXTURE_CUBE_MAP:
3922 {
3923 es2::TextureCubeMap *texture = context->getTextureCubeMap();
3924 if(!texture || texture->name == 0 || texture->getImmutableFormat())
3925 {
3926 return error(GL_INVALID_OPERATION);
3927 }
3928
3929 for(int level = 0; level < levels; ++level)
3930 {
3931 for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
3932 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003933 texture->setImage(context, face, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003934 }
3935 width = std::max(1, (width / 2));
3936 height = std::max(1, (height / 2));
3937 }
3938 texture->makeImmutable(levels);
3939 }
3940 break;
3941 default:
3942 return error(GL_INVALID_ENUM);
3943 }
3944 }
3945}
3946
3947GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
3948{
3949 TRACE("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d)",
3950 target, levels, internalformat, width, height, depth);
3951
3952 if(width < 1 || height < 1 || depth < 1 || levels < 1)
3953 {
3954 return error(GL_INVALID_VALUE);
3955 }
3956
3957 GLenum type;
3958 if(!GetStorageType(internalformat, type))
3959 {
3960 return error(GL_INVALID_ENUM);
3961 }
3962
3963 es2::Context *context = es2::getContext();
3964
3965 if(context)
3966 {
3967 switch(target)
3968 {
3969 case GL_TEXTURE_3D:
3970 {
3971 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(std::max(width, height), depth)) + 1))
3972 {
3973 return error(GL_INVALID_OPERATION);
3974 }
3975
3976 es2::Texture3D *texture = context->getTexture3D();
3977 if(!texture || texture->name == 0 || texture->getImmutableFormat() == GL_TRUE)
3978 {
3979 return error(GL_INVALID_OPERATION);
3980 }
3981
3982 for(int level = 0; level < levels; ++level)
3983 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04003984 texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04003985 width = std::max(1, (width / 2));
3986 height = std::max(1, (height / 2));
3987 depth = std::max(1, (depth / 2));
3988 }
3989 texture->makeImmutable(levels);
3990 }
3991 break;
3992 case GL_TEXTURE_2D_ARRAY:
3993 {
3994 if(levels > es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS || levels > (log2(std::max(width, height)) + 1))
3995 {
3996 return error(GL_INVALID_OPERATION);
3997 }
3998
3999 es2::Texture3D *texture = context->getTexture2DArray();
4000 if(!texture || texture->name == 0 || texture->getImmutableFormat())
4001 {
4002 return error(GL_INVALID_OPERATION);
4003 }
4004
4005 for(int level = 0; level < levels; ++level)
4006 {
4007 for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
4008 {
Nicolas Capens81aa97b2017-06-27 17:08:08 -04004009 texture->setImage(context, level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), nullptr);
Nicolas Capens0bac2852016-05-07 06:09:58 -04004010 }
4011 width = std::max(1, (width / 2));
4012 height = std::max(1, (height / 2));
4013 }
4014 texture->makeImmutable(levels);
4015 }
4016 break;
4017 default:
4018 return error(GL_INVALID_ENUM);
4019 }
4020 }
4021}
4022
4023GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)
4024{
4025 TRACE("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, GLint *params = %p)",
4026 target, internalformat, pname, bufSize, params);
4027
4028 if(bufSize < 0)
4029 {
4030 return error(GL_INVALID_VALUE);
4031 }
4032
4033 if(bufSize == 0)
4034 {
4035 return;
4036 }
4037
Nicolas Capens400667e2017-03-29 14:40:14 -04004038 if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) &&
4039 !IsDepthRenderable(internalformat, egl::getClientVersion()) &&
4040 !IsStencilRenderable(internalformat, egl::getClientVersion()))
Nicolas Capens0bac2852016-05-07 06:09:58 -04004041 {
4042 return error(GL_INVALID_ENUM);
4043 }
4044
4045 switch(target)
4046 {
4047 case GL_RENDERBUFFER:
4048 break;
4049 default:
4050 return error(GL_INVALID_ENUM);
4051 }
4052
4053 // Integer types have no multisampling
4054 GLint numMultisampleCounts = NUM_MULTISAMPLE_COUNTS;
4055 switch(internalformat)
4056 {
4057 case GL_R8UI:
4058 case GL_R8I:
4059 case GL_R16UI:
4060 case GL_R16I:
4061 case GL_R32UI:
4062 case GL_R32I:
4063 case GL_RG8UI:
4064 case GL_RG8I:
4065 case GL_RG16UI:
4066 case GL_RG16I:
4067 case GL_RG32UI:
4068 case GL_RG32I:
4069 case GL_RGB8UI:
4070 case GL_RGB8I:
4071 case GL_RGB16UI:
4072 case GL_RGB16I:
4073 case GL_RGB32UI:
4074 case GL_RGB32I:
4075 case GL_RGBA8UI:
4076 case GL_RGBA8I:
4077 case GL_RGB10_A2UI:
4078 case GL_RGBA16UI:
4079 case GL_RGBA16I:
4080 case GL_RGBA32UI:
4081 case GL_RGBA32I:
4082 numMultisampleCounts = 0;
4083 break;
4084 default:
4085 break;
4086 }
4087
4088 switch(pname)
4089 {
4090 case GL_NUM_SAMPLE_COUNTS:
4091 *params = numMultisampleCounts;
4092 break;
4093 case GL_SAMPLES:
4094 for(int i = 0; i < numMultisampleCounts && i < bufSize; i++)
4095 {
4096 params[i] = multisampleCount[i];
4097 }
4098 break;
4099 default:
4100 return error(GL_INVALID_ENUM);
4101 }
4102}
4103
4104}