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