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