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