blob: e9b143d0c9488a4c841ae90daeda9632ba13b4a3 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700165 case GL_FRAMEBUFFER_SRGB_EXT:
166 return context->getExtensions().sRGBWriteControl;
167
Geoff Lang3b573612016-10-31 14:08:10 -0400168 case GL_SAMPLE_MASK:
169 UNIMPLEMENTED();
170 return context->getClientVersion() >= Version(3, 1);
171
Geoff Langf41a7152016-09-19 15:11:17 -0400172 default:
173 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500174 }
175}
176
Geoff Lang62fce5b2016-09-30 10:46:35 -0400177bool ValidateReadPixelsBase(ValidationContext *context,
178 GLint x,
179 GLint y,
180 GLsizei width,
181 GLsizei height,
182 GLenum format,
183 GLenum type,
184 GLsizei bufSize,
185 GLsizei *length,
186 GLvoid *pixels)
187{
188 if (length != nullptr)
189 {
190 *length = 0;
191 }
192
193 if (width < 0 || height < 0)
194 {
195 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
196 return false;
197 }
198
199 auto readFramebuffer = context->getGLState().getReadFramebuffer();
200
201 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
202 {
203 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
204 return false;
205 }
206
207 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
208 {
209 context->handleError(Error(GL_INVALID_OPERATION));
210 return false;
211 }
212
213 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
214 ASSERT(framebuffer);
215
216 if (framebuffer->getReadBufferState() == GL_NONE)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
219 return false;
220 }
221
222 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
223 if (!readBuffer)
224 {
225 context->handleError(Error(GL_INVALID_OPERATION));
226 return false;
227 }
228
229 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
230 GLenum currentType = framebuffer->getImplementationColorReadType();
231 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
232
233 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
234 bool validFormatTypeCombination =
235 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
236
237 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION));
240 return false;
241 }
242
243 // Check for pixel pack buffer related API errors
244 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
245 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
246 {
247 // ...the buffer object's data store is currently mapped.
248 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
249 return false;
250 }
251
252 // .. the data would be packed to the buffer object such that the memory writes required
253 // would exceed the data store size.
254 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
255 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
256 const gl::Extents size(width, height, 1);
257 const auto &pack = context->getGLState().getPackState();
258
259 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
260 if (endByteOrErr.isError())
261 {
262 context->handleError(endByteOrErr.getError());
263 return false;
264 }
265
266 size_t endByte = endByteOrErr.getResult();
267 if (bufSize >= 0)
268 {
269
270 if (static_cast<size_t>(bufSize) < endByte)
271 {
272 context->handleError(
273 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
274 return false;
275 }
276 }
277
278 if (pixelPackBuffer != nullptr)
279 {
280 CheckedNumeric<size_t> checkedEndByte(endByte);
281 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
282 checkedEndByte += checkedOffset;
283
284 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
285 {
286 // Overflow past the end of the buffer
287 context->handleError(
288 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
289 return false;
290 }
291 }
292
293 if (length != nullptr)
294 {
295 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
296 {
297 context->handleError(
298 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
299 return false;
300 }
301
302 *length = static_cast<GLsizei>(endByte);
303 }
304
305 return true;
306}
307
Geoff Lang740d9022016-10-07 11:20:52 -0400308bool ValidateGetRenderbufferParameterivBase(Context *context,
309 GLenum target,
310 GLenum pname,
311 GLsizei *length)
312{
313 if (length)
314 {
315 *length = 0;
316 }
317
318 if (target != GL_RENDERBUFFER)
319 {
320 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
321 return false;
322 }
323
324 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
325 if (renderbuffer == nullptr)
326 {
327 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
328 return false;
329 }
330
331 switch (pname)
332 {
333 case GL_RENDERBUFFER_WIDTH:
334 case GL_RENDERBUFFER_HEIGHT:
335 case GL_RENDERBUFFER_INTERNAL_FORMAT:
336 case GL_RENDERBUFFER_RED_SIZE:
337 case GL_RENDERBUFFER_GREEN_SIZE:
338 case GL_RENDERBUFFER_BLUE_SIZE:
339 case GL_RENDERBUFFER_ALPHA_SIZE:
340 case GL_RENDERBUFFER_DEPTH_SIZE:
341 case GL_RENDERBUFFER_STENCIL_SIZE:
342 break;
343
344 case GL_RENDERBUFFER_SAMPLES_ANGLE:
345 if (!context->getExtensions().framebufferMultisample)
346 {
347 context->handleError(
348 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
349 return false;
350 }
351 break;
352
353 default:
354 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
355 return false;
356 }
357
358 if (length)
359 {
360 *length = 1;
361 }
362 return true;
363}
364
Geoff Langd7d0ed32016-10-07 11:33:51 -0400365bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
366{
367 if (length)
368 {
369 *length = 0;
370 }
371
372 if (GetValidShader(context, shader) == nullptr)
373 {
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_SHADER_TYPE:
380 case GL_DELETE_STATUS:
381 case GL_COMPILE_STATUS:
382 case GL_INFO_LOG_LENGTH:
383 case GL_SHADER_SOURCE_LENGTH:
384 break;
385
386 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
387 if (!context->getExtensions().translatedShaderSource)
388 {
389 context->handleError(
390 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
391 return false;
392 }
393 break;
394
395 default:
396 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
397 return false;
398 }
399
400 if (length)
401 {
402 *length = 1;
403 }
404 return true;
405}
406
Geoff Langc1984ed2016-10-07 12:41:00 -0400407bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
408{
409 if (length)
410 {
411 *length = 0;
412 }
413
414 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
415 {
416 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
417 return false;
418 }
419
420 if (context->getTargetTexture(target) == nullptr)
421 {
422 // Should only be possible for external textures
423 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
424 return false;
425 }
426
427 switch (pname)
428 {
429 case GL_TEXTURE_MAG_FILTER:
430 case GL_TEXTURE_MIN_FILTER:
431 case GL_TEXTURE_WRAP_S:
432 case GL_TEXTURE_WRAP_T:
433 break;
434
435 case GL_TEXTURE_USAGE_ANGLE:
436 if (!context->getExtensions().textureUsage)
437 {
438 context->handleError(
439 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
445 if (!context->getExtensions().textureFilterAnisotropic)
446 {
447 context->handleError(
448 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
449 return false;
450 }
451 break;
452
453 case GL_TEXTURE_IMMUTABLE_FORMAT:
454 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
455 {
456 context->handleError(
457 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
458 return false;
459 }
460 break;
461
462 case GL_TEXTURE_WRAP_R:
463 case GL_TEXTURE_IMMUTABLE_LEVELS:
464 case GL_TEXTURE_SWIZZLE_R:
465 case GL_TEXTURE_SWIZZLE_G:
466 case GL_TEXTURE_SWIZZLE_B:
467 case GL_TEXTURE_SWIZZLE_A:
468 case GL_TEXTURE_BASE_LEVEL:
469 case GL_TEXTURE_MAX_LEVEL:
470 case GL_TEXTURE_MIN_LOD:
471 case GL_TEXTURE_MAX_LOD:
472 case GL_TEXTURE_COMPARE_MODE:
473 case GL_TEXTURE_COMPARE_FUNC:
474 if (context->getClientMajorVersion() < 3)
475 {
476 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
477 return false;
478 }
479 break;
480
Geoff Lang81c6b572016-10-19 14:07:52 -0700481 case GL_TEXTURE_SRGB_DECODE_EXT:
482 if (!context->getExtensions().textureSRGBDecode)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
486 return false;
487 }
488 break;
489
Geoff Langc1984ed2016-10-07 12:41:00 -0400490 default:
491 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
492 return false;
493 }
494
495 if (length)
496 {
497 *length = 1;
498 }
499 return true;
500}
501
502template <typename ParamType>
503bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
504{
505 switch (ConvertToGLenum(params[0]))
506 {
507 case GL_CLAMP_TO_EDGE:
508 break;
509
510 case GL_REPEAT:
511 case GL_MIRRORED_REPEAT:
512 if (isExternalTextureTarget)
513 {
514 // OES_EGL_image_external specifies this error.
515 context->handleError(Error(
516 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
517 return false;
518 }
519 break;
520
521 default:
522 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
523 return false;
524 }
525
526 return true;
527}
528
529template <typename ParamType>
530bool ValidateTextureMinFilterValue(Context *context,
531 ParamType *params,
532 bool isExternalTextureTarget)
533{
534 switch (ConvertToGLenum(params[0]))
535 {
536 case GL_NEAREST:
537 case GL_LINEAR:
538 break;
539
540 case GL_NEAREST_MIPMAP_NEAREST:
541 case GL_LINEAR_MIPMAP_NEAREST:
542 case GL_NEAREST_MIPMAP_LINEAR:
543 case GL_LINEAR_MIPMAP_LINEAR:
544 if (isExternalTextureTarget)
545 {
546 // OES_EGL_image_external specifies this error.
547 context->handleError(
548 Error(GL_INVALID_ENUM,
549 "external textures only support NEAREST and LINEAR filtering"));
550 return false;
551 }
552 break;
553
554 default:
555 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
556 return false;
557 }
558
559 return true;
560}
561
562template <typename ParamType>
563bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
564{
565 switch (ConvertToGLenum(params[0]))
566 {
567 case GL_NEAREST:
568 case GL_LINEAR:
569 break;
570
571 default:
572 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
573 return false;
574 }
575
576 return true;
577}
578
579template <typename ParamType>
580bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
581{
582 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
583 switch (ConvertToGLenum(params[0]))
584 {
585 case GL_NONE:
586 case GL_COMPARE_REF_TO_TEXTURE:
587 break;
588
589 default:
590 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
591 return false;
592 }
593
594 return true;
595}
596
597template <typename ParamType>
598bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
599{
600 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
601 switch (ConvertToGLenum(params[0]))
602 {
603 case GL_LEQUAL:
604 case GL_GEQUAL:
605 case GL_LESS:
606 case GL_GREATER:
607 case GL_EQUAL:
608 case GL_NOTEQUAL:
609 case GL_ALWAYS:
610 case GL_NEVER:
611 break;
612
613 default:
614 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
615 return false;
616 }
617
618 return true;
619}
620
621template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700622bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
623{
624 if (!context->getExtensions().textureSRGBDecode)
625 {
626 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
627 return false;
628 }
629
630 switch (ConvertToGLenum(params[0]))
631 {
632 case GL_DECODE_EXT:
633 case GL_SKIP_DECODE_EXT:
634 break;
635
636 default:
637 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
638 return false;
639 }
640
641 return true;
642}
643
644template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400645bool ValidateTexParameterBase(Context *context,
646 GLenum target,
647 GLenum pname,
648 GLsizei bufSize,
649 ParamType *params)
650{
651 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
652 {
653 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
654 return false;
655 }
656
657 if (context->getTargetTexture(target) == nullptr)
658 {
659 // Should only be possible for external textures
660 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
661 return false;
662 }
663
664 const GLsizei minBufSize = 1;
665 if (bufSize >= 0 && bufSize < minBufSize)
666 {
667 context->handleError(
668 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
669 return false;
670 }
671
672 switch (pname)
673 {
674 case GL_TEXTURE_WRAP_R:
675 case GL_TEXTURE_SWIZZLE_R:
676 case GL_TEXTURE_SWIZZLE_G:
677 case GL_TEXTURE_SWIZZLE_B:
678 case GL_TEXTURE_SWIZZLE_A:
679 case GL_TEXTURE_BASE_LEVEL:
680 case GL_TEXTURE_MAX_LEVEL:
681 case GL_TEXTURE_COMPARE_MODE:
682 case GL_TEXTURE_COMPARE_FUNC:
683 case GL_TEXTURE_MIN_LOD:
684 case GL_TEXTURE_MAX_LOD:
685 if (context->getClientMajorVersion() < 3)
686 {
687 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
688 return false;
689 }
690 if (target == GL_TEXTURE_EXTERNAL_OES &&
691 !context->getExtensions().eglImageExternalEssl3)
692 {
693 context->handleError(Error(GL_INVALID_ENUM,
694 "ES3 texture parameters are not available without "
695 "GL_OES_EGL_image_external_essl3."));
696 return false;
697 }
698 break;
699
700 default:
701 break;
702 }
703
704 switch (pname)
705 {
706 case GL_TEXTURE_WRAP_S:
707 case GL_TEXTURE_WRAP_T:
708 case GL_TEXTURE_WRAP_R:
709 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
710 {
711 return false;
712 }
713 break;
714
715 case GL_TEXTURE_MIN_FILTER:
716 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
717 {
718 return false;
719 }
720 break;
721
722 case GL_TEXTURE_MAG_FILTER:
723 if (!ValidateTextureMagFilterValue(context, params))
724 {
725 return false;
726 }
727 break;
728
729 case GL_TEXTURE_USAGE_ANGLE:
730 switch (ConvertToGLenum(params[0]))
731 {
732 case GL_NONE:
733 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
734 break;
735
736 default:
737 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
738 return false;
739 }
740 break;
741
742 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
743 if (!context->getExtensions().textureFilterAnisotropic)
744 {
745 context->handleError(
746 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
747 return false;
748 }
749
750 // we assume the parameter passed to this validation method is truncated, not rounded
751 if (params[0] < 1)
752 {
753 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_MIN_LOD:
759 case GL_TEXTURE_MAX_LOD:
760 // any value is permissible
761 break;
762
763 case GL_TEXTURE_COMPARE_MODE:
764 if (!ValidateTextureCompareModeValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_COMPARE_FUNC:
771 if (!ValidateTextureCompareFuncValue(context, params))
772 {
773 return false;
774 }
775 break;
776
777 case GL_TEXTURE_SWIZZLE_R:
778 case GL_TEXTURE_SWIZZLE_G:
779 case GL_TEXTURE_SWIZZLE_B:
780 case GL_TEXTURE_SWIZZLE_A:
781 switch (ConvertToGLenum(params[0]))
782 {
783 case GL_RED:
784 case GL_GREEN:
785 case GL_BLUE:
786 case GL_ALPHA:
787 case GL_ZERO:
788 case GL_ONE:
789 break;
790
791 default:
792 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
793 return false;
794 }
795 break;
796
797 case GL_TEXTURE_BASE_LEVEL:
798 if (params[0] < 0)
799 {
800 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
801 return false;
802 }
803 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
804 {
805 context->handleError(
806 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
807 return false;
808 }
809 break;
810
811 case GL_TEXTURE_MAX_LEVEL:
812 if (params[0] < 0)
813 {
814 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
815 return false;
816 }
817 break;
818
Geoff Lang3b573612016-10-31 14:08:10 -0400819 case GL_DEPTH_STENCIL_TEXTURE_MODE:
820 if (context->getClientVersion() < Version(3, 1))
821 {
822 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
823 return false;
824 }
825 UNIMPLEMENTED();
826 break;
827
Geoff Lang81c6b572016-10-19 14:07:52 -0700828 case GL_TEXTURE_SRGB_DECODE_EXT:
829 if (!ValidateTextureSRGBDecodeValue(context, params))
830 {
831 return false;
832 }
833 break;
834
Geoff Langc1984ed2016-10-07 12:41:00 -0400835 default:
836 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
837 return false;
838 }
839
840 return true;
841}
842
843template <typename ParamType>
844bool ValidateSamplerParameterBase(Context *context,
845 GLuint sampler,
846 GLenum pname,
847 GLsizei bufSize,
848 ParamType *params)
849{
850 if (context->getClientMajorVersion() < 3)
851 {
852 context->handleError(
853 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
854 return false;
855 }
856
857 if (!context->isSampler(sampler))
858 {
859 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
860 return false;
861 }
862
863 const GLsizei minBufSize = 1;
864 if (bufSize >= 0 && bufSize < minBufSize)
865 {
866 context->handleError(
867 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
868 return false;
869 }
870
871 switch (pname)
872 {
873 case GL_TEXTURE_WRAP_S:
874 case GL_TEXTURE_WRAP_T:
875 case GL_TEXTURE_WRAP_R:
876 if (!ValidateTextureWrapModeValue(context, params, false))
877 {
878 return false;
879 }
880 break;
881
882 case GL_TEXTURE_MIN_FILTER:
883 if (!ValidateTextureMinFilterValue(context, params, false))
884 {
885 return false;
886 }
887 break;
888
889 case GL_TEXTURE_MAG_FILTER:
890 if (!ValidateTextureMagFilterValue(context, params))
891 {
892 return false;
893 }
894 break;
895
896 case GL_TEXTURE_MIN_LOD:
897 case GL_TEXTURE_MAX_LOD:
898 // any value is permissible
899 break;
900
901 case GL_TEXTURE_COMPARE_MODE:
902 if (!ValidateTextureCompareModeValue(context, params))
903 {
904 return false;
905 }
906 break;
907
908 case GL_TEXTURE_COMPARE_FUNC:
909 if (!ValidateTextureCompareFuncValue(context, params))
910 {
911 return false;
912 }
913 break;
914
Geoff Lang81c6b572016-10-19 14:07:52 -0700915 case GL_TEXTURE_SRGB_DECODE_EXT:
916 if (!ValidateTextureSRGBDecodeValue(context, params))
917 {
918 return false;
919 }
920 break;
921
Geoff Langc1984ed2016-10-07 12:41:00 -0400922 default:
923 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
924 return false;
925 }
926
927 return true;
928}
929
930bool ValidateGetSamplerParameterBase(Context *context,
931 GLuint sampler,
932 GLenum pname,
933 GLsizei *length)
934{
935 if (length)
936 {
937 *length = 0;
938 }
939
940 if (context->getClientMajorVersion() < 3)
941 {
942 context->handleError(
943 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
944 return false;
945 }
946
947 if (!context->isSampler(sampler))
948 {
949 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
950 return false;
951 }
952
953 switch (pname)
954 {
955 case GL_TEXTURE_WRAP_S:
956 case GL_TEXTURE_WRAP_T:
957 case GL_TEXTURE_WRAP_R:
958 case GL_TEXTURE_MIN_FILTER:
959 case GL_TEXTURE_MAG_FILTER:
960 case GL_TEXTURE_MIN_LOD:
961 case GL_TEXTURE_MAX_LOD:
962 case GL_TEXTURE_COMPARE_MODE:
963 case GL_TEXTURE_COMPARE_FUNC:
964 break;
965
Geoff Lang81c6b572016-10-19 14:07:52 -0700966 case GL_TEXTURE_SRGB_DECODE_EXT:
967 if (!context->getExtensions().textureSRGBDecode)
968 {
969 context->handleError(
970 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
971 return false;
972 }
973 break;
974
Geoff Langc1984ed2016-10-07 12:41:00 -0400975 default:
976 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
977 return false;
978 }
979
980 if (length)
981 {
982 *length = 1;
983 }
984 return true;
985}
986
Geoff Lang0b031062016-10-13 14:30:04 -0400987bool ValidateGetVertexAttribBase(Context *context,
988 GLuint index,
989 GLenum pname,
990 GLsizei *length,
991 bool pointer,
992 bool pureIntegerEntryPoint)
993{
994 if (length)
995 {
996 *length = 0;
997 }
998
999 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1000 {
1001 context->handleError(
1002 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1003 return false;
1004 }
1005
1006 if (index >= context->getCaps().maxVertexAttributes)
1007 {
1008 context->handleError(Error(
1009 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1010 return false;
1011 }
1012
1013 if (pointer)
1014 {
1015 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1016 {
1017 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1018 return false;
1019 }
1020 }
1021 else
1022 {
1023 switch (pname)
1024 {
1025 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1026 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1027 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1028 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1029 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1030 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1031 case GL_CURRENT_VERTEX_ATTRIB:
1032 break;
1033
1034 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1035 static_assert(
1036 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1037 "ANGLE extension enums not equal to GL enums.");
1038 if (context->getClientMajorVersion() < 3 &&
1039 !context->getExtensions().instancedArrays)
1040 {
1041 context->handleError(Error(GL_INVALID_ENUM,
1042 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1043 "3.0 or GL_ANGLE_instanced_arrays."));
1044 return false;
1045 }
1046 break;
1047
1048 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1049 if (context->getClientMajorVersion() < 3)
1050 {
1051 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1052 return false;
1053 }
1054 break;
1055
1056 default:
1057 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1058 return false;
1059 }
1060 }
1061
1062 if (length)
1063 {
1064 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1065 {
1066 *length = 4;
1067 }
1068 else
1069 {
1070 *length = 1;
1071 }
1072 }
1073
1074 return true;
1075}
1076
Geoff Lang6899b872016-10-14 11:30:13 -04001077bool ValidateGetActiveUniformBlockivBase(Context *context,
1078 GLuint program,
1079 GLuint uniformBlockIndex,
1080 GLenum pname,
1081 GLsizei *length)
1082{
1083 if (length)
1084 {
1085 *length = 0;
1086 }
1087
1088 if (context->getClientMajorVersion() < 3)
1089 {
1090 context->handleError(
1091 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1092 return false;
1093 }
1094
1095 Program *programObject = GetValidProgram(context, program);
1096 if (!programObject)
1097 {
1098 return false;
1099 }
1100
1101 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1102 {
1103 context->handleError(
1104 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1105 return false;
1106 }
1107
1108 switch (pname)
1109 {
1110 case GL_UNIFORM_BLOCK_BINDING:
1111 case GL_UNIFORM_BLOCK_DATA_SIZE:
1112 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1113 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1114 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1115 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1116 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1117 break;
1118
1119 default:
1120 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1121 return false;
1122 }
1123
1124 if (length)
1125 {
1126 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1127 {
1128 const UniformBlock &uniformBlock =
1129 programObject->getUniformBlockByIndex(uniformBlockIndex);
1130 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1131 }
1132 else
1133 {
1134 *length = 1;
1135 }
1136 }
1137
1138 return true;
1139}
1140
Geoff Langebebe1c2016-10-14 12:01:31 -04001141bool ValidateGetBufferParameterBase(ValidationContext *context,
1142 GLenum target,
1143 GLenum pname,
1144 bool pointerVersion,
1145 GLsizei *numParams)
1146{
1147 if (numParams)
1148 {
1149 *numParams = 0;
1150 }
1151
1152 if (!ValidBufferTarget(context, target))
1153 {
1154 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1155 return false;
1156 }
1157
1158 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1159 if (!buffer)
1160 {
1161 // A null buffer means that "0" is bound to the requested buffer target
1162 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1163 return false;
1164 }
1165
1166 const Extensions &extensions = context->getExtensions();
1167
1168 switch (pname)
1169 {
1170 case GL_BUFFER_USAGE:
1171 case GL_BUFFER_SIZE:
1172 break;
1173
1174 case GL_BUFFER_ACCESS_OES:
1175 if (!extensions.mapBuffer)
1176 {
1177 context->handleError(
1178 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1179 return false;
1180 }
1181 break;
1182
1183 case GL_BUFFER_MAPPED:
1184 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1185 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1186 !extensions.mapBufferRange)
1187 {
1188 context->handleError(Error(
1189 GL_INVALID_ENUM,
1190 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1191 return false;
1192 }
1193 break;
1194
1195 case GL_BUFFER_MAP_POINTER:
1196 if (!pointerVersion)
1197 {
1198 context->handleError(
1199 Error(GL_INVALID_ENUM,
1200 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1201 return false;
1202 }
1203 break;
1204
1205 case GL_BUFFER_ACCESS_FLAGS:
1206 case GL_BUFFER_MAP_OFFSET:
1207 case GL_BUFFER_MAP_LENGTH:
1208 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1209 {
1210 context->handleError(Error(
1211 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1212 return false;
1213 }
1214 break;
1215
1216 default:
1217 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1218 return false;
1219 }
1220
1221 // All buffer parameter queries return one value.
1222 if (numParams)
1223 {
1224 *numParams = 1;
1225 }
1226
1227 return true;
1228}
1229
Geoff Lang0a9661f2016-10-20 10:59:20 -07001230bool ValidateGetInternalFormativBase(Context *context,
1231 GLenum target,
1232 GLenum internalformat,
1233 GLenum pname,
1234 GLsizei bufSize,
1235 GLsizei *numParams)
1236{
1237 if (numParams)
1238 {
1239 *numParams = 0;
1240 }
1241
1242 if (context->getClientMajorVersion() < 3)
1243 {
1244 context->handleError(
1245 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1246 return false;
1247 }
1248
1249 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1250 if (!formatCaps.renderable)
1251 {
1252 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1253 return false;
1254 }
1255
1256 switch (target)
1257 {
1258 case GL_RENDERBUFFER:
1259 break;
1260
1261 default:
1262 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1263 return false;
1264 }
1265
1266 if (bufSize < 0)
1267 {
1268 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1269 return false;
1270 }
1271
1272 GLsizei maxWriteParams = 0;
1273 switch (pname)
1274 {
1275 case GL_NUM_SAMPLE_COUNTS:
1276 maxWriteParams = 1;
1277 break;
1278
1279 case GL_SAMPLES:
1280 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1281 break;
1282
1283 default:
1284 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1285 return false;
1286 }
1287
1288 if (numParams)
1289 {
1290 // glGetInternalFormativ will not overflow bufSize
1291 *numParams = std::min(bufSize, maxWriteParams);
1292 }
1293
1294 return true;
1295}
1296
Geoff Langf41a7152016-09-19 15:11:17 -04001297} // anonymous namespace
1298
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001299bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001300{
Jamie Madilld7460c72014-01-21 16:38:14 -05001301 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001302 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001303 case GL_TEXTURE_2D:
1304 case GL_TEXTURE_CUBE_MAP:
1305 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001306
Jamie Madilld7460c72014-01-21 16:38:14 -05001307 case GL_TEXTURE_3D:
1308 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001309 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001310
Geoff Lang3b573612016-10-31 14:08:10 -04001311 case GL_TEXTURE_2D_MULTISAMPLE:
1312 UNIMPLEMENTED();
1313 return (context->getClientVersion() >= Version(3, 1));
1314
Jamie Madilld7460c72014-01-21 16:38:14 -05001315 default:
1316 return false;
1317 }
Jamie Madill35d15012013-10-07 10:46:37 -04001318}
1319
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001320bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1321{
1322 switch (target)
1323 {
1324 case GL_TEXTURE_2D:
1325 case GL_TEXTURE_CUBE_MAP:
1326 return true;
1327
1328 default:
1329 return false;
1330 }
1331}
1332
1333bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1334{
1335 switch (target)
1336 {
1337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001339 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001340
1341 default:
1342 return false;
1343 }
1344}
1345
Ian Ewellbda75592016-04-18 17:25:54 -04001346// Most texture GL calls are not compatible with external textures, so we have a separate validation
1347// function for use in the GL calls that do
1348bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1349{
1350 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1351 (context->getExtensions().eglImageExternal ||
1352 context->getExtensions().eglStreamConsumerExternal);
1353}
1354
Shannon Woods4dfed832014-03-17 20:03:39 -04001355// This function differs from ValidTextureTarget in that the target must be
1356// usable as the destination of a 2D operation-- so a cube face is valid, but
1357// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001358// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001359bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001360{
1361 switch (target)
1362 {
1363 case GL_TEXTURE_2D:
1364 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1365 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1366 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1367 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1368 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1369 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1370 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001371 default:
1372 return false;
1373 }
1374}
1375
1376bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1377{
1378 switch (target)
1379 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001380 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001381 case GL_TEXTURE_2D_ARRAY:
1382 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001383 default:
1384 return false;
1385 }
1386}
1387
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001388bool ValidFramebufferTarget(GLenum target)
1389{
Geoff Langd4475812015-03-18 10:53:05 -04001390 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1391 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001392
1393 switch (target)
1394 {
1395 case GL_FRAMEBUFFER: return true;
1396 case GL_READ_FRAMEBUFFER: return true;
1397 case GL_DRAW_FRAMEBUFFER: return true;
1398 default: return false;
1399 }
1400}
1401
Jamie Madill29639852016-09-02 15:00:09 -04001402bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001403{
1404 switch (target)
1405 {
1406 case GL_ARRAY_BUFFER:
1407 case GL_ELEMENT_ARRAY_BUFFER:
1408 return true;
1409
Jamie Madill8c96d582014-03-05 15:01:23 -05001410 case GL_PIXEL_PACK_BUFFER:
1411 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001412 return (context->getExtensions().pixelBufferObject ||
1413 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001414
Shannon Woodsb3801742014-03-27 14:59:19 -04001415 case GL_COPY_READ_BUFFER:
1416 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001417 case GL_TRANSFORM_FEEDBACK_BUFFER:
1418 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001419 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001420
Geoff Lang3b573612016-10-31 14:08:10 -04001421 case GL_ATOMIC_COUNTER_BUFFER:
1422 case GL_SHADER_STORAGE_BUFFER:
1423 case GL_DRAW_INDIRECT_BUFFER:
1424 case GL_DISPATCH_INDIRECT_BUFFER:
1425 UNIMPLEMENTED();
1426 return context->getClientVersion() >= Version(3, 1);
1427
Jamie Madill8c96d582014-03-05 15:01:23 -05001428 default:
1429 return false;
1430 }
1431}
1432
Jamie Madillc29968b2016-01-20 11:17:23 -05001433bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001434{
Jamie Madillc29968b2016-01-20 11:17:23 -05001435 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001436 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001437 switch (target)
1438 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001439 case GL_TEXTURE_2D:
1440 maxDimension = caps.max2DTextureSize;
1441 break;
Geoff Langce635692013-09-24 13:56:32 -04001442 case GL_TEXTURE_CUBE_MAP:
1443 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1444 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1445 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1446 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1447 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001448 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1449 maxDimension = caps.maxCubeMapTextureSize;
1450 break;
1451 case GL_TEXTURE_3D:
1452 maxDimension = caps.max3DTextureSize;
1453 break;
1454 case GL_TEXTURE_2D_ARRAY:
1455 maxDimension = caps.max2DTextureSize;
1456 break;
Geoff Langce635692013-09-24 13:56:32 -04001457 default: UNREACHABLE();
1458 }
1459
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001460 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001461}
1462
Austin Kinross08528e12015-10-07 16:24:40 -07001463bool ValidImageSizeParameters(const Context *context,
1464 GLenum target,
1465 GLint level,
1466 GLsizei width,
1467 GLsizei height,
1468 GLsizei depth,
1469 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001470{
1471 if (level < 0 || width < 0 || height < 0 || depth < 0)
1472 {
1473 return false;
1474 }
1475
Austin Kinross08528e12015-10-07 16:24:40 -07001476 // TexSubImage parameters can be NPOT without textureNPOT extension,
1477 // as long as the destination texture is POT.
1478 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001479 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001480 {
1481 return false;
1482 }
1483
1484 if (!ValidMipLevel(context, target, level))
1485 {
1486 return false;
1487 }
1488
1489 return true;
1490}
1491
Geoff Lang0d8b7242015-09-09 14:56:53 -04001492bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1493{
1494 // List of compressed format that require that the texture size is smaller than or a multiple of
1495 // the compressed block size.
1496 switch (internalFormat)
1497 {
1498 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1499 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1500 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1501 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001502 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001503 return true;
1504
1505 default:
1506 return false;
1507 }
1508}
1509
Jamie Madillc29968b2016-01-20 11:17:23 -05001510bool ValidCompressedImageSize(const ValidationContext *context,
1511 GLenum internalFormat,
1512 GLsizei width,
1513 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001514{
Geoff Lang5d601382014-07-22 15:14:06 -04001515 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1516 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001517 {
1518 return false;
1519 }
1520
Geoff Lang0d8b7242015-09-09 14:56:53 -04001521 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001522 {
1523 return false;
1524 }
1525
Geoff Lang0d8b7242015-09-09 14:56:53 -04001526 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1527 {
1528 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1529 width % formatInfo.compressedBlockWidth != 0) ||
1530 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1531 height % formatInfo.compressedBlockHeight != 0))
1532 {
1533 return false;
1534 }
1535 }
1536
Geoff Langd4f180b2013-09-24 13:57:44 -04001537 return true;
1538}
1539
Geoff Langff5b2d52016-09-07 11:32:23 -04001540bool ValidImageDataSize(ValidationContext *context,
1541 GLenum textureTarget,
1542 GLsizei width,
1543 GLsizei height,
1544 GLsizei depth,
1545 GLenum internalFormat,
1546 GLenum type,
1547 const GLvoid *pixels,
1548 GLsizei imageSize)
1549{
1550 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1551 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1552 {
1553 // Checks are not required
1554 return true;
1555 }
1556
1557 // ...the data would be unpacked from the buffer object such that the memory reads required
1558 // would exceed the data store size.
1559 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1560 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1561 const gl::Extents size(width, height, depth);
1562 const auto &unpack = context->getGLState().getUnpackState();
1563
1564 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1565 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1566 if (endByteOrErr.isError())
1567 {
1568 context->handleError(endByteOrErr.getError());
1569 return false;
1570 }
1571
1572 GLuint endByte = endByteOrErr.getResult();
1573
1574 if (pixelUnpackBuffer)
1575 {
1576 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1577 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1578 checkedEndByte += checkedOffset;
1579
1580 if (!checkedEndByte.IsValid() ||
1581 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1582 {
1583 // Overflow past the end of the buffer
1584 context->handleError(Error(GL_INVALID_OPERATION));
1585 return false;
1586 }
1587 }
1588 else
1589 {
1590 ASSERT(imageSize >= 0);
1591 if (pixels == nullptr && imageSize != 0)
1592 {
1593 context->handleError(
1594 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001595 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001596 }
1597
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001598 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001599 {
1600 context->handleError(
1601 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1602 return false;
1603 }
1604 }
1605
1606 return true;
1607}
1608
Geoff Lang37dde692014-01-31 16:34:54 -05001609bool ValidQueryType(const Context *context, GLenum queryType)
1610{
Geoff Langd4475812015-03-18 10:53:05 -04001611 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1612 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001613
1614 switch (queryType)
1615 {
1616 case GL_ANY_SAMPLES_PASSED:
1617 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1618 return true;
1619 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001620 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621 case GL_TIME_ELAPSED_EXT:
1622 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001623 case GL_COMMANDS_COMPLETED_CHROMIUM:
1624 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001625 default:
1626 return false;
1627 }
1628}
1629
Jamie Madillef300b12016-10-07 15:12:09 -04001630Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001631{
1632 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1633 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1634 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1635
Dian Xiang769769a2015-09-09 15:20:08 -07001636 Program *validProgram = context->getProgram(id);
1637
1638 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001639 {
Dian Xiang769769a2015-09-09 15:20:08 -07001640 if (context->getShader(id))
1641 {
Jamie Madill437fa652016-05-03 15:13:24 -04001642 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001643 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1644 }
1645 else
1646 {
Jamie Madill437fa652016-05-03 15:13:24 -04001647 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001648 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001649 }
Dian Xiang769769a2015-09-09 15:20:08 -07001650
1651 return validProgram;
1652}
1653
Jamie Madillef300b12016-10-07 15:12:09 -04001654Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001655{
1656 // See ValidProgram for spec details.
1657
1658 Shader *validShader = context->getShader(id);
1659
1660 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001661 {
Dian Xiang769769a2015-09-09 15:20:08 -07001662 if (context->getProgram(id))
1663 {
Jamie Madill437fa652016-05-03 15:13:24 -04001664 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001665 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1666 }
1667 else
1668 {
Jamie Madill437fa652016-05-03 15:13:24 -04001669 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001670 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001671 }
Dian Xiang769769a2015-09-09 15:20:08 -07001672
1673 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001674}
1675
Geoff Langb1196682014-07-23 13:47:29 -04001676bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001677{
1678 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1679 {
1680 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1681
Geoff Langaae65a42014-05-26 12:43:44 -04001682 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001685 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001686 }
1687 }
1688 else
1689 {
1690 switch (attachment)
1691 {
1692 case GL_DEPTH_ATTACHMENT:
1693 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001694 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001695
1696 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001697 if (!context->getExtensions().webglCompatibility &&
1698 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001699 {
1700 context->handleError(Error(GL_INVALID_ENUM));
1701 return false;
1702 }
1703 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001704
1705 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001707 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001708 }
1709 }
1710
1711 return true;
1712}
1713
Corentin Walleze0902642014-11-04 12:32:15 -08001714bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1715 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001716{
1717 switch (target)
1718 {
1719 case GL_RENDERBUFFER:
1720 break;
1721 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001722 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001723 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724 }
1725
1726 if (width < 0 || height < 0 || samples < 0)
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001729 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001730 }
1731
Geoff Langd87878e2014-09-19 15:42:59 -04001732 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1733 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001734 {
Jamie Madill437fa652016-05-03 15:13:24 -04001735 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001736 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 }
1738
1739 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1740 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001741 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001742 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001743 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001747 }
1748
Geoff Langaae65a42014-05-26 12:43:44 -04001749 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 }
1754
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001755 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001756 if (handle == 0)
1757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 }
1761
1762 return true;
1763}
1764
Corentin Walleze0902642014-11-04 12:32:15 -08001765bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1766 GLenum internalformat, GLsizei width, GLsizei height)
1767{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001768 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001769
1770 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001771 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001772 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001773 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001776 return false;
1777 }
1778
1779 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1780 // the specified storage. This is different than ES 3.0 in which a sample number higher
1781 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001782 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001783 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001784 {
Geoff Langa4903b72015-03-02 16:02:48 -08001785 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1786 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001789 return false;
1790 }
Corentin Walleze0902642014-11-04 12:32:15 -08001791 }
1792
1793 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1794}
1795
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001796bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1797 GLenum renderbuffertarget, GLuint renderbuffer)
1798{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001799 if (!ValidFramebufferTarget(target))
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001802 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001803 }
1804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001805 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001806
Jamie Madill84115c92015-04-23 15:00:07 -04001807 ASSERT(framebuffer);
1808 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001809 {
Jamie Madill437fa652016-05-03 15:13:24 -04001810 context->handleError(
1811 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001812 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001813 }
1814
Jamie Madillb4472272014-07-03 10:38:55 -04001815 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001816 {
Jamie Madillb4472272014-07-03 10:38:55 -04001817 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001818 }
1819
Jamie Madillab9d82c2014-01-21 16:38:14 -05001820 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1821 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1822 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1823 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1824 if (renderbuffer != 0)
1825 {
1826 if (!context->getRenderbuffer(renderbuffer))
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001830 }
1831 }
1832
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001833 return true;
1834}
1835
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001836bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001837 GLint srcX0,
1838 GLint srcY0,
1839 GLint srcX1,
1840 GLint srcY1,
1841 GLint dstX0,
1842 GLint dstY0,
1843 GLint dstX1,
1844 GLint dstY1,
1845 GLbitfield mask,
1846 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001847{
1848 switch (filter)
1849 {
1850 case GL_NEAREST:
1851 break;
1852 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001853 break;
1854 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001857 }
1858
1859 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001862 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001863 }
1864
1865 if (mask == 0)
1866 {
1867 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1868 // buffers are copied.
1869 return false;
1870 }
1871
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001872 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1873 // color buffer, leaving only nearest being unfiltered from above
1874 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1875 {
Jamie Madill437fa652016-05-03 15:13:24 -04001876 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001877 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001878 }
1879
Jamie Madill51f40ec2016-06-15 14:06:00 -04001880 const auto &glState = context->getGLState();
1881 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1882 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001883
1884 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001888 }
1889
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001890 if (readFramebuffer->id() == drawFramebuffer->id())
1891 {
1892 context->handleError(Error(GL_INVALID_OPERATION));
1893 return false;
1894 }
1895
Jamie Madill51f40ec2016-06-15 14:06:00 -04001896 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001897 {
Jamie Madill437fa652016-05-03 15:13:24 -04001898 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001899 return false;
1900 }
1901
Jamie Madill51f40ec2016-06-15 14:06:00 -04001902 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001905 return false;
1906 }
1907
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001908 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 }
1913
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001914 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1915
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001916 if (mask & GL_COLOR_BUFFER_BIT)
1917 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001918 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1919 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001920 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001921
1922 if (readColorBuffer && drawColorBuffer)
1923 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001924 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001925
Geoff Langa15472a2015-08-11 11:48:03 -04001926 for (size_t drawbufferIdx = 0;
1927 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001928 {
Geoff Langa15472a2015-08-11 11:48:03 -04001929 const FramebufferAttachment *attachment =
1930 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1931 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001932 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001933 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001934
Geoff Langb2f3d052013-08-13 12:49:27 -04001935 // The GL ES 3.0.2 spec (pg 193) states that:
1936 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1937 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1938 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001939 // Changes with EXT_color_buffer_float:
1940 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001941 GLenum readComponentType = readFormat.info->componentType;
1942 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001943 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1944 readComponentType == GL_SIGNED_NORMALIZED);
1945 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1946 drawComponentType == GL_SIGNED_NORMALIZED);
1947
1948 if (extensions.colorBufferFloat)
1949 {
1950 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1951 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1952
1953 if (readFixedOrFloat != drawFixedOrFloat)
1954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001956 "If the read buffer contains fixed-point or "
1957 "floating-point values, the draw buffer "
1958 "must as well."));
1959 return false;
1960 }
1961 }
1962 else if (readFixedPoint != drawFixedPoint)
1963 {
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001965 "If the read buffer contains fixed-point "
1966 "values, the draw buffer must as well."));
1967 return false;
1968 }
1969
1970 if (readComponentType == GL_UNSIGNED_INT &&
1971 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 }
1976
Jamie Madill6163c752015-12-07 16:32:59 -05001977 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001980 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 }
1982
Jamie Madilla3944d42016-07-22 22:13:26 -04001983 if (readColorBuffer->getSamples() > 0 &&
1984 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001988 }
1989 }
1990 }
1991
Jamie Madilla3944d42016-07-22 22:13:26 -04001992 if ((readFormat.info->componentType == GL_INT ||
1993 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1994 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995 {
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001999 }
2000 }
2001
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002002 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
2003 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2004 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002005 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002006 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002007 {
Jamie Madill2d06b732015-04-20 12:53:28 -04002008 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
2009 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002010
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002011 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002012 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002013 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002016 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002017 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002018
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002019 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002022 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002023 }
2024 }
2025 }
2026 }
2027
2028 return true;
2029}
2030
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002031bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 GLint x,
2033 GLint y,
2034 GLsizei width,
2035 GLsizei height,
2036 GLenum format,
2037 GLenum type,
2038 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002039{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002040 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2041}
2042
2043bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2044 GLint x,
2045 GLint y,
2046 GLsizei width,
2047 GLsizei height,
2048 GLenum format,
2049 GLenum type,
2050 GLsizei bufSize,
2051 GLsizei *length,
2052 GLvoid *pixels)
2053{
2054 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002055 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002056 return false;
2057 }
2058
Geoff Lang62fce5b2016-09-30 10:46:35 -04002059 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2060 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002061 {
Geoff Langb1196682014-07-23 13:47:29 -04002062 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002063 }
2064
Geoff Lang62fce5b2016-09-30 10:46:35 -04002065 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002066 {
Geoff Langb1196682014-07-23 13:47:29 -04002067 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002068 }
2069
Jamie Madillc29968b2016-01-20 11:17:23 -05002070 return true;
2071}
2072
2073bool ValidateReadnPixelsEXT(Context *context,
2074 GLint x,
2075 GLint y,
2076 GLsizei width,
2077 GLsizei height,
2078 GLenum format,
2079 GLenum type,
2080 GLsizei bufSize,
2081 GLvoid *pixels)
2082{
2083 if (bufSize < 0)
2084 {
Jamie Madill437fa652016-05-03 15:13:24 -04002085 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002086 return false;
2087 }
2088
Geoff Lang62fce5b2016-09-30 10:46:35 -04002089 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2090 pixels);
2091}
Jamie Madill26e91952014-03-05 15:01:27 -05002092
Geoff Lang62fce5b2016-09-30 10:46:35 -04002093bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2094 GLint x,
2095 GLint y,
2096 GLsizei width,
2097 GLsizei height,
2098 GLenum format,
2099 GLenum type,
2100 GLsizei bufSize,
2101 GLsizei *length,
2102 GLvoid *data)
2103{
2104 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002105 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002106 return false;
2107 }
2108
Geoff Lang62fce5b2016-09-30 10:46:35 -04002109 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002110 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002111 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002112 }
2113
Geoff Lang62fce5b2016-09-30 10:46:35 -04002114 if (!ValidateRobustBufferSize(context, bufSize, *length))
2115 {
2116 return false;
2117 }
2118
2119 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002120}
2121
Olli Etuaho41997e72016-03-10 13:38:39 +02002122bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002123{
2124 if (!context->getExtensions().occlusionQueryBoolean &&
2125 !context->getExtensions().disjointTimerQuery)
2126 {
Jamie Madill437fa652016-05-03 15:13:24 -04002127 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002128 return false;
2129 }
2130
Olli Etuaho41997e72016-03-10 13:38:39 +02002131 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002132}
2133
Olli Etuaho41997e72016-03-10 13:38:39 +02002134bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002135{
2136 if (!context->getExtensions().occlusionQueryBoolean &&
2137 !context->getExtensions().disjointTimerQuery)
2138 {
Jamie Madill437fa652016-05-03 15:13:24 -04002139 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002140 return false;
2141 }
2142
Olli Etuaho41997e72016-03-10 13:38:39 +02002143 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002144}
2145
2146bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002147{
2148 if (!ValidQueryType(context, target))
2149 {
Jamie Madill437fa652016-05-03 15:13:24 -04002150 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002151 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002152 }
2153
2154 if (id == 0)
2155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002157 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002158 }
2159
2160 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2161 // of zero, if the active query object name for <target> is non-zero (for the
2162 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2163 // the active query for either target is non-zero), if <id> is the name of an
2164 // existing query object whose type does not match <target>, or if <id> is the
2165 // active query object name for any query type, the error INVALID_OPERATION is
2166 // generated.
2167
2168 // Ensure no other queries are active
2169 // NOTE: If other queries than occlusion are supported, we will need to check
2170 // separately that:
2171 // a) The query ID passed is not the current active query for any target/type
2172 // b) There are no active queries for the requested target (and in the case
2173 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2174 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002176 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002180 }
2181
2182 Query *queryObject = context->getQuery(id, true, target);
2183
2184 // check that name was obtained with glGenQueries
2185 if (!queryObject)
2186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002189 }
2190
2191 // check for type mismatch
2192 if (queryObject->getType() != target)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002196 }
2197
2198 return true;
2199}
2200
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2202{
2203 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002204 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002207 return false;
2208 }
2209
2210 return ValidateBeginQueryBase(context, target, id);
2211}
2212
2213bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002214{
2215 if (!ValidQueryType(context, target))
2216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002218 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002219 }
2220
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002221 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002222
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002223 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002227 }
2228
Jamie Madill45c785d2014-05-13 14:09:34 -04002229 return true;
2230}
2231
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002232bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2233{
2234 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002235 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002236 {
Jamie Madill437fa652016-05-03 15:13:24 -04002237 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002238 return false;
2239 }
2240
2241 return ValidateEndQueryBase(context, target);
2242}
2243
2244bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2245{
2246 if (!context->getExtensions().disjointTimerQuery)
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 return false;
2250 }
2251
2252 if (target != GL_TIMESTAMP_EXT)
2253 {
Jamie Madill437fa652016-05-03 15:13:24 -04002254 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002255 return false;
2256 }
2257
2258 Query *queryObject = context->getQuery(id, true, target);
2259 if (queryObject == nullptr)
2260 {
Jamie Madill437fa652016-05-03 15:13:24 -04002261 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262 return false;
2263 }
2264
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002265 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002266 {
Jamie Madill437fa652016-05-03 15:13:24 -04002267 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002268 return false;
2269 }
2270
2271 return true;
2272}
2273
Geoff Lang2186c382016-10-14 10:54:54 -04002274bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002275{
Geoff Lang2186c382016-10-14 10:54:54 -04002276 if (numParams)
2277 {
2278 *numParams = 0;
2279 }
2280
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002281 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2282 {
Jamie Madill437fa652016-05-03 15:13:24 -04002283 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002284 return false;
2285 }
2286
2287 switch (pname)
2288 {
2289 case GL_CURRENT_QUERY_EXT:
2290 if (target == GL_TIMESTAMP_EXT)
2291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2294 return false;
2295 }
2296 break;
2297 case GL_QUERY_COUNTER_BITS_EXT:
2298 if (!context->getExtensions().disjointTimerQuery ||
2299 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2300 {
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302 return false;
2303 }
2304 break;
2305 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002306 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002307 return false;
2308 }
2309
Geoff Lang2186c382016-10-14 10:54:54 -04002310 if (numParams)
2311 {
2312 // All queries return only one value
2313 *numParams = 1;
2314 }
2315
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002316 return true;
2317}
2318
2319bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2320{
2321 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002322 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002325 return false;
2326 }
2327
Geoff Lang2186c382016-10-14 10:54:54 -04002328 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002329}
2330
Geoff Lang2186c382016-10-14 10:54:54 -04002331bool ValidateGetQueryivRobustANGLE(Context *context,
2332 GLenum target,
2333 GLenum pname,
2334 GLsizei bufSize,
2335 GLsizei *length,
2336 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337{
Geoff Lang2186c382016-10-14 10:54:54 -04002338 if (!ValidateRobustEntryPoint(context, bufSize))
2339 {
2340 return false;
2341 }
2342
2343 if (!ValidateGetQueryivBase(context, target, pname, length))
2344 {
2345 return false;
2346 }
2347
2348 if (!ValidateRobustBufferSize(context, bufSize, *length))
2349 {
2350 return false;
2351 }
2352
2353 return true;
2354}
2355
2356bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2357{
2358 if (numParams)
2359 {
2360 *numParams = 0;
2361 }
2362
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002363 Query *queryObject = context->getQuery(id, false, GL_NONE);
2364
2365 if (!queryObject)
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 return false;
2369 }
2370
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002371 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374 return false;
2375 }
2376
2377 switch (pname)
2378 {
2379 case GL_QUERY_RESULT_EXT:
2380 case GL_QUERY_RESULT_AVAILABLE_EXT:
2381 break;
2382
2383 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002384 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002385 return false;
2386 }
2387
Geoff Lang2186c382016-10-14 10:54:54 -04002388 if (numParams)
2389 {
2390 *numParams = 1;
2391 }
2392
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002393 return true;
2394}
2395
2396bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2397{
2398 if (!context->getExtensions().disjointTimerQuery)
2399 {
Jamie Madill437fa652016-05-03 15:13:24 -04002400 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002401 return false;
2402 }
Geoff Lang2186c382016-10-14 10:54:54 -04002403 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2404}
2405
2406bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2407 GLuint id,
2408 GLenum pname,
2409 GLsizei bufSize,
2410 GLsizei *length,
2411 GLint *params)
2412{
2413 if (!context->getExtensions().disjointTimerQuery)
2414 {
2415 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2416 return false;
2417 }
2418
2419 if (!ValidateRobustEntryPoint(context, bufSize))
2420 {
2421 return false;
2422 }
2423
2424 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2425 {
2426 return false;
2427 }
2428
2429 if (!ValidateRobustBufferSize(context, bufSize, *length))
2430 {
2431 return false;
2432 }
2433
2434 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002435}
2436
2437bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2438{
2439 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002440 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443 return false;
2444 }
Geoff Lang2186c382016-10-14 10:54:54 -04002445 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2446}
2447
2448bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2449 GLuint id,
2450 GLenum pname,
2451 GLsizei bufSize,
2452 GLsizei *length,
2453 GLuint *params)
2454{
2455 if (!context->getExtensions().disjointTimerQuery &&
2456 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2457 {
2458 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2459 return false;
2460 }
2461
2462 if (!ValidateRobustEntryPoint(context, bufSize))
2463 {
2464 return false;
2465 }
2466
2467 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2468 {
2469 return false;
2470 }
2471
2472 if (!ValidateRobustBufferSize(context, bufSize, *length))
2473 {
2474 return false;
2475 }
2476
2477 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002478}
2479
2480bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2481{
2482 if (!context->getExtensions().disjointTimerQuery)
2483 {
Jamie Madill437fa652016-05-03 15:13:24 -04002484 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002485 return false;
2486 }
Geoff Lang2186c382016-10-14 10:54:54 -04002487 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2488}
2489
2490bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2491 GLuint id,
2492 GLenum pname,
2493 GLsizei bufSize,
2494 GLsizei *length,
2495 GLint64 *params)
2496{
2497 if (!context->getExtensions().disjointTimerQuery)
2498 {
2499 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2500 return false;
2501 }
2502
2503 if (!ValidateRobustEntryPoint(context, bufSize))
2504 {
2505 return false;
2506 }
2507
2508 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2509 {
2510 return false;
2511 }
2512
2513 if (!ValidateRobustBufferSize(context, bufSize, *length))
2514 {
2515 return false;
2516 }
2517
2518 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002519}
2520
2521bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2522{
2523 if (!context->getExtensions().disjointTimerQuery)
2524 {
Jamie Madill437fa652016-05-03 15:13:24 -04002525 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002526 return false;
2527 }
Geoff Lang2186c382016-10-14 10:54:54 -04002528 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2529}
2530
2531bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2532 GLuint id,
2533 GLenum pname,
2534 GLsizei bufSize,
2535 GLsizei *length,
2536 GLuint64 *params)
2537{
2538 if (!context->getExtensions().disjointTimerQuery)
2539 {
2540 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2541 return false;
2542 }
2543
2544 if (!ValidateRobustEntryPoint(context, bufSize))
2545 {
2546 return false;
2547 }
2548
2549 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2550 {
2551 return false;
2552 }
2553
2554 if (!ValidateRobustBufferSize(context, bufSize, *length))
2555 {
2556 return false;
2557 }
2558
2559 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560}
2561
Jamie Madill62d31cb2015-09-11 13:25:51 -04002562static bool ValidateUniformCommonBase(gl::Context *context,
2563 GLenum targetUniformType,
2564 GLint location,
2565 GLsizei count,
2566 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002567{
2568 if (count < 0)
2569 {
Jamie Madill437fa652016-05-03 15:13:24 -04002570 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002571 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002572 }
2573
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002574 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002575 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002576 {
Jamie Madill437fa652016-05-03 15:13:24 -04002577 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002578 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002579 }
2580
Geoff Langd8605522016-04-13 10:19:12 -04002581 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002582 {
2583 // Silently ignore the uniform command
2584 return false;
2585 }
2586
Geoff Lang7dd2e102014-11-10 15:19:26 -05002587 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002588 {
Jamie Madill437fa652016-05-03 15:13:24 -04002589 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002590 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002591 }
2592
Jamie Madill62d31cb2015-09-11 13:25:51 -04002593 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002594
2595 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002596 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002597 {
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002599 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002600 }
2601
Jamie Madill62d31cb2015-09-11 13:25:51 -04002602 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002603 return true;
2604}
2605
Jamie Madillaa981bd2014-05-20 10:55:55 -04002606bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2607{
2608 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002609 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2610 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002611 {
Jamie Madill437fa652016-05-03 15:13:24 -04002612 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002613 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002614 }
2615
Jamie Madill62d31cb2015-09-11 13:25:51 -04002616 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002617 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2618 {
2619 return false;
2620 }
2621
Jamie Madillf2575982014-06-25 16:04:54 -04002622 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002623 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002624 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2625 {
Jamie Madill437fa652016-05-03 15:13:24 -04002626 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002627 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002628 }
2629
2630 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002631}
2632
2633bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2634 GLboolean transpose)
2635{
2636 // Check for ES3 uniform entry points
2637 int rows = VariableRowCount(matrixType);
2638 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002639 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002640 {
Jamie Madill437fa652016-05-03 15:13:24 -04002641 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002643 }
2644
Martin Radev1be913c2016-07-11 17:59:16 +03002645 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002646 {
Jamie Madill437fa652016-05-03 15:13:24 -04002647 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002648 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002649 }
2650
Jamie Madill62d31cb2015-09-11 13:25:51 -04002651 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002652 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2653 {
2654 return false;
2655 }
2656
2657 if (uniform->type != matrixType)
2658 {
Jamie Madill437fa652016-05-03 15:13:24 -04002659 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002660 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002661 }
2662
2663 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002664}
2665
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002666bool ValidateStateQuery(ValidationContext *context,
2667 GLenum pname,
2668 GLenum *nativeType,
2669 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002670{
2671 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2672 {
Jamie Madill437fa652016-05-03 15:13:24 -04002673 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002674 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002675 }
2676
Jamie Madill0af26e12015-03-05 19:54:33 -05002677 const Caps &caps = context->getCaps();
2678
Jamie Madill893ab082014-05-16 16:56:10 -04002679 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2680 {
2681 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2682
Jamie Madill0af26e12015-03-05 19:54:33 -05002683 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002684 {
Jamie Madill437fa652016-05-03 15:13:24 -04002685 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002686 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002687 }
2688 }
2689
2690 switch (pname)
2691 {
2692 case GL_TEXTURE_BINDING_2D:
2693 case GL_TEXTURE_BINDING_CUBE_MAP:
2694 case GL_TEXTURE_BINDING_3D:
2695 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002696 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002697 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002698 if (!context->getExtensions().eglStreamConsumerExternal &&
2699 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002700 {
John Bauman18319182016-09-28 14:22:27 -07002701 context->handleError(Error(GL_INVALID_ENUM,
2702 "Neither NV_EGL_stream_consumer_external nor "
2703 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002704 return false;
2705 }
2706 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002707
2708 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2709 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2710 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002711 if (context->getGLState().getReadFramebuffer()->checkStatus(
2712 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002713 {
Jamie Madill437fa652016-05-03 15:13:24 -04002714 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002716 }
2717
Jamie Madill51f40ec2016-06-15 14:06:00 -04002718 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2719 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002720
2721 if (framebuffer->getReadBufferState() == GL_NONE)
2722 {
2723 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2724 return false;
2725 }
2726
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002727 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002728 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002729 {
Jamie Madill437fa652016-05-03 15:13:24 -04002730 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002731 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002732 }
2733 }
2734 break;
2735
2736 default:
2737 break;
2738 }
2739
2740 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002741 if (*numParams == 0)
2742 {
2743 return false;
2744 }
2745
2746 return true;
2747}
2748
2749bool ValidateRobustStateQuery(ValidationContext *context,
2750 GLenum pname,
2751 GLsizei bufSize,
2752 GLenum *nativeType,
2753 unsigned int *numParams)
2754{
2755 if (!ValidateRobustEntryPoint(context, bufSize))
2756 {
2757 return false;
2758 }
2759
2760 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2761 {
2762 return false;
2763 }
2764
2765 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002766 {
2767 return false;
2768 }
2769
2770 return true;
2771}
2772
Jamie Madillc29968b2016-01-20 11:17:23 -05002773bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2774 GLenum target,
2775 GLint level,
2776 GLenum internalformat,
2777 bool isSubImage,
2778 GLint xoffset,
2779 GLint yoffset,
2780 GLint zoffset,
2781 GLint x,
2782 GLint y,
2783 GLsizei width,
2784 GLsizei height,
2785 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002786 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002787{
Jamie Madill560a8d82014-05-21 13:06:20 -04002788 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2789 {
Jamie Madill437fa652016-05-03 15:13:24 -04002790 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002791 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002792 }
2793
2794 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2795 {
Jamie Madill437fa652016-05-03 15:13:24 -04002796 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002797 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002798 }
2799
2800 if (border != 0)
2801 {
Jamie Madill437fa652016-05-03 15:13:24 -04002802 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002803 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002804 }
2805
2806 if (!ValidMipLevel(context, target, level))
2807 {
Jamie Madill437fa652016-05-03 15:13:24 -04002808 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002809 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002810 }
2811
Jamie Madill51f40ec2016-06-15 14:06:00 -04002812 const auto &state = context->getGLState();
2813 auto readFramebuffer = state.getReadFramebuffer();
2814 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002815 {
Jamie Madill437fa652016-05-03 15:13:24 -04002816 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002817 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002818 }
2819
Jamie Madill51f40ec2016-06-15 14:06:00 -04002820 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002821 {
Jamie Madill437fa652016-05-03 15:13:24 -04002822 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002823 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002824 }
2825
Martin Radev138064f2016-07-15 12:03:41 +03002826 if (readFramebuffer->getReadBufferState() == GL_NONE)
2827 {
2828 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2829 return false;
2830 }
2831
Geoff Langaae65a42014-05-26 12:43:44 -04002832 const gl::Caps &caps = context->getCaps();
2833
Geoff Langaae65a42014-05-26 12:43:44 -04002834 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002835 switch (target)
2836 {
2837 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002838 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002839 break;
2840
2841 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2842 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2843 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2844 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2845 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2846 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002847 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002848 break;
2849
2850 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002851 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002852 break;
2853
2854 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002855 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002856 break;
2857
2858 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002859 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002860 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002861 }
2862
Jamie Madillc29968b2016-01-20 11:17:23 -05002863 gl::Texture *texture =
2864 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002865 if (!texture)
2866 {
Jamie Madill437fa652016-05-03 15:13:24 -04002867 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002868 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002869 }
2870
Geoff Lang69cce582015-09-17 13:20:36 -04002871 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002872 {
Jamie Madill437fa652016-05-03 15:13:24 -04002873 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002874 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002875 }
2876
Geoff Lang5d601382014-07-22 15:14:06 -04002877 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2878
2879 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002880 {
Jamie Madill437fa652016-05-03 15:13:24 -04002881 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002882 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002883 }
2884
Geoff Langa9be0dc2014-12-17 12:34:40 -05002885 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002886 {
Jamie Madill437fa652016-05-03 15:13:24 -04002887 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002888 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002889 }
2890
2891 if (isSubImage)
2892 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002893 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2894 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2895 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002896 {
Jamie Madill437fa652016-05-03 15:13:24 -04002897 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002898 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002899 }
2900 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002901 else
2902 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002903 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002904 {
Jamie Madill437fa652016-05-03 15:13:24 -04002905 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002906 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002907 }
2908
Geoff Langeb66a6e2016-10-31 13:06:12 -04002909 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002910 {
Jamie Madill437fa652016-05-03 15:13:24 -04002911 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002912 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002913 }
2914
2915 int maxLevelDimension = (maxDimension >> level);
2916 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2917 {
Jamie Madill437fa652016-05-03 15:13:24 -04002918 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002919 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002920 }
2921 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002922
Jamie Madill0c8abca2016-07-22 20:21:26 -04002923 if (textureFormatOut)
2924 {
2925 *textureFormatOut = texture->getFormat(target, level);
2926 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002927 return true;
2928}
2929
Jamie Madillf25855c2015-11-03 11:06:18 -05002930static bool ValidateDrawBase(ValidationContext *context,
2931 GLenum mode,
2932 GLsizei count,
2933 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002934{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002935 switch (mode)
2936 {
2937 case GL_POINTS:
2938 case GL_LINES:
2939 case GL_LINE_LOOP:
2940 case GL_LINE_STRIP:
2941 case GL_TRIANGLES:
2942 case GL_TRIANGLE_STRIP:
2943 case GL_TRIANGLE_FAN:
2944 break;
2945 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002946 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002948 }
2949
Jamie Madill250d33f2014-06-06 17:09:03 -04002950 if (count < 0)
2951 {
Jamie Madill437fa652016-05-03 15:13:24 -04002952 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002953 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002954 }
2955
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002956 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002957
Jamie Madill250d33f2014-06-06 17:09:03 -04002958 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002959 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002960 {
Jamie Madill437fa652016-05-03 15:13:24 -04002961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002962 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002963 }
2964
Jamie Madill51f40ec2016-06-15 14:06:00 -04002965 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002966 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002967 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002968 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2969 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2970 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2971 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2972 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2973 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002974 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002975 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2976 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002977 {
2978 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2979 // Section 6.10 of the WebGL 1.0 spec
2980 ERR(
2981 "This ANGLE implementation does not support separate front/back stencil "
2982 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002983 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002984 return false;
2985 }
Jamie Madillac528012014-06-20 13:21:23 -04002986 }
2987
Jamie Madill51f40ec2016-06-15 14:06:00 -04002988 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002989 {
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002992 }
2993
Geoff Lang7dd2e102014-11-10 15:19:26 -05002994 gl::Program *program = state.getProgram();
2995 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002996 {
Jamie Madill437fa652016-05-03 15:13:24 -04002997 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002998 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002999 }
3000
Geoff Lang7dd2e102014-11-10 15:19:26 -05003001 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003002 {
Jamie Madill437fa652016-05-03 15:13:24 -04003003 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003004 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003005 }
3006
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003007 // Uniform buffer validation
3008 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
3009 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003010 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003011 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003012 const OffsetBindingPointer<Buffer> &uniformBuffer =
3013 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003014
Geoff Lang5d124a62015-09-15 13:03:27 -04003015 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003016 {
3017 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(
3019 Error(GL_INVALID_OPERATION,
3020 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003021 return false;
3022 }
3023
Geoff Lang5d124a62015-09-15 13:03:27 -04003024 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003025 if (uniformBufferSize == 0)
3026 {
3027 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003028 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003029 }
3030
Jamie Madill62d31cb2015-09-11 13:25:51 -04003031 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003032 {
3033 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003034 context->handleError(
3035 Error(GL_INVALID_OPERATION,
3036 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003037 return false;
3038 }
3039 }
3040
Jamie Madill250d33f2014-06-06 17:09:03 -04003041 // No-op if zero count
3042 return (count > 0);
3043}
3044
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003045bool ValidateDrawArrays(ValidationContext *context,
3046 GLenum mode,
3047 GLint first,
3048 GLsizei count,
3049 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003050{
Jamie Madillfd716582014-06-06 17:09:04 -04003051 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003052 {
Jamie Madill437fa652016-05-03 15:13:24 -04003053 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003054 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003055 }
3056
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003057 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003058 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003059 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
3060 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003061 {
3062 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
3063 // that does not match the current transform feedback object's draw mode (if transform feedback
3064 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003065 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003066 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003067 }
3068
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003069 if (!ValidateDrawBase(context, mode, count, primcount))
3070 {
3071 return false;
3072 }
3073
3074 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04003075 {
3076 return false;
3077 }
3078
3079 return true;
3080}
3081
Geoff Langb1196682014-07-23 13:47:29 -04003082bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003083{
3084 if (primcount < 0)
3085 {
Jamie Madill437fa652016-05-03 15:13:24 -04003086 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003087 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003088 }
3089
Jamie Madill2b976812014-08-25 15:47:49 -04003090 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003091 {
3092 return false;
3093 }
3094
3095 // No-op if zero primitive count
3096 return (primcount > 0);
3097}
3098
Geoff Lang87a93302014-09-16 13:29:43 -04003099static bool ValidateDrawInstancedANGLE(Context *context)
3100{
3101 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003102 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003103
Geoff Lang7dd2e102014-11-10 15:19:26 -05003104 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003105
3106 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003107 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003108 {
3109 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003110 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003111 {
3112 return true;
3113 }
3114 }
3115
Jamie Madill437fa652016-05-03 15:13:24 -04003116 context->handleError(Error(GL_INVALID_OPERATION,
3117 "ANGLE_instanced_arrays requires that at least one active attribute"
3118 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003119 return false;
3120}
3121
3122bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
3123{
3124 if (!ValidateDrawInstancedANGLE(context))
3125 {
3126 return false;
3127 }
3128
3129 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3130}
3131
Jamie Madillf25855c2015-11-03 11:06:18 -05003132bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003133 GLenum mode,
3134 GLsizei count,
3135 GLenum type,
3136 const GLvoid *indices,
3137 GLsizei primcount,
3138 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003139{
Jamie Madill250d33f2014-06-06 17:09:03 -04003140 switch (type)
3141 {
3142 case GL_UNSIGNED_BYTE:
3143 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03003144 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003145 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03003146 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3147 {
3148 context->handleError(Error(GL_INVALID_ENUM));
3149 return false;
3150 }
3151 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04003152 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03003154 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003155 }
3156
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003157 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003158
3159 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04003160 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003161 {
3162 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
3163 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003164 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003166 }
3167
3168 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003169 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003173 }
3174
Jamie Madill2b976812014-08-25 15:47:49 -04003175 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003176 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003177 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003178 {
Jamie Madill437fa652016-05-03 15:13:24 -04003179 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003181 }
3182
Jamie Madillae3000b2014-08-25 15:47:51 -04003183 if (elementArrayBuffer)
3184 {
3185 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3186
3187 GLint64 offset = reinterpret_cast<GLint64>(indices);
3188 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
3189
3190 // check for integer overflows
3191 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3192 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3193 {
Jamie Madill437fa652016-05-03 15:13:24 -04003194 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003195 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003196 }
3197
3198 // Check for reading past the end of the bound buffer object
3199 if (byteCount > elementArrayBuffer->getSize())
3200 {
Jamie Madill437fa652016-05-03 15:13:24 -04003201 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003202 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003203 }
3204 }
3205 else if (!indices)
3206 {
3207 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003208 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003209 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003210 }
3211
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003212 if (!ValidateDrawBase(context, mode, count, primcount))
3213 {
3214 return false;
3215 }
3216
Jamie Madill2b976812014-08-25 15:47:49 -04003217 // Use max index to validate if our vertex buffers are large enough for the pull.
3218 // TODO: offer fast path, with disabled index validation.
3219 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3220 if (elementArrayBuffer)
3221 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003222 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003223 Error error =
3224 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3225 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003226 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003227 {
Jamie Madill437fa652016-05-03 15:13:24 -04003228 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003229 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003230 }
3231 }
3232 else
3233 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003234 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003235 }
3236
Jamie Madille79b1e12015-11-04 16:36:37 -05003237 // If we use an index greater than our maximum supported index range, return an error.
3238 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3239 // return an error if possible here.
3240 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3241 {
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003243 return false;
3244 }
3245
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04003246 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003247 {
3248 return false;
3249 }
3250
Geoff Lang3edfe032015-09-04 16:38:24 -04003251 // No op if there are no real indices in the index data (all are primitive restart).
3252 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003253}
3254
Geoff Langb1196682014-07-23 13:47:29 -04003255bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003256 GLenum mode,
3257 GLsizei count,
3258 GLenum type,
3259 const GLvoid *indices,
3260 GLsizei primcount,
3261 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003262{
3263 if (primcount < 0)
3264 {
Jamie Madill437fa652016-05-03 15:13:24 -04003265 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003266 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003267 }
3268
Jamie Madill2b976812014-08-25 15:47:49 -04003269 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003270 {
3271 return false;
3272 }
3273
3274 // No-op zero primitive count
3275 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003276}
3277
Geoff Lang3edfe032015-09-04 16:38:24 -04003278bool ValidateDrawElementsInstancedANGLE(Context *context,
3279 GLenum mode,
3280 GLsizei count,
3281 GLenum type,
3282 const GLvoid *indices,
3283 GLsizei primcount,
3284 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003285{
3286 if (!ValidateDrawInstancedANGLE(context))
3287 {
3288 return false;
3289 }
3290
3291 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3292}
3293
Geoff Langb1196682014-07-23 13:47:29 -04003294bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003295 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003296{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003297 if (!ValidFramebufferTarget(target))
3298 {
Jamie Madill437fa652016-05-03 15:13:24 -04003299 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003300 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003301 }
3302
3303 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003304 {
3305 return false;
3306 }
3307
Jamie Madill55ec3b12014-07-03 10:38:57 -04003308 if (texture != 0)
3309 {
3310 gl::Texture *tex = context->getTexture(texture);
3311
3312 if (tex == NULL)
3313 {
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003315 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003316 }
3317
3318 if (level < 0)
3319 {
Jamie Madill437fa652016-05-03 15:13:24 -04003320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003321 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003322 }
3323 }
3324
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003325 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003326 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003327
Jamie Madill84115c92015-04-23 15:00:07 -04003328 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003329 {
Jamie Madill437fa652016-05-03 15:13:24 -04003330 context->handleError(
3331 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003332 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003333 }
3334
3335 return true;
3336}
3337
Geoff Langb1196682014-07-23 13:47:29 -04003338bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003339 GLenum textarget, GLuint texture, GLint level)
3340{
Geoff Lang95663912015-04-02 15:54:45 -04003341 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension
Martin Radev1be913c2016-07-11 17:59:16 +03003342 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3343 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003344 {
Jamie Madill437fa652016-05-03 15:13:24 -04003345 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003346 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003347 }
3348
3349 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003350 {
3351 return false;
3352 }
3353
Jamie Madill55ec3b12014-07-03 10:38:57 -04003354 if (texture != 0)
3355 {
3356 gl::Texture *tex = context->getTexture(texture);
3357 ASSERT(tex);
3358
Jamie Madill2a6564e2014-07-11 09:53:19 -04003359 const gl::Caps &caps = context->getCaps();
3360
Jamie Madill55ec3b12014-07-03 10:38:57 -04003361 switch (textarget)
3362 {
3363 case GL_TEXTURE_2D:
3364 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003365 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003366 {
Jamie Madill437fa652016-05-03 15:13:24 -04003367 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003368 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003369 }
3370 if (tex->getTarget() != GL_TEXTURE_2D)
3371 {
Jamie Madill437fa652016-05-03 15:13:24 -04003372 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003373 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003374 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003375 }
3376 break;
3377
3378 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3379 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3380 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3381 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3382 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3383 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3384 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003385 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003386 {
Jamie Madill437fa652016-05-03 15:13:24 -04003387 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003388 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003389 }
3390 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3391 {
Jamie Madill437fa652016-05-03 15:13:24 -04003392 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003393 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003394 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003395 }
3396 break;
3397
3398 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003399 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003400 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003401 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003402
Jamie Madilla3944d42016-07-22 22:13:26 -04003403 const Format &format = tex->getFormat(textarget, level);
3404 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003405 {
Jamie Madill437fa652016-05-03 15:13:24 -04003406 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003407 return false;
3408 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003409 }
3410
Jamie Madill570f7c82014-07-03 10:38:54 -04003411 return true;
3412}
3413
Geoff Langb1196682014-07-23 13:47:29 -04003414bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003415{
3416 if (program == 0)
3417 {
Jamie Madill437fa652016-05-03 15:13:24 -04003418 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003419 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003420 }
3421
Dian Xiang769769a2015-09-09 15:20:08 -07003422 gl::Program *programObject = GetValidProgram(context, program);
3423 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003424 {
3425 return false;
3426 }
3427
Jamie Madill0063c512014-08-25 15:47:53 -04003428 if (!programObject || !programObject->isLinked())
3429 {
Jamie Madill437fa652016-05-03 15:13:24 -04003430 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003431 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003432 }
3433
Geoff Lang7dd2e102014-11-10 15:19:26 -05003434 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003435 {
Jamie Madill437fa652016-05-03 15:13:24 -04003436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003437 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003438 }
3439
Jamie Madill0063c512014-08-25 15:47:53 -04003440 return true;
3441}
3442
Geoff Langb1196682014-07-23 13:47:29 -04003443bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003444{
3445 return ValidateGetUniformBase(context, program, location);
3446}
3447
Geoff Langb1196682014-07-23 13:47:29 -04003448bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003449{
Jamie Madill78f41802014-08-25 15:47:55 -04003450 return ValidateGetUniformBase(context, program, location);
3451}
3452
Geoff Langf41d0ee2016-10-07 13:04:23 -04003453static bool ValidateSizedGetUniform(Context *context,
3454 GLuint program,
3455 GLint location,
3456 GLsizei bufSize,
3457 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003458{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003459 if (length)
3460 {
3461 *length = 0;
3462 }
3463
Jamie Madill78f41802014-08-25 15:47:55 -04003464 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003465 {
Jamie Madill78f41802014-08-25 15:47:55 -04003466 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003467 }
3468
Geoff Langf41d0ee2016-10-07 13:04:23 -04003469 if (bufSize < 0)
3470 {
3471 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3472 return false;
3473 }
3474
Jamie Madilla502c742014-08-28 17:19:13 -04003475 gl::Program *programObject = context->getProgram(program);
3476 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003477
Jamie Madill78f41802014-08-25 15:47:55 -04003478 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003479 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3480 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003481 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003482 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003483 context->handleError(
3484 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003485 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003486 }
3487
Geoff Langf41d0ee2016-10-07 13:04:23 -04003488 if (length)
3489 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003490 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003491 }
3492
Jamie Madill0063c512014-08-25 15:47:53 -04003493 return true;
3494}
3495
Geoff Langb1196682014-07-23 13:47:29 -04003496bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003497{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003498 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003499}
3500
Geoff Langb1196682014-07-23 13:47:29 -04003501bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003502{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003503 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3504}
3505
3506bool ValidateGetUniformfvRobustANGLE(Context *context,
3507 GLuint program,
3508 GLint location,
3509 GLsizei bufSize,
3510 GLsizei *length,
3511 GLfloat *params)
3512{
3513 if (!ValidateRobustEntryPoint(context, bufSize))
3514 {
3515 return false;
3516 }
3517
3518 // bufSize is validated in ValidateSizedGetUniform
3519 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3520}
3521
3522bool ValidateGetUniformivRobustANGLE(Context *context,
3523 GLuint program,
3524 GLint location,
3525 GLsizei bufSize,
3526 GLsizei *length,
3527 GLint *params)
3528{
3529 if (!ValidateRobustEntryPoint(context, bufSize))
3530 {
3531 return false;
3532 }
3533
3534 // bufSize is validated in ValidateSizedGetUniform
3535 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3536}
3537
3538bool ValidateGetUniformuivRobustANGLE(Context *context,
3539 GLuint program,
3540 GLint location,
3541 GLsizei bufSize,
3542 GLsizei *length,
3543 GLuint *params)
3544{
3545 if (!ValidateRobustEntryPoint(context, bufSize))
3546 {
3547 return false;
3548 }
3549
3550 if (context->getClientMajorVersion() < 3)
3551 {
3552 context->handleError(
3553 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3554 return false;
3555 }
3556
3557 // bufSize is validated in ValidateSizedGetUniform
3558 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003559}
3560
Austin Kinross08332632015-05-05 13:35:47 -07003561bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3562 const GLenum *attachments, bool defaultFramebuffer)
3563{
3564 if (numAttachments < 0)
3565 {
Jamie Madill437fa652016-05-03 15:13:24 -04003566 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003567 return false;
3568 }
3569
3570 for (GLsizei i = 0; i < numAttachments; ++i)
3571 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003572 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003573 {
3574 if (defaultFramebuffer)
3575 {
Jamie Madill437fa652016-05-03 15:13:24 -04003576 context->handleError(Error(
3577 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003578 return false;
3579 }
3580
3581 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3582 {
Jamie Madill437fa652016-05-03 15:13:24 -04003583 context->handleError(Error(GL_INVALID_OPERATION,
3584 "Requested color attachment is greater than the maximum "
3585 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003586 return false;
3587 }
3588 }
3589 else
3590 {
3591 switch (attachments[i])
3592 {
3593 case GL_DEPTH_ATTACHMENT:
3594 case GL_STENCIL_ATTACHMENT:
3595 case GL_DEPTH_STENCIL_ATTACHMENT:
3596 if (defaultFramebuffer)
3597 {
Jamie Madill437fa652016-05-03 15:13:24 -04003598 context->handleError(
3599 Error(GL_INVALID_ENUM,
3600 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003601 return false;
3602 }
3603 break;
3604 case GL_COLOR:
3605 case GL_DEPTH:
3606 case GL_STENCIL:
3607 if (!defaultFramebuffer)
3608 {
Jamie Madill437fa652016-05-03 15:13:24 -04003609 context->handleError(
3610 Error(GL_INVALID_ENUM,
3611 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003612 return false;
3613 }
3614 break;
3615 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003616 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003617 return false;
3618 }
3619 }
3620 }
3621
3622 return true;
3623}
3624
Austin Kinross6ee1e782015-05-29 17:05:37 -07003625bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3626{
3627 // Note that debug marker calls must not set error state
3628
3629 if (length < 0)
3630 {
3631 return false;
3632 }
3633
3634 if (marker == nullptr)
3635 {
3636 return false;
3637 }
3638
3639 return true;
3640}
3641
3642bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3643{
3644 // Note that debug marker calls must not set error state
3645
3646 if (length < 0)
3647 {
3648 return false;
3649 }
3650
3651 if (length > 0 && marker == nullptr)
3652 {
3653 return false;
3654 }
3655
3656 return true;
3657}
3658
Geoff Langdcab33b2015-07-21 13:03:16 -04003659bool ValidateEGLImageTargetTexture2DOES(Context *context,
3660 egl::Display *display,
3661 GLenum target,
3662 egl::Image *image)
3663{
Geoff Langa8406172015-07-21 16:53:39 -04003664 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3665 {
Jamie Madill437fa652016-05-03 15:13:24 -04003666 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003667 return false;
3668 }
3669
3670 switch (target)
3671 {
3672 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003673 if (!context->getExtensions().eglImage)
3674 {
3675 context->handleError(Error(
3676 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3677 }
3678 break;
3679
3680 case GL_TEXTURE_EXTERNAL_OES:
3681 if (!context->getExtensions().eglImageExternal)
3682 {
3683 context->handleError(Error(
3684 GL_INVALID_ENUM,
3685 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3686 }
Geoff Langa8406172015-07-21 16:53:39 -04003687 break;
3688
3689 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003690 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003691 return false;
3692 }
3693
3694 if (!display->isValidImage(image))
3695 {
Jamie Madill437fa652016-05-03 15:13:24 -04003696 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003697 return false;
3698 }
3699
3700 if (image->getSamples() > 0)
3701 {
Jamie Madill437fa652016-05-03 15:13:24 -04003702 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003703 "cannot create a 2D texture from a multisampled EGL image."));
3704 return false;
3705 }
3706
Jamie Madilla3944d42016-07-22 22:13:26 -04003707 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003708 if (!textureCaps.texturable)
3709 {
Jamie Madill437fa652016-05-03 15:13:24 -04003710 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003711 "EGL image internal format is not supported as a texture."));
3712 return false;
3713 }
3714
Geoff Langdcab33b2015-07-21 13:03:16 -04003715 return true;
3716}
3717
3718bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3719 egl::Display *display,
3720 GLenum target,
3721 egl::Image *image)
3722{
Geoff Langa8406172015-07-21 16:53:39 -04003723 if (!context->getExtensions().eglImage)
3724 {
Jamie Madill437fa652016-05-03 15:13:24 -04003725 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003726 return false;
3727 }
3728
3729 switch (target)
3730 {
3731 case GL_RENDERBUFFER:
3732 break;
3733
3734 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003735 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003736 return false;
3737 }
3738
3739 if (!display->isValidImage(image))
3740 {
Jamie Madill437fa652016-05-03 15:13:24 -04003741 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003742 return false;
3743 }
3744
Jamie Madilla3944d42016-07-22 22:13:26 -04003745 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003746 if (!textureCaps.renderable)
3747 {
Jamie Madill437fa652016-05-03 15:13:24 -04003748 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003749 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3750 return false;
3751 }
3752
Geoff Langdcab33b2015-07-21 13:03:16 -04003753 return true;
3754}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003755
3756bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3757{
Geoff Lang36167ab2015-12-07 10:27:14 -05003758 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003759 {
3760 // The default VAO should always exist
3761 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003762 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003763 return false;
3764 }
3765
3766 return true;
3767}
3768
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003769bool ValidateLinkProgram(Context *context, GLuint program)
3770{
3771 if (context->hasActiveTransformFeedback(program))
3772 {
3773 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003775 "Cannot link program while program is associated with an active "
3776 "transform feedback object."));
3777 return false;
3778 }
3779 return true;
3780}
3781
Geoff Langc5629752015-12-07 16:29:04 -05003782bool ValidateProgramBinaryBase(Context *context,
3783 GLuint program,
3784 GLenum binaryFormat,
3785 const void *binary,
3786 GLint length)
3787{
3788 Program *programObject = GetValidProgram(context, program);
3789 if (programObject == nullptr)
3790 {
3791 return false;
3792 }
3793
3794 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3795 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3796 programBinaryFormats.end())
3797 {
Jamie Madill437fa652016-05-03 15:13:24 -04003798 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003799 return false;
3800 }
3801
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003802 if (context->hasActiveTransformFeedback(program))
3803 {
3804 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003806 "Cannot change program binary while program is associated with "
3807 "an active transform feedback object."));
3808 return false;
3809 }
3810
Geoff Langc5629752015-12-07 16:29:04 -05003811 return true;
3812}
3813
3814bool ValidateGetProgramBinaryBase(Context *context,
3815 GLuint program,
3816 GLsizei bufSize,
3817 GLsizei *length,
3818 GLenum *binaryFormat,
3819 void *binary)
3820{
3821 Program *programObject = GetValidProgram(context, program);
3822 if (programObject == nullptr)
3823 {
3824 return false;
3825 }
3826
3827 if (!programObject->isLinked())
3828 {
Jamie Madill437fa652016-05-03 15:13:24 -04003829 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003830 return false;
3831 }
3832
3833 return true;
3834}
Jamie Madillc29968b2016-01-20 11:17:23 -05003835
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003836bool ValidateUseProgram(Context *context, GLuint program)
3837{
3838 if (program != 0)
3839 {
3840 Program *programObject = context->getProgram(program);
3841 if (!programObject)
3842 {
3843 // ES 3.1.0 section 7.3 page 72
3844 if (context->getShader(program))
3845 {
Jamie Madill437fa652016-05-03 15:13:24 -04003846 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003847 Error(GL_INVALID_OPERATION,
3848 "Attempted to use a single shader instead of a shader program."));
3849 return false;
3850 }
3851 else
3852 {
Jamie Madill437fa652016-05-03 15:13:24 -04003853 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003854 return false;
3855 }
3856 }
3857 if (!programObject->isLinked())
3858 {
Jamie Madill437fa652016-05-03 15:13:24 -04003859 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003860 return false;
3861 }
3862 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003863 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003864 {
3865 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003866 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003867 Error(GL_INVALID_OPERATION,
3868 "Cannot change active program while transform feedback is unpaused."));
3869 return false;
3870 }
3871
3872 return true;
3873}
3874
Jamie Madillc29968b2016-01-20 11:17:23 -05003875bool ValidateCopyTexImage2D(ValidationContext *context,
3876 GLenum target,
3877 GLint level,
3878 GLenum internalformat,
3879 GLint x,
3880 GLint y,
3881 GLsizei width,
3882 GLsizei height,
3883 GLint border)
3884{
Martin Radev1be913c2016-07-11 17:59:16 +03003885 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003886 {
3887 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3888 0, x, y, width, height, border);
3889 }
3890
Martin Radev1be913c2016-07-11 17:59:16 +03003891 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003892 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3893 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003894}
Jamie Madillc29968b2016-01-20 11:17:23 -05003895
3896bool ValidateFramebufferRenderbuffer(Context *context,
3897 GLenum target,
3898 GLenum attachment,
3899 GLenum renderbuffertarget,
3900 GLuint renderbuffer)
3901{
3902 if (!ValidFramebufferTarget(target) ||
3903 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3904 {
Jamie Madill437fa652016-05-03 15:13:24 -04003905 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003906 return false;
3907 }
3908
3909 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3910 renderbuffertarget, renderbuffer);
3911}
3912
3913bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3914{
3915 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3916 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3917 {
Jamie Madill437fa652016-05-03 15:13:24 -04003918 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003919 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3920 return false;
3921 }
3922
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003923 ASSERT(context->getGLState().getDrawFramebuffer());
3924 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003925 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3926
3927 // This should come first before the check for the default frame buffer
3928 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3929 // rather than INVALID_OPERATION
3930 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3931 {
3932 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3933
3934 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003935 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3936 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003937 {
3938 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003939 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3940 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3941 // 3.1 is still a bit ambiguous about the error, but future specs are
3942 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003943 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003944 return false;
3945 }
3946 else if (bufs[colorAttachment] >= maxColorAttachment)
3947 {
Jamie Madill437fa652016-05-03 15:13:24 -04003948 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003949 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003950 return false;
3951 }
3952 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3953 frameBufferId != 0)
3954 {
3955 // INVALID_OPERATION-GL is bound to buffer and ith argument
3956 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003957 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003958 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3959 return false;
3960 }
3961 }
3962
3963 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3964 // and n is not 1 or bufs is bound to value other than BACK and NONE
3965 if (frameBufferId == 0)
3966 {
3967 if (n != 1)
3968 {
Jamie Madill437fa652016-05-03 15:13:24 -04003969 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003970 "n must be 1 when GL is bound to the default framebuffer"));
3971 return false;
3972 }
3973
3974 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3975 {
Jamie Madill437fa652016-05-03 15:13:24 -04003976 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003977 GL_INVALID_OPERATION,
3978 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3979 return false;
3980 }
3981 }
3982
3983 return true;
3984}
3985
3986bool ValidateCopyTexSubImage2D(Context *context,
3987 GLenum target,
3988 GLint level,
3989 GLint xoffset,
3990 GLint yoffset,
3991 GLint x,
3992 GLint y,
3993 GLsizei width,
3994 GLsizei height)
3995{
Martin Radev1be913c2016-07-11 17:59:16 +03003996 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003997 {
3998 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3999 yoffset, x, y, width, height, 0);
4000 }
4001
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004002 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4003 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004004}
4005
Geoff Lang496c02d2016-10-20 11:38:11 -07004006bool ValidateGetBufferPointervBase(Context *context,
4007 GLenum target,
4008 GLenum pname,
4009 GLsizei *length,
4010 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004011{
Geoff Lang496c02d2016-10-20 11:38:11 -07004012 if (length)
4013 {
4014 *length = 0;
4015 }
4016
4017 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4018 {
4019 context->handleError(
4020 Error(GL_INVALID_OPERATION,
4021 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4022 return false;
4023 }
4024
Olli Etuaho4f667482016-03-30 15:56:35 +03004025 if (!ValidBufferTarget(context, target))
4026 {
Jamie Madill437fa652016-05-03 15:13:24 -04004027 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004028 return false;
4029 }
4030
Geoff Lang496c02d2016-10-20 11:38:11 -07004031 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004032 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004033 case GL_BUFFER_MAP_POINTER:
4034 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004035
Geoff Lang496c02d2016-10-20 11:38:11 -07004036 default:
4037 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4038 return false;
4039 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004040
4041 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4042 // target bound to zero generate an INVALID_OPERATION error."
4043 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004044 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004045 {
Jamie Madill437fa652016-05-03 15:13:24 -04004046 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004047 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4048 return false;
4049 }
4050
Geoff Lang496c02d2016-10-20 11:38:11 -07004051 if (length)
4052 {
4053 *length = 1;
4054 }
4055
Olli Etuaho4f667482016-03-30 15:56:35 +03004056 return true;
4057}
4058
4059bool ValidateUnmapBufferBase(Context *context, GLenum target)
4060{
4061 if (!ValidBufferTarget(context, target))
4062 {
Jamie Madill437fa652016-05-03 15:13:24 -04004063 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004064 return false;
4065 }
4066
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004067 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004068
4069 if (buffer == nullptr || !buffer->isMapped())
4070 {
Jamie Madill437fa652016-05-03 15:13:24 -04004071 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004072 return false;
4073 }
4074
4075 return true;
4076}
4077
4078bool ValidateMapBufferRangeBase(Context *context,
4079 GLenum target,
4080 GLintptr offset,
4081 GLsizeiptr length,
4082 GLbitfield access)
4083{
4084 if (!ValidBufferTarget(context, target))
4085 {
Jamie Madill437fa652016-05-03 15:13:24 -04004086 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004087 return false;
4088 }
4089
4090 if (offset < 0 || length < 0)
4091 {
Jamie Madill437fa652016-05-03 15:13:24 -04004092 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004093 return false;
4094 }
4095
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004096 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004097
4098 if (!buffer)
4099 {
Jamie Madill437fa652016-05-03 15:13:24 -04004100 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004101 return false;
4102 }
4103
4104 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004105 CheckedNumeric<size_t> checkedOffset(offset);
4106 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004107
Jamie Madille2e406c2016-06-02 13:04:10 -04004108 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004109 {
Jamie Madill437fa652016-05-03 15:13:24 -04004110 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004111 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4112 return false;
4113 }
4114
4115 // Check for invalid bits in the mask
4116 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4117 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4118 GL_MAP_UNSYNCHRONIZED_BIT;
4119
4120 if (access & ~(allAccessBits))
4121 {
Jamie Madill437fa652016-05-03 15:13:24 -04004122 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004123 return false;
4124 }
4125
4126 if (length == 0)
4127 {
Jamie Madill437fa652016-05-03 15:13:24 -04004128 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004129 return false;
4130 }
4131
4132 if (buffer->isMapped())
4133 {
Jamie Madill437fa652016-05-03 15:13:24 -04004134 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004135 return false;
4136 }
4137
4138 // Check for invalid bit combinations
4139 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4140 {
Jamie Madill437fa652016-05-03 15:13:24 -04004141 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004142 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4143 return false;
4144 }
4145
4146 GLbitfield writeOnlyBits =
4147 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4148
4149 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4150 {
Jamie Madill437fa652016-05-03 15:13:24 -04004151 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004152 "Invalid access bits when mapping buffer for reading: 0x%X.",
4153 access));
4154 return false;
4155 }
4156
4157 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4158 {
Jamie Madill437fa652016-05-03 15:13:24 -04004159 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004160 GL_INVALID_OPERATION,
4161 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4162 return false;
4163 }
4164 return true;
4165}
4166
4167bool ValidateFlushMappedBufferRangeBase(Context *context,
4168 GLenum target,
4169 GLintptr offset,
4170 GLsizeiptr length)
4171{
4172 if (offset < 0 || length < 0)
4173 {
Jamie Madill437fa652016-05-03 15:13:24 -04004174 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004175 return false;
4176 }
4177
4178 if (!ValidBufferTarget(context, target))
4179 {
Jamie Madill437fa652016-05-03 15:13:24 -04004180 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004181 return false;
4182 }
4183
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004184 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004185
4186 if (buffer == nullptr)
4187 {
Jamie Madill437fa652016-05-03 15:13:24 -04004188 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004189 return false;
4190 }
4191
4192 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4193 {
Jamie Madill437fa652016-05-03 15:13:24 -04004194 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004195 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4196 return false;
4197 }
4198
4199 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004200 CheckedNumeric<size_t> checkedOffset(offset);
4201 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004202
Jamie Madille2e406c2016-06-02 13:04:10 -04004203 if (!checkedSize.IsValid() ||
4204 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004205 {
Jamie Madill437fa652016-05-03 15:13:24 -04004206 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004207 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4208 return false;
4209 }
4210
4211 return true;
4212}
4213
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004214bool ValidateGenerateMipmap(Context *context, GLenum target)
4215{
4216 if (!ValidTextureTarget(context, target))
4217 {
4218 context->handleError(Error(GL_INVALID_ENUM));
4219 return false;
4220 }
4221
4222 Texture *texture = context->getTargetTexture(target);
4223
4224 if (texture == nullptr)
4225 {
4226 context->handleError(Error(GL_INVALID_OPERATION));
4227 return false;
4228 }
4229
4230 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4231
4232 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4233 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4234 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4235 {
4236 context->handleError(Error(GL_INVALID_OPERATION));
4237 return false;
4238 }
4239
Jamie Madilla3944d42016-07-22 22:13:26 -04004240 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4241 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4242 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004243
4244 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4245 // unsized formats or that are color renderable and filterable. Since we do not track if
4246 // the texture was created with sized or unsized format (only sized formats are stored),
4247 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4248 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4249 // textures since they're the only texture format that can be created with unsized formats
4250 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4251 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004252 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4253 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004254 {
4255 context->handleError(Error(GL_INVALID_OPERATION));
4256 return false;
4257 }
4258
4259 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004260 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004261 {
4262 context->handleError(Error(GL_INVALID_OPERATION));
4263 return false;
4264 }
4265
4266 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004267 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004268 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4269 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4270 {
Geoff Lang55482a12016-11-21 16:54:01 -05004271 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004272 context->handleError(Error(GL_INVALID_OPERATION));
4273 return false;
4274 }
4275
4276 // Cube completeness check
4277 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4278 {
4279 context->handleError(Error(GL_INVALID_OPERATION));
4280 return false;
4281 }
4282
4283 return true;
4284}
4285
Olli Etuaho41997e72016-03-10 13:38:39 +02004286bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4287{
4288 return ValidateGenOrDelete(context, n);
4289}
4290
4291bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4292{
4293 return ValidateGenOrDelete(context, n);
4294}
4295
4296bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4297{
4298 return ValidateGenOrDelete(context, n);
4299}
4300
4301bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4302{
4303 return ValidateGenOrDelete(context, n);
4304}
4305
4306bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4307{
4308 return ValidateGenOrDelete(context, n);
4309}
4310
4311bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4312{
4313 return ValidateGenOrDelete(context, n);
4314}
4315
4316bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4317{
4318 return ValidateGenOrDelete(context, n);
4319}
4320
4321bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4322{
4323 return ValidateGenOrDelete(context, n);
4324}
4325
4326bool ValidateGenOrDelete(Context *context, GLint n)
4327{
4328 if (n < 0)
4329 {
Jamie Madill437fa652016-05-03 15:13:24 -04004330 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004331 return false;
4332 }
4333 return true;
4334}
4335
Geoff Langf41a7152016-09-19 15:11:17 -04004336bool ValidateEnable(Context *context, GLenum cap)
4337{
4338 if (!ValidCap(context, cap, false))
4339 {
4340 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4341 return false;
4342 }
4343
4344 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4345 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4346 {
4347 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4348 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4349
4350 // We also output an error message to the debugger window if tracing is active, so that
4351 // developers can see the error message.
4352 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004353 return false;
4354 }
4355
4356 return true;
4357}
4358
4359bool ValidateDisable(Context *context, GLenum cap)
4360{
4361 if (!ValidCap(context, cap, false))
4362 {
4363 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4364 return false;
4365 }
4366
4367 return true;
4368}
4369
4370bool ValidateIsEnabled(Context *context, GLenum cap)
4371{
4372 if (!ValidCap(context, cap, true))
4373 {
4374 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4375 return false;
4376 }
4377
4378 return true;
4379}
4380
Geoff Langff5b2d52016-09-07 11:32:23 -04004381bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4382{
4383 if (!context->getExtensions().robustClientMemory)
4384 {
4385 context->handleError(
4386 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4387 return false;
4388 }
4389
4390 if (bufSize < 0)
4391 {
4392 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4393 return false;
4394 }
4395
4396 return true;
4397}
4398
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004399bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4400{
4401 if (bufSize < numParams)
4402 {
4403 context->handleError(Error(GL_INVALID_OPERATION,
4404 "%u parameters are required but %i were provided.", numParams,
4405 bufSize));
4406 return false;
4407 }
4408
4409 return true;
4410}
4411
Geoff Langff5b2d52016-09-07 11:32:23 -04004412bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4413 GLenum target,
4414 GLenum attachment,
4415 GLenum pname,
4416 GLsizei *numParams)
4417{
4418 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4419 *numParams = 1;
4420
4421 if (!ValidFramebufferTarget(target))
4422 {
4423 context->handleError(Error(GL_INVALID_ENUM));
4424 return false;
4425 }
4426
4427 int clientVersion = context->getClientMajorVersion();
4428
4429 switch (pname)
4430 {
4431 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4432 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4433 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4434 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4435 break;
4436
4437 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4438 if (clientVersion < 3 && !context->getExtensions().sRGB)
4439 {
4440 context->handleError(Error(GL_INVALID_ENUM));
4441 return false;
4442 }
4443 break;
4444
4445 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4446 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4447 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4448 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4449 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4450 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4451 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4452 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4453 if (clientVersion < 3)
4454 {
4455 context->handleError(Error(GL_INVALID_ENUM));
4456 return false;
4457 }
4458 break;
4459
4460 default:
4461 context->handleError(Error(GL_INVALID_ENUM));
4462 return false;
4463 }
4464
4465 // Determine if the attachment is a valid enum
4466 switch (attachment)
4467 {
4468 case GL_BACK:
4469 case GL_FRONT:
4470 case GL_DEPTH:
4471 case GL_STENCIL:
4472 case GL_DEPTH_STENCIL_ATTACHMENT:
4473 if (clientVersion < 3)
4474 {
4475 context->handleError(Error(GL_INVALID_ENUM));
4476 return false;
4477 }
4478 break;
4479
4480 case GL_DEPTH_ATTACHMENT:
4481 case GL_STENCIL_ATTACHMENT:
4482 break;
4483
4484 default:
4485 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4486 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4487 {
4488 context->handleError(Error(GL_INVALID_ENUM));
4489 return false;
4490 }
4491 break;
4492 }
4493
4494 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4495 ASSERT(framebuffer);
4496
4497 if (framebuffer->id() == 0)
4498 {
4499 if (clientVersion < 3)
4500 {
4501 context->handleError(Error(GL_INVALID_OPERATION));
4502 return false;
4503 }
4504
4505 switch (attachment)
4506 {
4507 case GL_BACK:
4508 case GL_DEPTH:
4509 case GL_STENCIL:
4510 break;
4511
4512 default:
4513 context->handleError(Error(GL_INVALID_OPERATION));
4514 return false;
4515 }
4516 }
4517 else
4518 {
4519 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4520 {
4521 // Valid attachment query
4522 }
4523 else
4524 {
4525 switch (attachment)
4526 {
4527 case GL_DEPTH_ATTACHMENT:
4528 case GL_STENCIL_ATTACHMENT:
4529 break;
4530
4531 case GL_DEPTH_STENCIL_ATTACHMENT:
4532 if (!framebuffer->hasValidDepthStencil())
4533 {
4534 context->handleError(Error(GL_INVALID_OPERATION));
4535 return false;
4536 }
4537 break;
4538
4539 default:
4540 context->handleError(Error(GL_INVALID_OPERATION));
4541 return false;
4542 }
4543 }
4544 }
4545
4546 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4547 if (attachmentObject)
4548 {
4549 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4550 attachmentObject->type() == GL_TEXTURE ||
4551 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4552
4553 switch (pname)
4554 {
4555 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4556 if (attachmentObject->type() != GL_RENDERBUFFER &&
4557 attachmentObject->type() != GL_TEXTURE)
4558 {
4559 context->handleError(Error(GL_INVALID_ENUM));
4560 return false;
4561 }
4562 break;
4563
4564 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4565 if (attachmentObject->type() != GL_TEXTURE)
4566 {
4567 context->handleError(Error(GL_INVALID_ENUM));
4568 return false;
4569 }
4570 break;
4571
4572 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4573 if (attachmentObject->type() != GL_TEXTURE)
4574 {
4575 context->handleError(Error(GL_INVALID_ENUM));
4576 return false;
4577 }
4578 break;
4579
4580 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4581 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4582 {
4583 context->handleError(Error(GL_INVALID_OPERATION));
4584 return false;
4585 }
4586 break;
4587
4588 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4589 if (attachmentObject->type() != GL_TEXTURE)
4590 {
4591 context->handleError(Error(GL_INVALID_ENUM));
4592 return false;
4593 }
4594 break;
4595
4596 default:
4597 break;
4598 }
4599 }
4600 else
4601 {
4602 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4603 // is NONE, then querying any other pname will generate INVALID_ENUM.
4604
4605 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4606 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4607 // INVALID_OPERATION for all other pnames
4608
4609 switch (pname)
4610 {
4611 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4612 break;
4613
4614 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4615 if (clientVersion < 3)
4616 {
4617 context->handleError(Error(GL_INVALID_ENUM));
4618 return false;
4619 }
4620 break;
4621
4622 default:
4623 if (clientVersion < 3)
4624 {
4625 context->handleError(Error(GL_INVALID_ENUM));
4626 return false;
4627 }
4628 else
4629 {
4630 context->handleError(Error(GL_INVALID_OPERATION));
4631 return false;
4632 }
4633 }
4634 }
4635
4636 return true;
4637}
4638
4639bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4640 GLenum target,
4641 GLenum attachment,
4642 GLenum pname,
4643 GLsizei bufSize,
4644 GLsizei *numParams)
4645{
4646 if (!ValidateRobustEntryPoint(context, bufSize))
4647 {
4648 return false;
4649 }
4650
4651 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4652 {
4653 return false;
4654 }
4655
4656 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4657 {
4658 return false;
4659 }
4660
4661 return true;
4662}
4663
4664bool ValidateGetBufferParameteriv(ValidationContext *context,
4665 GLenum target,
4666 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004667 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004668{
Geoff Langebebe1c2016-10-14 12:01:31 -04004669 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004670}
4671
4672bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4673 GLenum target,
4674 GLenum pname,
4675 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004676 GLsizei *length,
4677 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004678{
4679 if (!ValidateRobustEntryPoint(context, bufSize))
4680 {
4681 return false;
4682 }
4683
Geoff Langebebe1c2016-10-14 12:01:31 -04004684 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004685 {
4686 return false;
4687 }
4688
Geoff Langebebe1c2016-10-14 12:01:31 -04004689 if (!ValidateRobustBufferSize(context, bufSize, *length))
4690 {
4691 return false;
4692 }
4693
4694 return true;
4695}
4696
4697bool ValidateGetBufferParameteri64v(ValidationContext *context,
4698 GLenum target,
4699 GLenum pname,
4700 GLint64 *params)
4701{
4702 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4703}
4704
4705bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4706 GLenum target,
4707 GLenum pname,
4708 GLsizei bufSize,
4709 GLsizei *length,
4710 GLint64 *params)
4711{
4712 if (!ValidateRobustEntryPoint(context, bufSize))
4713 {
4714 return false;
4715 }
4716
4717 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4718 {
4719 return false;
4720 }
4721
4722 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004723 {
4724 return false;
4725 }
4726
4727 return true;
4728}
4729
4730bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4731{
4732 // Currently, all GetProgramiv queries return 1 parameter
4733 *numParams = 1;
4734
4735 Program *programObject = GetValidProgram(context, program);
4736 if (!programObject)
4737 {
4738 return false;
4739 }
4740
4741 switch (pname)
4742 {
4743 case GL_DELETE_STATUS:
4744 case GL_LINK_STATUS:
4745 case GL_VALIDATE_STATUS:
4746 case GL_INFO_LOG_LENGTH:
4747 case GL_ATTACHED_SHADERS:
4748 case GL_ACTIVE_ATTRIBUTES:
4749 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4750 case GL_ACTIVE_UNIFORMS:
4751 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4752 break;
4753
4754 case GL_PROGRAM_BINARY_LENGTH:
4755 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4756 {
4757 context->handleError(Error(GL_INVALID_ENUM,
4758 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4759 "GL_OES_get_program_binary or ES 3.0."));
4760 return false;
4761 }
4762 break;
4763
4764 case GL_ACTIVE_UNIFORM_BLOCKS:
4765 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4766 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4767 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4768 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4769 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4770 if (context->getClientMajorVersion() < 3)
4771 {
4772 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4773 return false;
4774 }
4775 break;
4776
4777 default:
4778 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4779 return false;
4780 }
4781
4782 return true;
4783}
4784
4785bool ValidateGetProgramivRobustANGLE(Context *context,
4786 GLuint program,
4787 GLenum pname,
4788 GLsizei bufSize,
4789 GLsizei *numParams)
4790{
4791 if (!ValidateRobustEntryPoint(context, bufSize))
4792 {
4793 return false;
4794 }
4795
4796 if (!ValidateGetProgramiv(context, program, pname, numParams))
4797 {
4798 return false;
4799 }
4800
4801 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4802 {
4803 return false;
4804 }
4805
4806 return true;
4807}
4808
Geoff Lang740d9022016-10-07 11:20:52 -04004809bool ValidateGetRenderbufferParameteriv(Context *context,
4810 GLenum target,
4811 GLenum pname,
4812 GLint *params)
4813{
4814 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4815}
4816
4817bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4818 GLenum target,
4819 GLenum pname,
4820 GLsizei bufSize,
4821 GLsizei *length,
4822 GLint *params)
4823{
4824 if (!ValidateRobustEntryPoint(context, bufSize))
4825 {
4826 return false;
4827 }
4828
4829 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4830 {
4831 return false;
4832 }
4833
4834 if (!ValidateRobustBufferSize(context, bufSize, *length))
4835 {
4836 return false;
4837 }
4838
4839 return true;
4840}
4841
Geoff Langd7d0ed32016-10-07 11:33:51 -04004842bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4843{
4844 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4845}
4846
4847bool ValidateGetShaderivRobustANGLE(Context *context,
4848 GLuint shader,
4849 GLenum pname,
4850 GLsizei bufSize,
4851 GLsizei *length,
4852 GLint *params)
4853{
4854 if (!ValidateRobustEntryPoint(context, bufSize))
4855 {
4856 return false;
4857 }
4858
4859 if (!ValidateGetShaderivBase(context, shader, pname, length))
4860 {
4861 return false;
4862 }
4863
4864 if (!ValidateRobustBufferSize(context, bufSize, *length))
4865 {
4866 return false;
4867 }
4868
4869 return true;
4870}
4871
Geoff Langc1984ed2016-10-07 12:41:00 -04004872bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4873{
4874 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4875}
4876
4877bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4878 GLenum target,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 GLsizei *length,
4882 GLfloat *params)
4883{
4884 if (!ValidateRobustEntryPoint(context, bufSize))
4885 {
4886 return false;
4887 }
4888
4889 if (!ValidateGetTexParameterBase(context, target, pname, length))
4890 {
4891 return false;
4892 }
4893
4894 if (!ValidateRobustBufferSize(context, bufSize, *length))
4895 {
4896 return false;
4897 }
4898
4899 return true;
4900}
4901
4902bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4903{
4904 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4905}
4906
4907bool ValidateGetTexParameterivRobustANGLE(Context *context,
4908 GLenum target,
4909 GLenum pname,
4910 GLsizei bufSize,
4911 GLsizei *length,
4912 GLint *params)
4913{
4914 if (!ValidateRobustEntryPoint(context, bufSize))
4915 {
4916 return false;
4917 }
4918
4919 if (!ValidateGetTexParameterBase(context, target, pname, length))
4920 {
4921 return false;
4922 }
4923
4924 if (!ValidateRobustBufferSize(context, bufSize, *length))
4925 {
4926 return false;
4927 }
4928
4929 return true;
4930}
4931
4932bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4933{
4934 return ValidateTexParameterBase(context, target, pname, -1, &param);
4935}
4936
4937bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4938{
4939 return ValidateTexParameterBase(context, target, pname, -1, params);
4940}
4941
4942bool ValidateTexParameterfvRobustANGLE(Context *context,
4943 GLenum target,
4944 GLenum pname,
4945 GLsizei bufSize,
4946 const GLfloat *params)
4947{
4948 if (!ValidateRobustEntryPoint(context, bufSize))
4949 {
4950 return false;
4951 }
4952
4953 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4954}
4955
4956bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4957{
4958 return ValidateTexParameterBase(context, target, pname, -1, &param);
4959}
4960
4961bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4962{
4963 return ValidateTexParameterBase(context, target, pname, -1, params);
4964}
4965
4966bool ValidateTexParameterivRobustANGLE(Context *context,
4967 GLenum target,
4968 GLenum pname,
4969 GLsizei bufSize,
4970 const GLint *params)
4971{
4972 if (!ValidateRobustEntryPoint(context, bufSize))
4973 {
4974 return false;
4975 }
4976
4977 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4978}
4979
4980bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4981{
4982 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4983}
4984
4985bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4986 GLuint sampler,
4987 GLenum pname,
4988 GLuint bufSize,
4989 GLsizei *length,
4990 GLfloat *params)
4991{
4992 if (!ValidateRobustEntryPoint(context, bufSize))
4993 {
4994 return false;
4995 }
4996
4997 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4998 {
4999 return false;
5000 }
5001
5002 if (!ValidateRobustBufferSize(context, bufSize, *length))
5003 {
5004 return false;
5005 }
5006
5007 return true;
5008}
5009
5010bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5011{
5012 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5013}
5014
5015bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5016 GLuint sampler,
5017 GLenum pname,
5018 GLuint bufSize,
5019 GLsizei *length,
5020 GLint *params)
5021{
5022 if (!ValidateRobustEntryPoint(context, bufSize))
5023 {
5024 return false;
5025 }
5026
5027 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5028 {
5029 return false;
5030 }
5031
5032 if (!ValidateRobustBufferSize(context, bufSize, *length))
5033 {
5034 return false;
5035 }
5036
5037 return true;
5038}
5039
5040bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5041{
5042 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5043}
5044
5045bool ValidateSamplerParameterfv(Context *context,
5046 GLuint sampler,
5047 GLenum pname,
5048 const GLfloat *params)
5049{
5050 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5051}
5052
5053bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5054 GLuint sampler,
5055 GLenum pname,
5056 GLsizei bufSize,
5057 const GLfloat *params)
5058{
5059 if (!ValidateRobustEntryPoint(context, bufSize))
5060 {
5061 return false;
5062 }
5063
5064 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5065}
5066
5067bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5068{
5069 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5070}
5071
5072bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5073{
5074 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5075}
5076
5077bool ValidateSamplerParameterivRobustANGLE(Context *context,
5078 GLuint sampler,
5079 GLenum pname,
5080 GLsizei bufSize,
5081 const GLint *params)
5082{
5083 if (!ValidateRobustEntryPoint(context, bufSize))
5084 {
5085 return false;
5086 }
5087
5088 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5089}
5090
Geoff Lang0b031062016-10-13 14:30:04 -04005091bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5092{
5093 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5094}
5095
5096bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5097 GLuint index,
5098 GLenum pname,
5099 GLsizei bufSize,
5100 GLsizei *length,
5101 GLfloat *params)
5102{
5103 if (!ValidateRobustEntryPoint(context, bufSize))
5104 {
5105 return false;
5106 }
5107
5108 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5109 {
5110 return false;
5111 }
5112
5113 if (!ValidateRobustBufferSize(context, bufSize, *length))
5114 {
5115 return false;
5116 }
5117
5118 return true;
5119}
5120
5121bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5122{
5123 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5124}
5125
5126bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5127 GLuint index,
5128 GLenum pname,
5129 GLsizei bufSize,
5130 GLsizei *length,
5131 GLint *params)
5132{
5133 if (!ValidateRobustEntryPoint(context, bufSize))
5134 {
5135 return false;
5136 }
5137
5138 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5139 {
5140 return false;
5141 }
5142
5143 if (!ValidateRobustBufferSize(context, bufSize, *length))
5144 {
5145 return false;
5146 }
5147
5148 return true;
5149}
5150
5151bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5152{
5153 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5154}
5155
5156bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5157 GLuint index,
5158 GLenum pname,
5159 GLsizei bufSize,
5160 GLsizei *length,
5161 void **pointer)
5162{
5163 if (!ValidateRobustEntryPoint(context, bufSize))
5164 {
5165 return false;
5166 }
5167
5168 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5169 {
5170 return false;
5171 }
5172
5173 if (!ValidateRobustBufferSize(context, bufSize, *length))
5174 {
5175 return false;
5176 }
5177
5178 return true;
5179}
5180
5181bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5182{
5183 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5184}
5185
5186bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5187 GLuint index,
5188 GLenum pname,
5189 GLsizei bufSize,
5190 GLsizei *length,
5191 GLint *params)
5192{
5193 if (!ValidateRobustEntryPoint(context, bufSize))
5194 {
5195 return false;
5196 }
5197
5198 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5199 {
5200 return false;
5201 }
5202
5203 if (!ValidateRobustBufferSize(context, bufSize, *length))
5204 {
5205 return false;
5206 }
5207
5208 return true;
5209}
5210
5211bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5212{
5213 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5214}
5215
5216bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5217 GLuint index,
5218 GLenum pname,
5219 GLsizei bufSize,
5220 GLsizei *length,
5221 GLuint *params)
5222{
5223 if (!ValidateRobustEntryPoint(context, bufSize))
5224 {
5225 return false;
5226 }
5227
5228 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5229 {
5230 return false;
5231 }
5232
5233 if (!ValidateRobustBufferSize(context, bufSize, *length))
5234 {
5235 return false;
5236 }
5237
5238 return true;
5239}
5240
Geoff Lang6899b872016-10-14 11:30:13 -04005241bool ValidateGetActiveUniformBlockiv(Context *context,
5242 GLuint program,
5243 GLuint uniformBlockIndex,
5244 GLenum pname,
5245 GLint *params)
5246{
5247 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5248}
5249
5250bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5251 GLuint program,
5252 GLuint uniformBlockIndex,
5253 GLenum pname,
5254 GLsizei bufSize,
5255 GLsizei *length,
5256 GLint *params)
5257{
5258 if (!ValidateRobustEntryPoint(context, bufSize))
5259 {
5260 return false;
5261 }
5262
5263 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5264 {
5265 return false;
5266 }
5267
5268 if (!ValidateRobustBufferSize(context, bufSize, *length))
5269 {
5270 return false;
5271 }
5272
5273 return true;
5274}
5275
Geoff Lang0a9661f2016-10-20 10:59:20 -07005276bool ValidateGetInternalFormativ(Context *context,
5277 GLenum target,
5278 GLenum internalformat,
5279 GLenum pname,
5280 GLsizei bufSize,
5281 GLint *params)
5282{
5283 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5284 nullptr);
5285}
5286
5287bool ValidateGetInternalFormativRobustANGLE(Context *context,
5288 GLenum target,
5289 GLenum internalformat,
5290 GLenum pname,
5291 GLsizei bufSize,
5292 GLsizei *length,
5293 GLint *params)
5294{
5295 if (!ValidateRobustEntryPoint(context, bufSize))
5296 {
5297 return false;
5298 }
5299
5300 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5301 {
5302 return false;
5303 }
5304
5305 if (!ValidateRobustBufferSize(context, bufSize, *length))
5306 {
5307 return false;
5308 }
5309
5310 return true;
5311}
5312
Jamie Madillc29968b2016-01-20 11:17:23 -05005313} // namespace gl