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