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