1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
9 #include "libANGLE/validationES3_autogen.h"
10
11 #include "anglebase/numerics/safe_conversions.h"
12 #include "common/mathutil.h"
13 #include "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/ErrorStrings.h"
16 #include "libANGLE/Framebuffer.h"
17 #include "libANGLE/FramebufferAttachment.h"
18 #include "libANGLE/Renderbuffer.h"
19 #include "libANGLE/Texture.h"
20 #include "libANGLE/VertexArray.h"
21 #include "libANGLE/formatutils.h"
22 #include "libANGLE/validationES.h"
23
24 using namespace angle;
25
26 namespace gl
27 {
28 using namespace err;
29
30 namespace
31 {
ValidateFramebufferTextureMultiviewBaseANGLE(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level,GLsizei numViews)32 bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context,
33 GLenum target,
34 GLenum attachment,
35 TextureID texture,
36 GLint level,
37 GLsizei numViews)
38 {
39 if (!(context->getExtensions().multiview || context->getExtensions().multiview2))
40 {
41 context->validationError(GL_INVALID_OPERATION, kMultiviewNotAvailable);
42 return false;
43 }
44
45 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
46 {
47 return false;
48 }
49
50 if (texture.value != 0 && numViews < 1)
51 {
52 context->validationError(GL_INVALID_VALUE, kMultiviewViewsTooSmall);
53 return false;
54 }
55
56 const Extensions &extensions = context->getExtensions();
57 if (static_cast<GLuint>(numViews) > extensions.maxViews)
58 {
59 context->validationError(GL_INVALID_VALUE, kMultiviewViewsTooLarge);
60 return false;
61 }
62
63 return true;
64 }
65
ValidateFramebufferTextureMultiviewLevelAndFormat(const Context * context,const Texture * texture,GLint level)66 bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context,
67 const Texture *texture,
68 GLint level)
69 {
70 TextureType type = texture->getType();
71 if (!ValidMipLevel(context, type, level))
72 {
73 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
74 return false;
75 }
76
77 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
78 if (format.info->compressed)
79 {
80 context->validationError(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
81 return false;
82 }
83 return true;
84 }
85
ValidateUniformES3(const Context * context,GLenum uniformType,UniformLocation location,GLint count)86 bool ValidateUniformES3(const Context *context,
87 GLenum uniformType,
88 UniformLocation location,
89 GLint count)
90 {
91 if (context->getClientMajorVersion() < 3)
92 {
93 context->validationError(GL_INVALID_OPERATION, kES3Required);
94 return false;
95 }
96
97 return ValidateUniform(context, uniformType, location, count);
98 }
99
ValidateUniformMatrixES3(const Context * context,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)100 bool ValidateUniformMatrixES3(const Context *context,
101 GLenum valueType,
102 UniformLocation location,
103 GLsizei count,
104 GLboolean transpose)
105 {
106 // Check for ES3 uniform entry points
107 if (context->getClientMajorVersion() < 3)
108 {
109 context->validationError(GL_INVALID_OPERATION, kES3Required);
110 return false;
111 }
112
113 return ValidateUniformMatrix(context, valueType, location, count, transpose);
114 }
115
ValidateGenOrDeleteES3(const Context * context,GLint n)116 bool ValidateGenOrDeleteES3(const Context *context, GLint n)
117 {
118 if (context->getClientMajorVersion() < 3)
119 {
120 context->validationError(GL_INVALID_OPERATION, kES3Required);
121 return false;
122 }
123 return ValidateGenOrDelete(context, n);
124 }
125
ValidateGenOrDeleteCountES3(const Context * context,GLint count)126 bool ValidateGenOrDeleteCountES3(const Context *context, GLint count)
127 {
128 if (context->getClientMajorVersion() < 3)
129 {
130 context->validationError(GL_INVALID_OPERATION, kES3Required);
131 return false;
132 }
133 if (count < 0)
134 {
135 context->validationError(GL_INVALID_VALUE, kNegativeCount);
136 return false;
137 }
138 return true;
139 }
140
ValidateCopyTexture3DCommon(const Context * context,const Texture * source,GLint sourceLevel,GLint srcInternalFormat,const Texture * dest,GLint destLevel,GLint internalFormat,TextureTarget destTarget)141 bool ValidateCopyTexture3DCommon(const Context *context,
142 const Texture *source,
143 GLint sourceLevel,
144 GLint srcInternalFormat,
145 const Texture *dest,
146 GLint destLevel,
147 GLint internalFormat,
148 TextureTarget destTarget)
149 {
150 if (context->getClientMajorVersion() < 3)
151 {
152 context->validationError(GL_INVALID_OPERATION, kES3Required);
153 return false;
154 }
155
156 if (!context->getExtensions().copyTexture3d)
157 {
158 context->validationError(GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable);
159 return false;
160 }
161
162 if (!ValidTexture3DTarget(context, source->getType()))
163 {
164 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
165 return false;
166 }
167
168 // Table 1.1 from the ANGLE_copy_texture_3d spec
169 switch (GetUnsizedFormat(srcInternalFormat))
170 {
171 case GL_ALPHA:
172 case GL_LUMINANCE:
173 case GL_LUMINANCE_ALPHA:
174 case GL_RED:
175 case GL_RED_INTEGER:
176 case GL_RG:
177 case GL_RG_INTEGER:
178 case GL_RGB:
179 case GL_RGB_INTEGER:
180 case GL_RGBA:
181 case GL_RGBA_INTEGER:
182 case GL_DEPTH_COMPONENT:
183 case GL_DEPTH_STENCIL:
184 break;
185 default:
186 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
187 return false;
188 }
189
190 if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
191 {
192 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
193 return false;
194 }
195
196 // Table 1.0 from the ANGLE_copy_texture_3d spec
197 switch (internalFormat)
198 {
199 case GL_RGB:
200 case GL_RGBA:
201 case GL_LUMINANCE:
202 case GL_LUMINANCE_ALPHA:
203 case GL_ALPHA:
204 case GL_R8:
205 case GL_R8_SNORM:
206 case GL_R16F:
207 case GL_R32F:
208 case GL_R8UI:
209 case GL_R8I:
210 case GL_R16UI:
211 case GL_R16I:
212 case GL_R32UI:
213 case GL_R32I:
214 case GL_RG:
215 case GL_RG8:
216 case GL_RG8_SNORM:
217 case GL_RG16F:
218 case GL_RG32F:
219 case GL_RG8UI:
220 case GL_RG8I:
221 case GL_RG16UI:
222 case GL_RG16I:
223 case GL_RG32UI:
224 case GL_RG32I:
225 case GL_RGB8:
226 case GL_SRGB8:
227 case GL_RGB565:
228 case GL_RGB8_SNORM:
229 case GL_R11F_G11F_B10F:
230 case GL_RGB9_E5:
231 case GL_RGB16F:
232 case GL_RGB32F:
233 case GL_RGB8UI:
234 case GL_RGB8I:
235 case GL_RGB16UI:
236 case GL_RGB16I:
237 case GL_RGB32UI:
238 case GL_RGB32I:
239 case GL_RGBA8:
240 case GL_SRGB8_ALPHA8:
241 case GL_RGBA8_SNORM:
242 case GL_RGB5_A1:
243 case GL_RGBA4:
244 case GL_RGB10_A2:
245 case GL_RGBA16F:
246 case GL_RGBA32F:
247 case GL_RGBA8UI:
248 case GL_RGBA8I:
249 case GL_RGB10_A2UI:
250 case GL_RGBA16UI:
251 case GL_RGBA16I:
252 case GL_RGBA32I:
253 case GL_RGBA32UI:
254 break;
255 default:
256 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
257 return false;
258 }
259
260 return true;
261 }
262 } // anonymous namespace
263
ValidateTexImageFormatCombination(const Context * context,TextureType target,GLenum internalFormat,GLenum format,GLenum type)264 static bool ValidateTexImageFormatCombination(const Context *context,
265 TextureType target,
266 GLenum internalFormat,
267 GLenum format,
268 GLenum type)
269 {
270 // Different validation if on desktop api
271 if (context->getClientType() == EGL_OPENGL_API)
272 {
273 // The type and format are valid if any supported internal format has that type and format
274 if (!ValidDesktopFormat(format))
275 {
276 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
277 return false;
278 }
279
280 if (!ValidDesktopType(type))
281 {
282 context->validationError(GL_INVALID_ENUM, kInvalidType);
283 return false;
284 }
285 }
286 else
287 {
288 // The type and format are valid if any supported internal format has that type and format
289 if (!ValidES3Format(format))
290 {
291 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
292 return false;
293 }
294
295 if (!ValidES3Type(type))
296 {
297 context->validationError(GL_INVALID_ENUM, kInvalidType);
298 return false;
299 }
300 }
301
302 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
303 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
304 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
305 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
306 if (!ValidES3InternalFormat(internalFormat))
307 {
308 context->validationError(GL_INVALID_VALUE, kInvalidInternalFormat);
309 return false;
310 }
311
312 // From the ES 3.0 spec section 3.8.3:
313 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
314 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
315 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
316 // INVALID_OPERATION error.
317 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
318 {
319 context->validationError(GL_INVALID_OPERATION, k3DDepthStencil);
320 return false;
321 }
322
323 if (context->getClientType() == EGL_OPENGL_API)
324 {
325 // Check if this is a valid format combination to load texture data
326 if (!ValidDesktopFormatCombination(format, type, internalFormat))
327 {
328 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
329 return false;
330 }
331 }
332 else
333 {
334 // Check if this is a valid format combination to load texture data
335 if (!ValidES3FormatCombination(format, type, internalFormat))
336 {
337 context->validationError(GL_INVALID_OPERATION, kInvalidFormatCombination);
338 return false;
339 }
340 }
341
342 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat, type);
343 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
344 {
345 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
346 return false;
347 }
348
349 return true;
350 }
351
ValidateES3CompressedFormatForTexture3D(const Context * context,GLenum format)352 static bool ValidateES3CompressedFormatForTexture3D(const Context *context, GLenum format)
353 {
354 if (IsETC2EACFormat(format))
355 {
356 // ES 3.1, Section 8.7, page 169.
357 context->validationError(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArray);
358 return false;
359 }
360
361 if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionASTCHDRKHR ||
362 context->getExtensions().textureCompressionSliced3dASTCKHR))
363 {
364 // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
365 context->validationError(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayASTC);
366 return false;
367 }
368
369 if (IsS3TCFormat(format))
370 {
371 // GL_EXT_texture_compression_s3tc
372 context->validationError(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayS3TC);
373 return false;
374 }
375
376 if (IsRGTCFormat(format))
377 {
378 // GL_EXT_texture_compression_rgtc
379 context->validationError(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayRGTC);
380 return false;
381 }
382 return true;
383 }
384
ValidateES3TexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)385 bool ValidateES3TexImageParametersBase(const Context *context,
386 TextureTarget target,
387 GLint level,
388 GLenum internalformat,
389 bool isCompressed,
390 bool isSubImage,
391 GLint xoffset,
392 GLint yoffset,
393 GLint zoffset,
394 GLsizei width,
395 GLsizei height,
396 GLsizei depth,
397 GLint border,
398 GLenum format,
399 GLenum type,
400 GLsizei imageSize,
401 const void *pixels)
402 {
403 TextureType texType = TextureTargetToType(target);
404
405 // Validate image size
406 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
407 {
408 // Error already processed.
409 return false;
410 }
411
412 // Verify zero border
413 if (border != 0)
414 {
415 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
416 return false;
417 }
418
419 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
420 {
421 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
422 return false;
423 }
424
425 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
426 std::numeric_limits<GLsizei>::max() - yoffset < height ||
427 std::numeric_limits<GLsizei>::max() - zoffset < depth)
428 {
429 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
430 return false;
431 }
432
433 const Caps &caps = context->getCaps();
434
435 switch (texType)
436 {
437 case TextureType::_2D:
438 case TextureType::External:
439 case TextureType::VideoImage:
440 if (width > (caps.max2DTextureSize >> level) ||
441 height > (caps.max2DTextureSize >> level))
442 {
443 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
444 return false;
445 }
446 break;
447
448 case TextureType::Rectangle:
449 ASSERT(level == 0);
450 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
451 {
452 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
453 return false;
454 }
455 if (isCompressed)
456 {
457 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
458 return false;
459 }
460 break;
461
462 case TextureType::CubeMap:
463 if (!isSubImage && width != height)
464 {
465 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
466 return false;
467 }
468
469 if (width > (caps.maxCubeMapTextureSize >> level))
470 {
471 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
472 return false;
473 }
474 break;
475
476 case TextureType::_3D:
477 if (width > (caps.max3DTextureSize >> level) ||
478 height > (caps.max3DTextureSize >> level) ||
479 depth > (caps.max3DTextureSize >> level))
480 {
481 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
482 return false;
483 }
484 break;
485
486 case TextureType::_2DArray:
487 if (width > (caps.max2DTextureSize >> level) ||
488 height > (caps.max2DTextureSize >> level) || depth > caps.maxArrayTextureLayers)
489 {
490 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
491 return false;
492 }
493 break;
494
495 default:
496 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
497 return false;
498 }
499
500 Texture *texture = context->getTextureByType(texType);
501 if (!texture)
502 {
503 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
504 return false;
505 }
506
507 if (texture->getImmutableFormat() && !isSubImage)
508 {
509 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
510 return false;
511 }
512
513 if (isCompressed && texType == TextureType::_3D)
514 {
515 GLenum compressedDataFormat = isSubImage ? format : internalformat;
516 if (!ValidateES3CompressedFormatForTexture3D(context, compressedDataFormat))
517 {
518 // Error already generated.
519 return false;
520 }
521 }
522
523 // Validate texture formats
524 GLenum actualInternalFormat =
525 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
526 if (isSubImage && actualInternalFormat == GL_NONE)
527 {
528 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevel);
529 return false;
530 }
531
532 const InternalFormat &actualFormatInfo = isSubImage
533 ? *texture->getFormat(target, level).info
534 : GetInternalFormatInfo(internalformat, type);
535 if (isCompressed)
536 {
537 if (!actualFormatInfo.compressed)
538 {
539 context->validationError(GL_INVALID_ENUM, kCompressedMismatch);
540 return false;
541 }
542
543 if (isSubImage)
544 {
545 if (!ValidCompressedSubImageSize(
546 context, actualFormatInfo.internalFormat, xoffset, yoffset, zoffset, width,
547 height, depth, texture->getWidth(target, level),
548 texture->getHeight(target, level), texture->getDepth(target, level)))
549 {
550 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
551 return false;
552 }
553
554 if (format != actualInternalFormat)
555 {
556 context->validationError(GL_INVALID_OPERATION, kMismatchedFormat);
557 return false;
558 }
559
560 // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
561 if (actualInternalFormat == GL_ETC1_RGB8_OES &&
562 !context->getExtensions().compressedETC1RGB8SubTexture)
563 {
564 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
565 return false;
566 }
567 }
568 else
569 {
570 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height,
571 depth))
572 {
573 context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
574 return false;
575 }
576 }
577
578 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
579 {
580 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
581 return false;
582 }
583
584 // Disallow 3D-only compressed formats from being set on 2D textures
585 if (actualFormatInfo.compressedBlockDepth > 1 && texType != TextureType::_2DArray)
586 {
587 context->validationError(GL_INVALID_OPERATION, kInvalidTextureTarget);
588 return false;
589 }
590 }
591 else
592 {
593 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
594 type))
595 {
596 return false;
597 }
598 }
599
600 // Validate sub image parameters
601 if (isSubImage)
602 {
603 if (isCompressed != actualFormatInfo.compressed)
604 {
605 context->validationError(GL_INVALID_OPERATION, kCompressedMismatch);
606 return false;
607 }
608
609 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
610 {
611 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
612 return false;
613 }
614
615 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
616 std::numeric_limits<GLsizei>::max() - yoffset < height ||
617 std::numeric_limits<GLsizei>::max() - zoffset < depth)
618 {
619 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
620 return false;
621 }
622
623 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
624 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
625 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
626 {
627 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
628 return false;
629 }
630
631 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
632 context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
633 {
634 context->validationError(GL_INVALID_VALUE, kPixelDataNull);
635 return false;
636 }
637 }
638
639 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
640 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
641 imageSize))
642 {
643 return false;
644 }
645
646 // Check for pixel unpack buffer related API errors
647 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
648 if (pixelUnpackBuffer != nullptr)
649 {
650 // ...data is not evenly divisible into the number of bytes needed to store in memory a
651 // datum
652 // indicated by type.
653 if (!isCompressed)
654 {
655 size_t offset = reinterpret_cast<size_t>(pixels);
656 size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
657
658 if ((offset % dataBytesPerPixel) != 0)
659 {
660 context->validationError(GL_INVALID_OPERATION, kDataTypeNotAligned);
661 return false;
662 }
663 }
664
665 // ...the buffer object's data store is currently mapped.
666 if (pixelUnpackBuffer->isMapped())
667 {
668 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
669 return false;
670 }
671 }
672
673 return true;
674 }
675
ValidateES3TexImage2DParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei imageSize,const void * pixels)676 bool ValidateES3TexImage2DParameters(const Context *context,
677 TextureTarget target,
678 GLint level,
679 GLenum internalformat,
680 bool isCompressed,
681 bool isSubImage,
682 GLint xoffset,
683 GLint yoffset,
684 GLint zoffset,
685 GLsizei width,
686 GLsizei height,
687 GLsizei depth,
688 GLint border,
689 GLenum format,
690 GLenum type,
691 GLsizei imageSize,
692 const void *pixels)
693 {
694 if (!ValidTexture2DDestinationTarget(context, target))
695 {
696 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
697 return false;
698 }
699
700 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
701 isSubImage, xoffset, yoffset, zoffset, width, height,
702 depth, border, format, type, imageSize, pixels);
703 }
704
ValidateES3TexImage3DParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isCompressed,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)705 bool ValidateES3TexImage3DParameters(const Context *context,
706 TextureTarget target,
707 GLint level,
708 GLenum internalformat,
709 bool isCompressed,
710 bool isSubImage,
711 GLint xoffset,
712 GLint yoffset,
713 GLint zoffset,
714 GLsizei width,
715 GLsizei height,
716 GLsizei depth,
717 GLint border,
718 GLenum format,
719 GLenum type,
720 GLsizei bufSize,
721 const void *pixels)
722 {
723 if (!ValidTexture3DDestinationTarget(context, target))
724 {
725 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
726 return false;
727 }
728
729 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
730 isSubImage, xoffset, yoffset, zoffset, width, height,
731 depth, border, format, type, bufSize, pixels);
732 }
733
734 struct EffectiveInternalFormatInfo
735 {
736 GLenum effectiveFormat;
737 GLenum destFormat;
738 GLuint minRedBits;
739 GLuint maxRedBits;
740 GLuint minGreenBits;
741 GLuint maxGreenBits;
742 GLuint minBlueBits;
743 GLuint maxBlueBits;
744 GLuint minAlphaBits;
745 GLuint maxAlphaBits;
746 };
747
QueryEffectiveFormatList(const InternalFormat & srcFormat,GLenum targetFormat,const EffectiveInternalFormatInfo * list,size_t size,GLenum * outEffectiveFormat)748 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
749 GLenum targetFormat,
750 const EffectiveInternalFormatInfo *list,
751 size_t size,
752 GLenum *outEffectiveFormat)
753 {
754 for (size_t curFormat = 0; curFormat < size; ++curFormat)
755 {
756 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
757 if ((formatInfo.destFormat == targetFormat) &&
758 (formatInfo.minRedBits <= srcFormat.redBits &&
759 formatInfo.maxRedBits >= srcFormat.redBits) &&
760 (formatInfo.minGreenBits <= srcFormat.greenBits &&
761 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
762 (formatInfo.minBlueBits <= srcFormat.blueBits &&
763 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
764 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
765 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
766 {
767 *outEffectiveFormat = formatInfo.effectiveFormat;
768 return true;
769 }
770 }
771
772 *outEffectiveFormat = GL_NONE;
773 return false;
774 }
775
GetSizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,GLenum * outEffectiveFormat)776 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
777 GLenum *outEffectiveFormat)
778 {
779 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
780 // Effective internal format coresponding to destination internal format and linear source
781 // buffer component sizes.
782 // | Source channel min/max sizes |
783 // Effective Internal Format | N/A | R | G | B | A |
784 // clang-format off
785 constexpr EffectiveInternalFormatInfo list[] = {
786 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
787 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
788 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
789 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
790 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
791 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
792 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
793 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
794 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
795 };
796 // clang-format on
797
798 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
799 }
800
GetUnsizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)801 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
802 const InternalFormat &destFormat,
803 GLenum *outEffectiveFormat)
804 {
805 constexpr GLuint umax = UINT_MAX;
806
807 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
808 // Effective internal format coresponding to destination internal format andlinear source buffer
809 // component sizes.
810 // | Source channel min/max sizes |
811 // Effective Internal Format | Dest Format | R | G | B | A |
812 // clang-format off
813 constexpr EffectiveInternalFormatInfo list[] = {
814 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
815 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
816 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
817 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
818 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
819 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
820 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
821 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
822 };
823 // clang-format on
824
825 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
826 outEffectiveFormat);
827 }
828
GetEffectiveInternalFormat(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)829 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
830 const InternalFormat &destFormat,
831 GLenum *outEffectiveFormat)
832 {
833 if (destFormat.sized)
834 {
835 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
836 }
837 else
838 {
839 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
840 }
841 }
842
EqualOrFirstZero(GLuint first,GLuint second)843 static bool EqualOrFirstZero(GLuint first, GLuint second)
844 {
845 return first == 0 || first == second;
846 }
847
IsValidES3CopyTexImageCombination(const InternalFormat & textureFormatInfo,const InternalFormat & framebufferFormatInfo,FramebufferID readBufferHandle)848 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
849 const InternalFormat &framebufferFormatInfo,
850 FramebufferID readBufferHandle)
851 {
852 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
853 {
854 return false;
855 }
856
857 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
858 // must both be signed, unsigned, or fixed point and both source and destinations
859 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
860 // conversion between fixed and floating point.
861
862 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
863 (framebufferFormatInfo.colorEncoding == GL_SRGB))
864 {
865 return false;
866 }
867
868 if (((textureFormatInfo.componentType == GL_INT) !=
869 (framebufferFormatInfo.componentType == GL_INT)) ||
870 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
871 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
872 {
873 return false;
874 }
875
876 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
877 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
878 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
879 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
880 {
881 return false;
882 }
883
884 // SNORM is not supported (e.g. is not in the tables of "effective internal format" that
885 // correspond to internal formats.
886 if (textureFormatInfo.componentType == GL_SIGNED_NORMALIZED)
887 {
888 return false;
889 }
890
891 // Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that
892 // the KHR dEQP tests enforce:
893 //
894 // Note that the above rules disallow matches where some components sizes are smaller and
895 // others are larger (such as RGB10_A2).
896 if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
897 {
898 return false;
899 }
900
901 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
902 // The effective internal format of the source buffer is determined with the following rules
903 // applied in order:
904 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
905 // format then the effective internal format is the source buffer's sized internal format.
906 // * If the source buffer is a texture that was created with an unsized base internal format,
907 // then the effective internal format is the source image array's effective internal
908 // format, as specified by table 3.12, which is determined from the <format> and <type>
909 // that were used when the source image array was specified by TexImage*.
910 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
911 // where Destination Internal Format matches internalformat and where the [source channel
912 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
913 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
914 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
915 const InternalFormat *sourceEffectiveFormat = nullptr;
916 if (readBufferHandle.value != 0)
917 {
918 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
919 // renderbuffer
920 if (framebufferFormatInfo.sized)
921 {
922 sourceEffectiveFormat = &framebufferFormatInfo;
923 }
924 else
925 {
926 // Renderbuffers cannot be created with an unsized internal format, so this must be an
927 // unsized-format texture. We can use the same table we use when creating textures to
928 // get its effective sized format.
929 sourceEffectiveFormat =
930 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
931 }
932 }
933 else
934 {
935 // The effective internal format must be derived from the source framebuffer's channel
936 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
937 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
938 {
939 GLenum effectiveFormat;
940 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
941 &effectiveFormat))
942 {
943 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
944 }
945 else
946 {
947 return false;
948 }
949 }
950 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
951 {
952 // SRGB buffers can only be copied to sized format destinations according to table 3.18
953 if (textureFormatInfo.sized &&
954 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
955 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
956 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
957 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
958 {
959 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
960 }
961 else
962 {
963 return false;
964 }
965 }
966 else
967 {
968 UNREACHABLE();
969 return false;
970 }
971 }
972
973 if (textureFormatInfo.sized)
974 {
975 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
976 // sized, component sizes of the source and destination formats must exactly match if the
977 // destination format exists.
978 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
979 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
980 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
981 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
982 {
983 return false;
984 }
985 }
986
987 return true; // A conversion function exists, and no rule in the specification has precluded
988 // conversion between these formats.
989 }
990
ValidateES3CopyTexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)991 bool ValidateES3CopyTexImageParametersBase(const Context *context,
992 TextureTarget target,
993 GLint level,
994 GLenum internalformat,
995 bool isSubImage,
996 GLint xoffset,
997 GLint yoffset,
998 GLint zoffset,
999 GLint x,
1000 GLint y,
1001 GLsizei width,
1002 GLsizei height,
1003 GLint border)
1004 {
1005 Format textureFormat = Format::Invalid();
1006 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1007 xoffset, yoffset, zoffset, x, y, width, height, border,
1008 &textureFormat))
1009 {
1010 return false;
1011 }
1012 ASSERT(textureFormat.valid() || !isSubImage);
1013
1014 const auto &state = context->getState();
1015 Framebuffer *framebuffer = state.getReadFramebuffer();
1016 FramebufferID readFramebufferID = framebuffer->id();
1017
1018 if (!ValidateFramebufferComplete(context, framebuffer))
1019 {
1020 return false;
1021 }
1022
1023 // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
1024 // resolved before copying
1025 if (!framebuffer->isDefault() &&
1026 !ValidateFramebufferNotMultisampled(context, framebuffer, true))
1027 {
1028 return false;
1029 }
1030
1031 const FramebufferAttachment *source = framebuffer->getReadColorAttachment();
1032
1033 // According to ES 3.x spec, if the internalformat of the texture
1034 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
1035 if (textureFormat.info->internalFormat == GL_RGB9_E5)
1036 {
1037 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
1038 return false;
1039 }
1040
1041 if (isSubImage)
1042 {
1043 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
1044 readFramebufferID))
1045 {
1046 context->validationError(GL_INVALID_OPERATION, kInvalidCopyCombination);
1047 return false;
1048 }
1049 }
1050 else
1051 {
1052 // Use format/type from the source FBO. (Might not be perfect for all cases?)
1053 const InternalFormat &framebufferFormat = *source->getFormat().info;
1054 const InternalFormat ©Format = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
1055 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
1056 {
1057 context->validationError(GL_INVALID_OPERATION, kInvalidCopyCombination);
1058 return false;
1059 }
1060 }
1061
1062 // If width or height is zero, it is a no-op. Return false without setting an error.
1063 return (width > 0 && height > 0);
1064 }
1065
ValidateES3CopyTexImage2DParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1066 bool ValidateES3CopyTexImage2DParameters(const Context *context,
1067 TextureTarget target,
1068 GLint level,
1069 GLenum internalformat,
1070 bool isSubImage,
1071 GLint xoffset,
1072 GLint yoffset,
1073 GLint zoffset,
1074 GLint x,
1075 GLint y,
1076 GLsizei width,
1077 GLsizei height,
1078 GLint border)
1079 {
1080 if (!ValidTexture2DDestinationTarget(context, target))
1081 {
1082 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1083 return false;
1084 }
1085
1086 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1087 xoffset, yoffset, zoffset, x, y, width, height,
1088 border);
1089 }
1090
ValidateES3CopyTexImage3DParameters(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1091 bool ValidateES3CopyTexImage3DParameters(const Context *context,
1092 TextureTarget target,
1093 GLint level,
1094 GLenum internalformat,
1095 bool isSubImage,
1096 GLint xoffset,
1097 GLint yoffset,
1098 GLint zoffset,
1099 GLint x,
1100 GLint y,
1101 GLsizei width,
1102 GLsizei height,
1103 GLint border)
1104 {
1105 if (!ValidTexture3DDestinationTarget(context, target))
1106 {
1107 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1108 return false;
1109 }
1110
1111 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1112 xoffset, yoffset, zoffset, x, y, width, height,
1113 border);
1114 }
1115
ValidateES3TexStorageParametersBase(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1116 bool ValidateES3TexStorageParametersBase(const Context *context,
1117 TextureType target,
1118 GLsizei levels,
1119 GLenum internalformat,
1120 GLsizei width,
1121 GLsizei height,
1122 GLsizei depth)
1123 {
1124 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1125 {
1126 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
1127 return false;
1128 }
1129
1130 GLsizei maxDim = std::max(width, height);
1131 if (target != TextureType::_2DArray)
1132 {
1133 maxDim = std::max(maxDim, depth);
1134 }
1135
1136 if (levels > log2(maxDim) + 1)
1137 {
1138 context->validationError(GL_INVALID_OPERATION, kInvalidMipLevels);
1139 return false;
1140 }
1141
1142 const Caps &caps = context->getCaps();
1143
1144 switch (target)
1145 {
1146 case TextureType::_2D:
1147 {
1148 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
1149 {
1150 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1151 return false;
1152 }
1153 }
1154 break;
1155
1156 case TextureType::Rectangle:
1157 {
1158 if (levels != 1)
1159 {
1160 context->validationError(GL_INVALID_VALUE, kInvalidMipLevels);
1161 return false;
1162 }
1163
1164 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
1165 {
1166 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1167 return false;
1168 }
1169 }
1170 break;
1171
1172 case TextureType::CubeMap:
1173 {
1174 if (width != height)
1175 {
1176 context->validationError(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
1177 return false;
1178 }
1179
1180 if (width > caps.maxCubeMapTextureSize)
1181 {
1182 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1183 return false;
1184 }
1185 }
1186 break;
1187
1188 case TextureType::_3D:
1189 {
1190 if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
1191 depth > caps.max3DTextureSize)
1192 {
1193 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1194 return false;
1195 }
1196 }
1197 break;
1198
1199 case TextureType::_2DArray:
1200 {
1201 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize ||
1202 depth > caps.maxArrayTextureLayers)
1203 {
1204 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
1205 return false;
1206 }
1207 }
1208 break;
1209
1210 default:
1211 UNREACHABLE();
1212 return false;
1213 }
1214
1215 Texture *texture = context->getTextureByType(target);
1216 if (!texture || texture->id().value == 0)
1217 {
1218 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
1219 return false;
1220 }
1221
1222 if (texture->getImmutableFormat())
1223 {
1224 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
1225 return false;
1226 }
1227
1228 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1229 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1230 {
1231 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1232 return false;
1233 }
1234
1235 if (!formatInfo.sized)
1236 {
1237 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
1238 return false;
1239 }
1240
1241 if (formatInfo.compressed && target == TextureType::Rectangle)
1242 {
1243 context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
1244 return false;
1245 }
1246
1247 if (formatInfo.compressed && target == TextureType::_3D)
1248 {
1249 if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat))
1250 {
1251 // Error already generated.
1252 return false;
1253 }
1254 }
1255
1256 return true;
1257 }
1258
ValidateES3TexStorage2DParameters(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1259 bool ValidateES3TexStorage2DParameters(const Context *context,
1260 TextureType target,
1261 GLsizei levels,
1262 GLenum internalformat,
1263 GLsizei width,
1264 GLsizei height,
1265 GLsizei depth)
1266 {
1267 if (!ValidTexture2DTarget(context, target))
1268 {
1269 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1270 return false;
1271 }
1272
1273 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1274 height, depth);
1275 }
1276
ValidateES3TexStorage3DParameters(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1277 bool ValidateES3TexStorage3DParameters(const Context *context,
1278 TextureType target,
1279 GLsizei levels,
1280 GLenum internalformat,
1281 GLsizei width,
1282 GLsizei height,
1283 GLsizei depth)
1284 {
1285 if (!ValidTexture3DTarget(context, target))
1286 {
1287 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1288 return false;
1289 }
1290
1291 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1292 height, depth);
1293 }
1294
ValidateBeginQuery(const Context * context,QueryType target,QueryID id)1295 bool ValidateBeginQuery(const Context *context, QueryType target, QueryID id)
1296 {
1297 if (context->getClientMajorVersion() < 3)
1298 {
1299 context->validationError(GL_INVALID_OPERATION, kES3Required);
1300 return false;
1301 }
1302
1303 return ValidateBeginQueryBase(context, target, id);
1304 }
1305
ValidateEndQuery(const Context * context,QueryType target)1306 bool ValidateEndQuery(const Context *context, QueryType target)
1307 {
1308 if (context->getClientMajorVersion() < 3)
1309 {
1310 context->validationError(GL_INVALID_OPERATION, kES3Required);
1311 return false;
1312 }
1313
1314 return ValidateEndQueryBase(context, target);
1315 }
1316
ValidateGetQueryiv(const Context * context,QueryType target,GLenum pname,const GLint * params)1317 bool ValidateGetQueryiv(const Context *context, QueryType target, GLenum pname, const GLint *params)
1318 {
1319 if (context->getClientMajorVersion() < 3)
1320 {
1321 context->validationError(GL_INVALID_OPERATION, kES3Required);
1322 return false;
1323 }
1324
1325 return ValidateGetQueryivBase(context, target, pname, nullptr);
1326 }
1327
ValidateGetQueryObjectuiv(const Context * context,QueryID id,GLenum pname,const GLuint * params)1328 bool ValidateGetQueryObjectuiv(const Context *context,
1329 QueryID id,
1330 GLenum pname,
1331 const GLuint *params)
1332 {
1333 if (context->getClientMajorVersion() < 3)
1334 {
1335 context->validationError(GL_INVALID_OPERATION, kES3Required);
1336 return false;
1337 }
1338
1339 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1340 }
1341
ValidateFramebufferTextureLayer(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint layer)1342 bool ValidateFramebufferTextureLayer(const Context *context,
1343 GLenum target,
1344 GLenum attachment,
1345 TextureID texture,
1346 GLint level,
1347 GLint layer)
1348 {
1349 if (context->getClientMajorVersion() < 3)
1350 {
1351 context->validationError(GL_INVALID_OPERATION, kES3Required);
1352 return false;
1353 }
1354
1355 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1356 {
1357 return false;
1358 }
1359
1360 const Caps &caps = context->getCaps();
1361 if (texture.value != 0)
1362 {
1363 if (layer < 0)
1364 {
1365 context->validationError(GL_INVALID_VALUE, kNegativeLayer);
1366 return false;
1367 }
1368
1369 Texture *tex = context->getTexture(texture);
1370 ASSERT(tex);
1371
1372 switch (tex->getType())
1373 {
1374 case TextureType::_2DArray:
1375 {
1376 if (level > log2(caps.max2DTextureSize))
1377 {
1378 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1379 return false;
1380 }
1381
1382 if (layer >= caps.maxArrayTextureLayers)
1383 {
1384 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1385 return false;
1386 }
1387 }
1388 break;
1389
1390 case TextureType::_3D:
1391 {
1392 if (level > log2(caps.max3DTextureSize))
1393 {
1394 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1395 return false;
1396 }
1397
1398 if (layer >= caps.max3DTextureSize)
1399 {
1400 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1401 return false;
1402 }
1403 }
1404 break;
1405
1406 case TextureType::_2DMultisampleArray:
1407 {
1408 if (level != 0)
1409 {
1410 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidMipLevel);
1411 return false;
1412 }
1413
1414 if (layer >= caps.maxArrayTextureLayers)
1415 {
1416 context->validationError(GL_INVALID_VALUE, kFramebufferTextureInvalidLayer);
1417 return false;
1418 }
1419 }
1420 break;
1421
1422 default:
1423 context->validationError(GL_INVALID_OPERATION,
1424 kFramebufferTextureLayerIncorrectTextureType);
1425 return false;
1426 }
1427
1428 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
1429 if (format.info->compressed)
1430 {
1431 context->validationError(GL_INVALID_OPERATION, kCompressedTexturesNotAttachable);
1432 return false;
1433 }
1434 }
1435
1436 return true;
1437 }
1438
ValidateInvalidateFramebuffer(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)1439 bool ValidateInvalidateFramebuffer(const Context *context,
1440 GLenum target,
1441 GLsizei numAttachments,
1442 const GLenum *attachments)
1443 {
1444 if (context->getClientMajorVersion() < 3)
1445 {
1446 context->validationError(GL_INVALID_OPERATION, kES3Required);
1447 return false;
1448 }
1449
1450 bool defaultFramebuffer = false;
1451
1452 switch (target)
1453 {
1454 case GL_DRAW_FRAMEBUFFER:
1455 case GL_FRAMEBUFFER:
1456 defaultFramebuffer = context->getState().getDrawFramebuffer()->isDefault();
1457 break;
1458 case GL_READ_FRAMEBUFFER:
1459 defaultFramebuffer = context->getState().getReadFramebuffer()->isDefault();
1460 break;
1461 default:
1462 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1463 return false;
1464 }
1465
1466 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1467 defaultFramebuffer);
1468 }
1469
ValidateInvalidateSubFramebuffer(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)1470 bool ValidateInvalidateSubFramebuffer(const Context *context,
1471 GLenum target,
1472 GLsizei numAttachments,
1473 const GLenum *attachments,
1474 GLint x,
1475 GLint y,
1476 GLsizei width,
1477 GLsizei height)
1478 {
1479 if (width < 0 || height < 0)
1480 {
1481 context->validationError(GL_INVALID_VALUE, kNegativeSize);
1482 return false;
1483 }
1484
1485 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1486 }
1487
ValidateClearBuffer(const Context * context)1488 bool ValidateClearBuffer(const Context *context)
1489 {
1490 if (context->getClientMajorVersion() < 3)
1491 {
1492 context->validationError(GL_INVALID_OPERATION, kES3Required);
1493 return false;
1494 }
1495
1496 if (!ValidateFramebufferComplete(context, context->getState().getDrawFramebuffer()))
1497 {
1498 return false;
1499 }
1500
1501 return true;
1502 }
1503
ValidateDrawRangeElements(const Context * context,PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,DrawElementsType type,const void * indices)1504 bool ValidateDrawRangeElements(const Context *context,
1505 PrimitiveMode mode,
1506 GLuint start,
1507 GLuint end,
1508 GLsizei count,
1509 DrawElementsType type,
1510 const void *indices)
1511 {
1512 if (context->getClientMajorVersion() < 3)
1513 {
1514 context->validationError(GL_INVALID_OPERATION, kES3Required);
1515 return false;
1516 }
1517
1518 if (end < start)
1519 {
1520 context->validationError(GL_INVALID_VALUE, kInvalidElementRange);
1521 return false;
1522 }
1523
1524 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
1525 {
1526 return false;
1527 }
1528
1529 // Skip range checks for no-op calls.
1530 if (count <= 0)
1531 {
1532 return true;
1533 }
1534
1535 return true;
1536 }
1537
ValidateGetUniformuiv(const Context * context,ShaderProgramID program,UniformLocation location,const GLuint * params)1538 bool ValidateGetUniformuiv(const Context *context,
1539 ShaderProgramID program,
1540 UniformLocation location,
1541 const GLuint *params)
1542 {
1543 if (context->getClientMajorVersion() < 3)
1544 {
1545 context->validationError(GL_INVALID_OPERATION, kES3Required);
1546 return false;
1547 }
1548
1549 return ValidateGetUniformBase(context, program, location);
1550 }
1551
ValidateReadBuffer(const Context * context,GLenum src)1552 bool ValidateReadBuffer(const Context *context, GLenum src)
1553 {
1554 if (context->getClientMajorVersion() < 3)
1555 {
1556 context->validationError(GL_INVALID_OPERATION, kES3Required);
1557 return false;
1558 }
1559
1560 const Framebuffer *readFBO = context->getState().getReadFramebuffer();
1561
1562 if (readFBO == nullptr)
1563 {
1564 context->validationError(GL_INVALID_OPERATION, kNoReadFramebuffer);
1565 return false;
1566 }
1567
1568 if (src == GL_NONE)
1569 {
1570 return true;
1571 }
1572
1573 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
1574 {
1575 context->validationError(GL_INVALID_ENUM, kInvalidReadBuffer);
1576 return false;
1577 }
1578
1579 if (readFBO->isDefault())
1580 {
1581 if (src != GL_BACK)
1582 {
1583 context->validationError(GL_INVALID_OPERATION, kInvalidDefaultReadBuffer);
1584 return false;
1585 }
1586 }
1587 else
1588 {
1589 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1590
1591 if (drawBuffer >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
1592 {
1593 context->validationError(GL_INVALID_OPERATION, kExceedsMaxDrawBuffers);
1594 return false;
1595 }
1596 }
1597
1598 return true;
1599 }
1600
ValidateCompressedTexImage3D(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)1601 bool ValidateCompressedTexImage3D(const Context *context,
1602 TextureTarget target,
1603 GLint level,
1604 GLenum internalformat,
1605 GLsizei width,
1606 GLsizei height,
1607 GLsizei depth,
1608 GLint border,
1609 GLsizei imageSize,
1610 const void *data)
1611 {
1612 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
1613 {
1614 context->validationError(GL_INVALID_OPERATION, kES3Required);
1615 return false;
1616 }
1617
1618 if (!ValidTextureTarget(context, TextureTargetToType(target)))
1619 {
1620 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1621 return false;
1622 }
1623
1624 // Validate image size
1625 if (!ValidImageSizeParameters(context, TextureTargetToType(target), level, width, height, depth,
1626 false))
1627 {
1628 // Error already generated.
1629 return false;
1630 }
1631
1632 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1633 if (!formatInfo.compressed)
1634 {
1635 context->validationError(GL_INVALID_ENUM, kInvalidCompressedFormat);
1636 return false;
1637 }
1638
1639 GLuint blockSize = 0;
1640 if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
1641 {
1642 context->validationError(GL_INVALID_VALUE, kIntegerOverflow);
1643 return false;
1644 }
1645
1646 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
1647 {
1648 context->validationError(GL_INVALID_VALUE, kInvalidCompressedImageSize);
1649 return false;
1650 }
1651
1652 // 3D texture target validation
1653 if (target != TextureTarget::_3D && target != TextureTarget::_2DArray)
1654 {
1655 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
1656 return false;
1657 }
1658
1659 // validateES3TexImageFormat sets the error code if there is an error
1660 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1661 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1662 data))
1663 {
1664 return false;
1665 }
1666
1667 return true;
1668 }
1669
ValidateCompressedTexImage3DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)1670 bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
1671 TextureTarget target,
1672 GLint level,
1673 GLenum internalformat,
1674 GLsizei width,
1675 GLsizei height,
1676 GLsizei depth,
1677 GLint border,
1678 GLsizei imageSize,
1679 GLsizei dataSize,
1680 const void *data)
1681 {
1682 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1683 {
1684 return false;
1685 }
1686
1687 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1688 depth, border, imageSize, data);
1689 }
1690
ValidateBindVertexArray(const Context * context,VertexArrayID array)1691 bool ValidateBindVertexArray(const Context *context, VertexArrayID array)
1692 {
1693 if (context->getClientMajorVersion() < 3)
1694 {
1695 context->validationError(GL_INVALID_OPERATION, kES3Required);
1696 return false;
1697 }
1698
1699 return ValidateBindVertexArrayBase(context, array);
1700 }
1701
ValidateIsVertexArray(const Context * context,VertexArrayID array)1702 bool ValidateIsVertexArray(const Context *context, VertexArrayID array)
1703 {
1704 if (context->getClientMajorVersion() < 3)
1705 {
1706 context->validationError(GL_INVALID_OPERATION, kES3Required);
1707 return false;
1708 }
1709
1710 return true;
1711 }
1712
ValidateBindBufferCommon(const Context * context,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)1713 static bool ValidateBindBufferCommon(const Context *context,
1714 BufferBinding target,
1715 GLuint index,
1716 BufferID buffer,
1717 GLintptr offset,
1718 GLsizeiptr size)
1719 {
1720 if (context->getClientMajorVersion() < 3)
1721 {
1722 context->validationError(GL_INVALID_OPERATION, kES3Required);
1723 return false;
1724 }
1725
1726 if (buffer.value != 0 && offset < 0)
1727 {
1728 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
1729 return false;
1730 }
1731
1732 if (!context->getState().isBindGeneratesResourceEnabled() &&
1733 !context->isBufferGenerated(buffer))
1734 {
1735 context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
1736 return false;
1737 }
1738
1739 const Caps &caps = context->getCaps();
1740 switch (target)
1741 {
1742 case BufferBinding::TransformFeedback:
1743 {
1744 if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
1745 {
1746 context->validationError(GL_INVALID_VALUE,
1747 kIndexExceedsTransformFeedbackBufferBindings);
1748 return false;
1749 }
1750 if (buffer.value != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1751 {
1752 context->validationError(GL_INVALID_VALUE, kOffsetAndSizeAlignment);
1753 return false;
1754 }
1755
1756 if (context->getState().isTransformFeedbackActive())
1757 {
1758 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackTargetActive);
1759 return false;
1760 }
1761 break;
1762 }
1763 case BufferBinding::Uniform:
1764 {
1765 if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
1766 {
1767 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
1768 return false;
1769 }
1770
1771 ASSERT(caps.uniformBufferOffsetAlignment);
1772 if (buffer.value != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1773 {
1774 context->validationError(GL_INVALID_VALUE, kUniformBufferOffsetAlignment);
1775 return false;
1776 }
1777 break;
1778 }
1779 case BufferBinding::AtomicCounter:
1780 {
1781 if (context->getClientVersion() < ES_3_1)
1782 {
1783 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
1784 return false;
1785 }
1786 if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
1787 {
1788 context->validationError(GL_INVALID_VALUE,
1789 kIndexExceedsMaxAtomicCounterBufferBindings);
1790 return false;
1791 }
1792 if (buffer.value != 0 && (offset % 4) != 0)
1793 {
1794 context->validationError(GL_INVALID_VALUE, kOffsetAlignment);
1795 return false;
1796 }
1797 break;
1798 }
1799 case BufferBinding::ShaderStorage:
1800 {
1801 if (context->getClientVersion() < ES_3_1)
1802 {
1803 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
1804 return false;
1805 }
1806 if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
1807 {
1808 context->validationError(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
1809 return false;
1810 }
1811 ASSERT(caps.shaderStorageBufferOffsetAlignment);
1812 if (buffer.value != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1813 {
1814 context->validationError(GL_INVALID_VALUE, kShaderStorageBufferOffsetAlignment);
1815 return false;
1816 }
1817 break;
1818 }
1819 default:
1820 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1821 return false;
1822 }
1823
1824 return true;
1825 }
1826
ValidateBindBufferBase(const Context * context,BufferBinding target,GLuint index,BufferID buffer)1827 bool ValidateBindBufferBase(const Context *context,
1828 BufferBinding target,
1829 GLuint index,
1830 BufferID buffer)
1831 {
1832 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1833 }
1834
ValidateBindBufferRange(const Context * context,BufferBinding target,GLuint index,BufferID buffer,GLintptr offset,GLsizeiptr size)1835 bool ValidateBindBufferRange(const Context *context,
1836 BufferBinding target,
1837 GLuint index,
1838 BufferID buffer,
1839 GLintptr offset,
1840 GLsizeiptr size)
1841 {
1842 if (buffer.value != 0 && size <= 0)
1843 {
1844 context->validationError(GL_INVALID_VALUE, kInvalidBindBufferSize);
1845 return false;
1846 }
1847 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1848 }
1849
ValidateProgramBinary(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)1850 bool ValidateProgramBinary(const Context *context,
1851 ShaderProgramID program,
1852 GLenum binaryFormat,
1853 const void *binary,
1854 GLint length)
1855 {
1856 if (context->getClientMajorVersion() < 3)
1857 {
1858 context->validationError(GL_INVALID_OPERATION, kES3Required);
1859 return false;
1860 }
1861
1862 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1863 }
1864
ValidateGetProgramBinary(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)1865 bool ValidateGetProgramBinary(const Context *context,
1866 ShaderProgramID program,
1867 GLsizei bufSize,
1868 const GLsizei *length,
1869 const GLenum *binaryFormat,
1870 const void *binary)
1871 {
1872 if (context->getClientMajorVersion() < 3)
1873 {
1874 context->validationError(GL_INVALID_OPERATION, kES3Required);
1875 return false;
1876 }
1877
1878 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1879 }
1880
ValidateProgramParameteri(const Context * context,ShaderProgramID program,GLenum pname,GLint value)1881 bool ValidateProgramParameteri(const Context *context,
1882 ShaderProgramID program,
1883 GLenum pname,
1884 GLint value)
1885 {
1886 if (context->getClientMajorVersion() < 3)
1887 {
1888 context->validationError(GL_INVALID_OPERATION, kES3Required);
1889 return false;
1890 }
1891
1892 if (GetValidProgram(context, program) == nullptr)
1893 {
1894 return false;
1895 }
1896
1897 switch (pname)
1898 {
1899 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
1900 if (value != GL_FALSE && value != GL_TRUE)
1901 {
1902 context->validationError(GL_INVALID_VALUE, kInvalidBooleanValue);
1903 return false;
1904 }
1905 break;
1906
1907 case GL_PROGRAM_SEPARABLE:
1908 if (context->getClientVersion() < ES_3_1)
1909 {
1910 context->validationError(GL_INVALID_ENUM, kES31Required);
1911 return false;
1912 }
1913
1914 if (value != GL_FALSE && value != GL_TRUE)
1915 {
1916 context->validationError(GL_INVALID_VALUE, kInvalidBooleanValue);
1917 return false;
1918 }
1919 break;
1920
1921 default:
1922 context->validationError(GL_INVALID_ENUM, kInvalidPname);
1923 return false;
1924 }
1925
1926 return true;
1927 }
1928
ValidateBlitFramebuffer(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1929 bool ValidateBlitFramebuffer(const Context *context,
1930 GLint srcX0,
1931 GLint srcY0,
1932 GLint srcX1,
1933 GLint srcY1,
1934 GLint dstX0,
1935 GLint dstY0,
1936 GLint dstX1,
1937 GLint dstY1,
1938 GLbitfield mask,
1939 GLenum filter)
1940 {
1941 if (context->getClientMajorVersion() < 3)
1942 {
1943 context->validationError(GL_INVALID_OPERATION, kES3Required);
1944 return false;
1945 }
1946
1947 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1948 dstX1, dstY1, mask, filter);
1949 }
1950
ValidateClearBufferiv(const Context * context,GLenum buffer,GLint drawbuffer,const GLint * value)1951 bool ValidateClearBufferiv(const Context *context,
1952 GLenum buffer,
1953 GLint drawbuffer,
1954 const GLint *value)
1955 {
1956 switch (buffer)
1957 {
1958 case GL_COLOR:
1959 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
1960 {
1961 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
1962 return false;
1963 }
1964 if (context->getExtensions().webglCompatibility)
1965 {
1966 constexpr GLenum validComponentTypes[] = {GL_INT};
1967 if (!ValidateWebGLFramebufferAttachmentClearType(
1968 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1969 {
1970 return false;
1971 }
1972 }
1973 break;
1974
1975 case GL_STENCIL:
1976 if (drawbuffer != 0)
1977 {
1978 context->validationError(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
1979 return false;
1980 }
1981 break;
1982
1983 default:
1984 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1985 return false;
1986 }
1987
1988 return ValidateClearBuffer(context);
1989 }
1990
ValidateClearBufferuiv(const Context * context,GLenum buffer,GLint drawbuffer,const GLuint * value)1991 bool ValidateClearBufferuiv(const Context *context,
1992 GLenum buffer,
1993 GLint drawbuffer,
1994 const GLuint *value)
1995 {
1996 switch (buffer)
1997 {
1998 case GL_COLOR:
1999 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2000 {
2001 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2002 return false;
2003 }
2004 if (context->getExtensions().webglCompatibility)
2005 {
2006 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
2007 if (!ValidateWebGLFramebufferAttachmentClearType(
2008 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
2009 {
2010 return false;
2011 }
2012 }
2013 break;
2014
2015 default:
2016 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2017 return false;
2018 }
2019
2020 return ValidateClearBuffer(context);
2021 }
2022
ValidateClearBufferfv(const Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * value)2023 bool ValidateClearBufferfv(const Context *context,
2024 GLenum buffer,
2025 GLint drawbuffer,
2026 const GLfloat *value)
2027 {
2028 switch (buffer)
2029 {
2030 case GL_COLOR:
2031 if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
2032 {
2033 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2034 return false;
2035 }
2036 if (context->getExtensions().webglCompatibility)
2037 {
2038 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
2039 GL_SIGNED_NORMALIZED};
2040 if (!ValidateWebGLFramebufferAttachmentClearType(
2041 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
2042 {
2043 return false;
2044 }
2045 }
2046 break;
2047
2048 case GL_DEPTH:
2049 if (drawbuffer != 0)
2050 {
2051 context->validationError(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2052 return false;
2053 }
2054 break;
2055
2056 default:
2057 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2058 return false;
2059 }
2060
2061 return ValidateClearBuffer(context);
2062 }
2063
ValidateClearBufferfi(const Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)2064 bool ValidateClearBufferfi(const Context *context,
2065 GLenum buffer,
2066 GLint drawbuffer,
2067 GLfloat depth,
2068 GLint stencil)
2069 {
2070 switch (buffer)
2071 {
2072 case GL_DEPTH_STENCIL:
2073 if (drawbuffer != 0)
2074 {
2075 context->validationError(GL_INVALID_VALUE, kInvalidDepthStencilDrawBuffer);
2076 return false;
2077 }
2078 break;
2079
2080 default:
2081 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2082 return false;
2083 }
2084
2085 return ValidateClearBuffer(context);
2086 }
2087
ValidateDrawBuffers(const Context * context,GLsizei n,const GLenum * bufs)2088 bool ValidateDrawBuffers(const Context *context, GLsizei n, const GLenum *bufs)
2089 {
2090 if (context->getClientMajorVersion() < 3)
2091 {
2092 context->validationError(GL_INVALID_OPERATION, kES3Required);
2093 return false;
2094 }
2095
2096 return ValidateDrawBuffersBase(context, n, bufs);
2097 }
2098
ValidateCopyTexSubImage3D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)2099 bool ValidateCopyTexSubImage3D(const Context *context,
2100 TextureTarget target,
2101 GLint level,
2102 GLint xoffset,
2103 GLint yoffset,
2104 GLint zoffset,
2105 GLint x,
2106 GLint y,
2107 GLsizei width,
2108 GLsizei height)
2109 {
2110 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2111 {
2112 context->validationError(GL_INVALID_OPERATION, kES3Required);
2113 return false;
2114 }
2115
2116 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
2117 yoffset, zoffset, x, y, width, height, 0);
2118 }
2119
ValidateCopyTexture3DANGLE(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint internalFormat,GLenum destType,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2120 bool ValidateCopyTexture3DANGLE(const Context *context,
2121 TextureID sourceId,
2122 GLint sourceLevel,
2123 TextureTarget destTarget,
2124 TextureID destId,
2125 GLint destLevel,
2126 GLint internalFormat,
2127 GLenum destType,
2128 GLboolean unpackFlipY,
2129 GLboolean unpackPremultiplyAlpha,
2130 GLboolean unpackUnmultiplyAlpha)
2131 {
2132 const Texture *source = context->getTexture(sourceId);
2133 if (source == nullptr)
2134 {
2135 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
2136 return false;
2137 }
2138
2139 TextureType sourceType = source->getType();
2140 ASSERT(sourceType != TextureType::CubeMap);
2141 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2142 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2143
2144 const Texture *dest = context->getTexture(destId);
2145 if (dest == nullptr)
2146 {
2147 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
2148 return false;
2149 }
2150
2151 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2152 sourceFormat.info->internalFormat, dest, destLevel,
2153 internalFormat, destTarget))
2154 {
2155 return false;
2156 }
2157
2158 if (!ValidMipLevel(context, source->getType(), sourceLevel))
2159 {
2160 context->validationError(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
2161 return false;
2162 }
2163
2164 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
2165 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
2166 if (sourceWidth == 0 || sourceHeight == 0)
2167 {
2168 context->validationError(GL_INVALID_OPERATION, kInvalidSourceTextureSize);
2169 return false;
2170 }
2171
2172 if (dest->getImmutableFormat())
2173 {
2174 context->validationError(GL_INVALID_OPERATION, kDestinationImmutable);
2175 return false;
2176 }
2177
2178 return true;
2179 }
2180
ValidateCopySubTexture3DANGLE(const Context * context,TextureID sourceId,GLint sourceLevel,TextureTarget destTarget,TextureID destId,GLint destLevel,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLint z,GLsizei width,GLsizei height,GLsizei depth,GLboolean unpackFlipY,GLboolean unpackPremultiplyAlpha,GLboolean unpackUnmultiplyAlpha)2181 bool ValidateCopySubTexture3DANGLE(const Context *context,
2182 TextureID sourceId,
2183 GLint sourceLevel,
2184 TextureTarget destTarget,
2185 TextureID destId,
2186 GLint destLevel,
2187 GLint xoffset,
2188 GLint yoffset,
2189 GLint zoffset,
2190 GLint x,
2191 GLint y,
2192 GLint z,
2193 GLsizei width,
2194 GLsizei height,
2195 GLsizei depth,
2196 GLboolean unpackFlipY,
2197 GLboolean unpackPremultiplyAlpha,
2198 GLboolean unpackUnmultiplyAlpha)
2199 {
2200 const Texture *source = context->getTexture(sourceId);
2201 if (source == nullptr)
2202 {
2203 context->validationError(GL_INVALID_VALUE, kInvalidSourceTexture);
2204 return false;
2205 }
2206
2207 TextureType sourceType = source->getType();
2208 ASSERT(sourceType != TextureType::CubeMap);
2209 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2210 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2211
2212 const Texture *dest = context->getTexture(destId);
2213 if (dest == nullptr)
2214 {
2215 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTexture);
2216 return false;
2217 }
2218
2219 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
2220
2221 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2222 sourceFormat.info->internalFormat, dest, destLevel,
2223 destFormat.internalFormat, destTarget))
2224 {
2225 return false;
2226 }
2227
2228 if (x < 0 || y < 0 || z < 0)
2229 {
2230 context->validationError(GL_INVALID_VALUE, kNegativeXYZ);
2231 return false;
2232 }
2233
2234 if (width < 0 || height < 0 || depth < 0)
2235 {
2236 context->validationError(GL_INVALID_VALUE, kNegativeHeightWidthDepth);
2237 return false;
2238 }
2239
2240 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
2241 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
2242 static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
2243 {
2244 context->validationError(GL_INVALID_VALUE, kSourceTextureTooSmall);
2245 return false;
2246 }
2247
2248 if (TextureTargetToType(destTarget) != dest->getType())
2249 {
2250 context->validationError(GL_INVALID_VALUE, kInvalidDestinationTextureType);
2251 return false;
2252 }
2253
2254 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2255 {
2256 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
2257 return false;
2258 }
2259
2260 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
2261 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
2262 static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
2263 {
2264 context->validationError(GL_INVALID_VALUE, kDestinationTextureTooSmall);
2265 return false;
2266 }
2267
2268 return true;
2269 }
2270
ValidateTexImage3D(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)2271 bool ValidateTexImage3D(const Context *context,
2272 TextureTarget target,
2273 GLint level,
2274 GLint internalformat,
2275 GLsizei width,
2276 GLsizei height,
2277 GLsizei depth,
2278 GLint border,
2279 GLenum format,
2280 GLenum type,
2281 const void *pixels)
2282 {
2283 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2284 {
2285 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2286 return false;
2287 }
2288
2289 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
2290 0, 0, width, height, depth, border, format, type, -1,
2291 pixels);
2292 }
2293
ValidateTexImage3DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2294 bool ValidateTexImage3DRobustANGLE(const Context *context,
2295 TextureTarget target,
2296 GLint level,
2297 GLint internalformat,
2298 GLsizei width,
2299 GLsizei height,
2300 GLsizei depth,
2301 GLint border,
2302 GLenum format,
2303 GLenum type,
2304 GLsizei bufSize,
2305 const void *pixels)
2306 {
2307 if (context->getClientMajorVersion() < 3)
2308 {
2309 context->validationError(GL_INVALID_OPERATION, kES3Required);
2310 return false;
2311 }
2312
2313 if (!ValidateRobustEntryPoint(context, bufSize))
2314 {
2315 return false;
2316 }
2317
2318 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
2319 0, 0, width, height, depth, border, format, type,
2320 bufSize, pixels);
2321 }
2322
ValidateTexSubImage3D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)2323 bool ValidateTexSubImage3D(const Context *context,
2324 TextureTarget target,
2325 GLint level,
2326 GLint xoffset,
2327 GLint yoffset,
2328 GLint zoffset,
2329 GLsizei width,
2330 GLsizei height,
2331 GLsizei depth,
2332 GLenum format,
2333 GLenum type,
2334 const void *pixels)
2335 {
2336 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2337 {
2338 context->validationError(GL_INVALID_OPERATION, kES3Required);
2339 return false;
2340 }
2341
2342 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2343 yoffset, zoffset, width, height, depth, 0, format, type,
2344 -1, pixels);
2345 }
2346
ValidateTexSubImage3DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2347 bool ValidateTexSubImage3DRobustANGLE(const Context *context,
2348 TextureTarget target,
2349 GLint level,
2350 GLint xoffset,
2351 GLint yoffset,
2352 GLint zoffset,
2353 GLsizei width,
2354 GLsizei height,
2355 GLsizei depth,
2356 GLenum format,
2357 GLenum type,
2358 GLsizei bufSize,
2359 const void *pixels)
2360 {
2361 if (context->getClientMajorVersion() < 3)
2362 {
2363 context->validationError(GL_INVALID_OPERATION, kES3Required);
2364 return false;
2365 }
2366
2367 if (!ValidateRobustEntryPoint(context, bufSize))
2368 {
2369 return false;
2370 }
2371
2372 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2373 yoffset, zoffset, width, height, depth, 0, format, type,
2374 bufSize, pixels);
2375 }
2376
ValidateCompressedTexSubImage3D(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)2377 bool ValidateCompressedTexSubImage3D(const Context *context,
2378 TextureTarget target,
2379 GLint level,
2380 GLint xoffset,
2381 GLint yoffset,
2382 GLint zoffset,
2383 GLsizei width,
2384 GLsizei height,
2385 GLsizei depth,
2386 GLenum format,
2387 GLsizei imageSize,
2388 const void *data)
2389 {
2390 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
2391 {
2392 context->validationError(GL_INVALID_OPERATION, kES3Required);
2393 return false;
2394 }
2395
2396 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2397 if (!formatInfo.compressed)
2398 {
2399 context->validationError(GL_INVALID_ENUM, kInvalidCompressedFormat);
2400 return false;
2401 }
2402
2403 GLuint blockSize = 0;
2404 if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
2405 {
2406 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
2407 return false;
2408 }
2409
2410 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
2411 {
2412 context->validationError(GL_INVALID_VALUE, kInvalidCompressedImageSize);
2413 return false;
2414 }
2415
2416 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2417 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2418 -1, data))
2419 {
2420 return false;
2421 }
2422
2423 if (!data)
2424 {
2425 context->validationError(GL_INVALID_VALUE, kPixelDataNull);
2426 return false;
2427 }
2428
2429 return true;
2430 }
2431
ValidateCompressedTexSubImage3DRobustANGLE(const Context * context,TextureTarget target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2432 bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
2433 TextureTarget target,
2434 GLint level,
2435 GLint xoffset,
2436 GLint yoffset,
2437 GLint zoffset,
2438 GLsizei width,
2439 GLsizei height,
2440 GLsizei depth,
2441 GLenum format,
2442 GLsizei imageSize,
2443 GLsizei dataSize,
2444 const void *data)
2445 {
2446 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2447 {
2448 return false;
2449 }
2450
2451 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2452 height, depth, format, imageSize, data);
2453 }
2454
ValidateGenQueries(const Context * context,GLint n,const QueryID * queries)2455 bool ValidateGenQueries(const Context *context, GLint n, const QueryID *queries)
2456 {
2457 return ValidateGenOrDeleteES3(context, n);
2458 }
2459
ValidateDeleteQueries(const Context * context,GLint n,const QueryID * queries)2460 bool ValidateDeleteQueries(const Context *context, GLint n, const QueryID *queries)
2461 {
2462 return ValidateGenOrDeleteES3(context, n);
2463 }
2464
ValidateGenSamplers(const Context * context,GLint count,const SamplerID * samplers)2465 bool ValidateGenSamplers(const Context *context, GLint count, const SamplerID *samplers)
2466 {
2467 return ValidateGenOrDeleteCountES3(context, count);
2468 }
2469
ValidateDeleteSamplers(const Context * context,GLint count,const SamplerID * samplers)2470 bool ValidateDeleteSamplers(const Context *context, GLint count, const SamplerID *samplers)
2471 {
2472 return ValidateGenOrDeleteCountES3(context, count);
2473 }
2474
ValidateGenTransformFeedbacks(const Context * context,GLint n,const TransformFeedbackID * ids)2475 bool ValidateGenTransformFeedbacks(const Context *context, GLint n, const TransformFeedbackID *ids)
2476 {
2477 return ValidateGenOrDeleteES3(context, n);
2478 }
2479
ValidateDeleteTransformFeedbacks(const Context * context,GLint n,const TransformFeedbackID * ids)2480 bool ValidateDeleteTransformFeedbacks(const Context *context,
2481 GLint n,
2482 const TransformFeedbackID *ids)
2483 {
2484 if (!ValidateGenOrDeleteES3(context, n))
2485 {
2486 return false;
2487 }
2488 for (GLint i = 0; i < n; ++i)
2489 {
2490 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2491 if (transformFeedback != nullptr && transformFeedback->isActive())
2492 {
2493 // ES 3.0.4 section 2.15.1 page 86
2494 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackActiveDelete);
2495 return false;
2496 }
2497 }
2498 return true;
2499 }
2500
ValidateGenVertexArrays(const Context * context,GLint n,const VertexArrayID * arrays)2501 bool ValidateGenVertexArrays(const Context *context, GLint n, const VertexArrayID *arrays)
2502 {
2503 return ValidateGenOrDeleteES3(context, n);
2504 }
2505
ValidateDeleteVertexArrays(const Context * context,GLint n,const VertexArrayID * arrays)2506 bool ValidateDeleteVertexArrays(const Context *context, GLint n, const VertexArrayID *arrays)
2507 {
2508 return ValidateGenOrDeleteES3(context, n);
2509 }
2510
ValidateBeginTransformFeedback(const Context * context,PrimitiveMode primitiveMode)2511 bool ValidateBeginTransformFeedback(const Context *context, PrimitiveMode primitiveMode)
2512 {
2513 if (context->getClientMajorVersion() < 3)
2514 {
2515 context->validationError(GL_INVALID_OPERATION, kES3Required);
2516 return false;
2517 }
2518 switch (primitiveMode)
2519 {
2520 case PrimitiveMode::Triangles:
2521 case PrimitiveMode::Lines:
2522 case PrimitiveMode::Points:
2523 break;
2524
2525 default:
2526 context->validationError(GL_INVALID_ENUM, kInvalidPrimitiveMode);
2527 return false;
2528 }
2529
2530 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
2531 ASSERT(transformFeedback != nullptr);
2532
2533 if (transformFeedback->isActive())
2534 {
2535 context->validationError(GL_INVALID_OPERATION, kTransfomFeedbackAlreadyActive);
2536 return false;
2537 }
2538
2539 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2540 {
2541 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2542 if (buffer.get())
2543 {
2544 if (buffer->isMapped())
2545 {
2546 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
2547 return false;
2548 }
2549 if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
2550 context->getExtensions().webglCompatibility) &&
2551 buffer->isDoubleBoundForTransformFeedback())
2552 {
2553 context->validationError(GL_INVALID_OPERATION,
2554 kTransformFeedbackBufferMultipleOutputs);
2555 return false;
2556 }
2557 }
2558 }
2559
2560 Program *program = context->getState().getLinkedProgram(context);
2561
2562 if (!program)
2563 {
2564 context->validationError(GL_INVALID_OPERATION, kProgramNotBound);
2565 return false;
2566 }
2567
2568 if (program->getTransformFeedbackVaryingCount() == 0)
2569 {
2570 context->validationError(GL_INVALID_OPERATION, kNoTransformFeedbackOutputVariables);
2571 return false;
2572 }
2573
2574 return true;
2575 }
2576
ValidateGetBufferPointerv(const Context * context,BufferBinding target,GLenum pname,void * const * params)2577 bool ValidateGetBufferPointerv(const Context *context,
2578 BufferBinding target,
2579 GLenum pname,
2580 void *const *params)
2581 {
2582 if (context->getClientMajorVersion() < 3)
2583 {
2584 context->validationError(GL_INVALID_OPERATION, kES3Required);
2585 return false;
2586 }
2587
2588 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2589 }
2590
ValidateGetBufferPointervRobustANGLE(const Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * params)2591 bool ValidateGetBufferPointervRobustANGLE(const Context *context,
2592 BufferBinding target,
2593 GLenum pname,
2594 GLsizei bufSize,
2595 const GLsizei *length,
2596 void *const *params)
2597 {
2598 if (!ValidateRobustEntryPoint(context, bufSize))
2599 {
2600 return false;
2601 }
2602
2603 GLsizei numParams = 0;
2604
2605 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBufferOES)
2606 {
2607 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2608 return false;
2609 }
2610
2611 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
2612 {
2613 return false;
2614 }
2615
2616 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2617 {
2618 return false;
2619 }
2620
2621 SetRobustLengthParam(length, numParams);
2622
2623 return true;
2624 }
2625
ValidateUnmapBuffer(const Context * context,BufferBinding target)2626 bool ValidateUnmapBuffer(const Context *context, BufferBinding target)
2627 {
2628 if (context->getClientMajorVersion() < 3)
2629 {
2630 context->validationError(GL_INVALID_OPERATION, kES3Required);
2631 return false;
2632 }
2633
2634 return ValidateUnmapBufferBase(context, target);
2635 }
2636
ValidateMapBufferRange(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)2637 bool ValidateMapBufferRange(const Context *context,
2638 BufferBinding target,
2639 GLintptr offset,
2640 GLsizeiptr length,
2641 GLbitfield access)
2642 {
2643 if (context->getClientMajorVersion() < 3)
2644 {
2645 context->validationError(GL_INVALID_OPERATION, kES3Required);
2646 return false;
2647 }
2648
2649 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2650 }
2651
ValidateFlushMappedBufferRange(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)2652 bool ValidateFlushMappedBufferRange(const Context *context,
2653 BufferBinding target,
2654 GLintptr offset,
2655 GLsizeiptr length)
2656 {
2657 if (context->getClientMajorVersion() < 3)
2658 {
2659 context->validationError(GL_INVALID_OPERATION, kES3Required);
2660 return false;
2661 }
2662
2663 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2664 }
2665
ValidateIndexedStateQuery(const Context * context,GLenum pname,GLuint index,GLsizei * length)2666 bool ValidateIndexedStateQuery(const Context *context, GLenum pname, GLuint index, GLsizei *length)
2667 {
2668 if (length)
2669 {
2670 *length = 0;
2671 }
2672
2673 GLenum nativeType;
2674 unsigned int numParams;
2675 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2676 {
2677 context->validationError(GL_INVALID_ENUM, kInvalidPname);
2678 return false;
2679 }
2680
2681 const Caps &caps = context->getCaps();
2682 switch (pname)
2683 {
2684 case GL_BLEND_SRC_RGB:
2685 case GL_BLEND_SRC_ALPHA:
2686 case GL_BLEND_DST_RGB:
2687 case GL_BLEND_DST_ALPHA:
2688 case GL_BLEND_EQUATION_RGB:
2689 case GL_BLEND_EQUATION_ALPHA:
2690 case GL_COLOR_WRITEMASK:
2691 if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
2692 {
2693 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
2694 return false;
2695 }
2696 break;
2697 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2698 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2699 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2700 if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
2701 {
2702 context->validationError(GL_INVALID_VALUE,
2703 kIndexExceedsMaxTransformFeedbackAttribs);
2704 return false;
2705 }
2706 break;
2707
2708 case GL_UNIFORM_BUFFER_START:
2709 case GL_UNIFORM_BUFFER_SIZE:
2710 case GL_UNIFORM_BUFFER_BINDING:
2711 if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
2712 {
2713 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
2714 return false;
2715 }
2716 break;
2717
2718 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2719 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2720 if (index >= 3u)
2721 {
2722 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxWorkgroupDimensions);
2723 return false;
2724 }
2725 break;
2726
2727 case GL_ATOMIC_COUNTER_BUFFER_START:
2728 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2729 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2730 if (context->getClientVersion() < ES_3_1)
2731 {
2732 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
2733 return false;
2734 }
2735 if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
2736 {
2737 context->validationError(GL_INVALID_VALUE,
2738 kIndexExceedsMaxAtomicCounterBufferBindings);
2739 return false;
2740 }
2741 break;
2742
2743 case GL_SHADER_STORAGE_BUFFER_START:
2744 case GL_SHADER_STORAGE_BUFFER_SIZE:
2745 case GL_SHADER_STORAGE_BUFFER_BINDING:
2746 if (context->getClientVersion() < ES_3_1)
2747 {
2748 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
2749 return false;
2750 }
2751 if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
2752 {
2753 context->validationError(GL_INVALID_VALUE, kExceedsMaxShaderStorageBufferBindings);
2754 return false;
2755 }
2756 break;
2757
2758 case GL_VERTEX_BINDING_BUFFER:
2759 case GL_VERTEX_BINDING_DIVISOR:
2760 case GL_VERTEX_BINDING_OFFSET:
2761 case GL_VERTEX_BINDING_STRIDE:
2762 if (context->getClientVersion() < ES_3_1)
2763 {
2764 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
2765 return false;
2766 }
2767 if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
2768 {
2769 context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
2770 return false;
2771 }
2772 break;
2773 case GL_SAMPLE_MASK_VALUE:
2774 if (context->getClientVersion() < ES_3_1)
2775 {
2776 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
2777 return false;
2778 }
2779 if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
2780 {
2781 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
2782 return false;
2783 }
2784 break;
2785 case GL_IMAGE_BINDING_NAME:
2786 case GL_IMAGE_BINDING_LEVEL:
2787 case GL_IMAGE_BINDING_LAYERED:
2788 case GL_IMAGE_BINDING_LAYER:
2789 case GL_IMAGE_BINDING_ACCESS:
2790 case GL_IMAGE_BINDING_FORMAT:
2791 if (context->getClientVersion() < ES_3_1)
2792 {
2793 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
2794 return false;
2795 }
2796 if (index >= static_cast<GLuint>(caps.maxImageUnits))
2797 {
2798 context->validationError(GL_INVALID_VALUE, kExceedsMaxImageUnits);
2799 return false;
2800 }
2801 break;
2802 default:
2803 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2804 return false;
2805 }
2806
2807 if (length)
2808 {
2809 *length = 1;
2810 }
2811
2812 return true;
2813 }
2814
ValidateGetIntegeri_v(const Context * context,GLenum target,GLuint index,const GLint * data)2815 bool ValidateGetIntegeri_v(const Context *context, GLenum target, GLuint index, const GLint *data)
2816 {
2817 if (context->getClientVersion() < ES_3_0)
2818 {
2819 context->validationError(GL_INVALID_OPERATION, kES3Required);
2820 return false;
2821 }
2822 return ValidateIndexedStateQuery(context, target, index, nullptr);
2823 }
2824
ValidateGetIntegeri_vRobustANGLE(const Context * context,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint * data)2825 bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
2826 GLenum target,
2827 GLuint index,
2828 GLsizei bufSize,
2829 const GLsizei *length,
2830 const GLint *data)
2831 {
2832 if (context->getClientVersion() < ES_3_0)
2833 {
2834 context->validationError(GL_INVALID_OPERATION, kES3Required);
2835 return false;
2836 }
2837
2838 if (!ValidateRobustEntryPoint(context, bufSize))
2839 {
2840 return false;
2841 }
2842
2843 GLsizei numParams = 0;
2844
2845 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
2846 {
2847 return false;
2848 }
2849
2850 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2851 {
2852 return false;
2853 }
2854
2855 SetRobustLengthParam(length, numParams);
2856
2857 return true;
2858 }
2859
ValidateGetInteger64i_v(const Context * context,GLenum target,GLuint index,const GLint64 * data)2860 bool ValidateGetInteger64i_v(const Context *context,
2861 GLenum target,
2862 GLuint index,
2863 const GLint64 *data)
2864 {
2865 if (context->getClientVersion() < ES_3_0)
2866 {
2867 context->validationError(GL_INVALID_OPERATION, kES3Required);
2868 return false;
2869 }
2870 return ValidateIndexedStateQuery(context, target, index, nullptr);
2871 }
2872
ValidateGetInteger64i_vRobustANGLE(const Context * context,GLenum target,GLuint index,GLsizei bufSize,const GLsizei * length,const GLint64 * data)2873 bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
2874 GLenum target,
2875 GLuint index,
2876 GLsizei bufSize,
2877 const GLsizei *length,
2878 const GLint64 *data)
2879 {
2880 if (context->getClientVersion() < ES_3_0)
2881 {
2882 context->validationError(GL_INVALID_OPERATION, kES3Required);
2883 return false;
2884 }
2885
2886 if (!ValidateRobustEntryPoint(context, bufSize))
2887 {
2888 return false;
2889 }
2890
2891 GLsizei numParams = 0;
2892
2893 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
2894 {
2895 return false;
2896 }
2897
2898 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2899 {
2900 return false;
2901 }
2902
2903 SetRobustLengthParam(length, numParams);
2904
2905 return true;
2906 }
2907
ValidateCopyBufferSubData(const Context * context,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)2908 bool ValidateCopyBufferSubData(const Context *context,
2909 BufferBinding readTarget,
2910 BufferBinding writeTarget,
2911 GLintptr readOffset,
2912 GLintptr writeOffset,
2913 GLsizeiptr size)
2914 {
2915 if (context->getClientMajorVersion() < 3)
2916 {
2917 context->validationError(GL_INVALID_OPERATION, kES3Required);
2918 return false;
2919 }
2920
2921 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
2922 {
2923 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
2924 return false;
2925 }
2926
2927 Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
2928 Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
2929
2930 if (!readBuffer || !writeBuffer)
2931 {
2932 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
2933 return false;
2934 }
2935
2936 // Verify that readBuffer and writeBuffer are not currently mapped
2937 if (readBuffer->isMapped() || writeBuffer->isMapped())
2938 {
2939 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
2940 return false;
2941 }
2942
2943 if (context->getExtensions().webglCompatibility &&
2944 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2945 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2946 {
2947 context->validationError(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
2948 return false;
2949 }
2950
2951 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2952 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2953 CheckedNumeric<GLintptr> checkedSize(size);
2954
2955 auto checkedReadSum = checkedReadOffset + checkedSize;
2956 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2957
2958 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2959 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2960 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
2961 {
2962 context->validationError(GL_INVALID_VALUE, kIntegerOverflow);
2963 return false;
2964 }
2965
2966 if (readOffset < 0 || writeOffset < 0)
2967 {
2968 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
2969 return false;
2970 }
2971
2972 if (size < 0)
2973 {
2974 context->validationError(GL_INVALID_VALUE, kNegativeSize);
2975 return false;
2976 }
2977
2978 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2979 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2980 {
2981 context->validationError(GL_INVALID_VALUE, kBufferOffsetOverflow);
2982 return false;
2983 }
2984
2985 if (readBuffer == writeBuffer)
2986 {
2987 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2988 if (!checkedOffsetDiff.IsValid())
2989 {
2990 // This shold not be possible.
2991 UNREACHABLE();
2992 context->validationError(GL_INVALID_VALUE, kIntegerOverflow);
2993 return false;
2994 }
2995
2996 if (checkedOffsetDiff.ValueOrDie() < size)
2997 {
2998 context->validationError(GL_INVALID_VALUE, kCopyAlias);
2999 return false;
3000 }
3001 }
3002
3003 return true;
3004 }
3005
ValidateGetStringi(const Context * context,GLenum name,GLuint index)3006 bool ValidateGetStringi(const Context *context, GLenum name, GLuint index)
3007 {
3008 if (context->getClientMajorVersion() < 3)
3009 {
3010 context->validationError(GL_INVALID_OPERATION, kES3Required);
3011 return false;
3012 }
3013
3014 switch (name)
3015 {
3016 case GL_EXTENSIONS:
3017 if (index >= context->getExtensionStringCount())
3018 {
3019 context->validationError(GL_INVALID_VALUE, kExceedsNumExtensions);
3020 return false;
3021 }
3022 break;
3023
3024 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
3025 if (!context->getExtensions().requestExtension)
3026 {
3027 context->validationError(GL_INVALID_ENUM, kInvalidName);
3028 return false;
3029 }
3030 if (index >= context->getRequestableExtensionStringCount())
3031 {
3032 context->validationError(GL_INVALID_VALUE, kExceedsNumRequestableExtensions);
3033 return false;
3034 }
3035 break;
3036
3037 default:
3038 context->validationError(GL_INVALID_ENUM, kInvalidName);
3039 return false;
3040 }
3041
3042 return true;
3043 }
3044
ValidateRenderbufferStorageMultisample(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)3045 bool ValidateRenderbufferStorageMultisample(const Context *context,
3046 GLenum target,
3047 GLsizei samples,
3048 GLenum internalformat,
3049 GLsizei width,
3050 GLsizei height)
3051 {
3052 if (context->getClientMajorVersion() < 3)
3053 {
3054 context->validationError(GL_INVALID_OPERATION, kES3Required);
3055 return false;
3056 }
3057
3058 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
3059 height))
3060 {
3061 return false;
3062 }
3063
3064 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
3065 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
3066 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
3067 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
3068 if (formatInfo.isInt())
3069 {
3070 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
3071 samples > context->getCaps().maxIntegerSamples)
3072 {
3073 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
3074 return false;
3075 }
3076 }
3077
3078 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
3079 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
3080 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
3081 {
3082 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
3083 return false;
3084 }
3085
3086 return true;
3087 }
3088
ValidateVertexAttribIPointer(const Context * context,GLuint index,GLint size,VertexAttribType type,GLsizei stride,const void * pointer)3089 bool ValidateVertexAttribIPointer(const Context *context,
3090 GLuint index,
3091 GLint size,
3092 VertexAttribType type,
3093 GLsizei stride,
3094 const void *pointer)
3095 {
3096 if (context->getClientMajorVersion() < 3)
3097 {
3098 context->validationError(GL_INVALID_OPERATION, kES3Required);
3099 return false;
3100 }
3101
3102 if (!ValidateIntegerVertexFormat(context, index, size, type))
3103 {
3104 return false;
3105 }
3106
3107 if (stride < 0)
3108 {
3109 context->validationError(GL_INVALID_VALUE, kNegativeStride);
3110 return false;
3111 }
3112
3113 const Caps &caps = context->getCaps();
3114 if (context->getClientVersion() >= ES_3_1)
3115 {
3116 if (stride > caps.maxVertexAttribStride)
3117 {
3118 context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
3119 return false;
3120 }
3121
3122 // [OpenGL ES 3.1] Section 10.3.1 page 245:
3123 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3124 // validation should be inherited.
3125 if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
3126 {
3127 context->validationError(GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
3128 return false;
3129 }
3130 }
3131
3132 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3133 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3134 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3135 // and the pointer argument is not NULL.
3136 if (context->getState().getVertexArrayId().value != 0 &&
3137 context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
3138 {
3139 context->validationError(GL_INVALID_OPERATION, kClientDataInVertexArray);
3140 return false;
3141 }
3142
3143 if (context->getExtensions().webglCompatibility)
3144 {
3145 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
3146 {
3147 return false;
3148 }
3149 }
3150
3151 return true;
3152 }
3153
ValidateGetSynciv(const Context * context,GLsync sync,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * values)3154 bool ValidateGetSynciv(const Context *context,
3155 GLsync sync,
3156 GLenum pname,
3157 GLsizei bufSize,
3158 const GLsizei *length,
3159 const GLint *values)
3160 {
3161 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
3162 {
3163 context->validationError(GL_INVALID_OPERATION, kES3Required);
3164 return false;
3165 }
3166
3167 if (bufSize < 0)
3168 {
3169 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
3170 return false;
3171 }
3172
3173 if (context->isContextLost())
3174 {
3175 context->validationError(GL_CONTEXT_LOST, kContextLost);
3176
3177 if (pname == GL_SYNC_STATUS)
3178 {
3179 // Generate an error but still return true, the context still needs to return a
3180 // value in this case.
3181 return true;
3182 }
3183 else
3184 {
3185 return false;
3186 }
3187 }
3188
3189 Sync *syncObject = context->getSync(sync);
3190 if (!syncObject)
3191 {
3192 context->validationError(GL_INVALID_VALUE, kSyncMissing);
3193 return false;
3194 }
3195
3196 switch (pname)
3197 {
3198 case GL_OBJECT_TYPE:
3199 case GL_SYNC_CONDITION:
3200 case GL_SYNC_FLAGS:
3201 case GL_SYNC_STATUS:
3202 break;
3203
3204 default:
3205 context->validationError(GL_INVALID_ENUM, kInvalidPname);
3206 return false;
3207 }
3208
3209 return true;
3210 }
3211
ValidateDrawElementsInstanced(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei instanceCount)3212 bool ValidateDrawElementsInstanced(const Context *context,
3213 PrimitiveMode mode,
3214 GLsizei count,
3215 DrawElementsType type,
3216 const void *indices,
3217 GLsizei instanceCount)
3218 {
3219 if (context->getClientMajorVersion() < 3)
3220 {
3221 context->validationError(GL_INVALID_OPERATION, kES3Required);
3222 return false;
3223 }
3224
3225 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, instanceCount);
3226 }
3227
ValidateMultiDrawArraysInstancedANGLE(const Context * context,PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)3228 bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
3229 PrimitiveMode mode,
3230 const GLint *firsts,
3231 const GLsizei *counts,
3232 const GLsizei *instanceCounts,
3233 GLsizei drawcount)
3234 {
3235 if (!context->getExtensions().multiDraw)
3236 {
3237 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3238 return false;
3239 }
3240 if (context->getClientMajorVersion() < 3)
3241 {
3242 if (!context->getExtensions().instancedArraysAny())
3243 {
3244 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3245 return false;
3246 }
3247 if (!ValidateDrawInstancedANGLE(context))
3248 {
3249 return false;
3250 }
3251 }
3252 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3253 {
3254 if (!ValidateDrawArraysInstancedBase(context, mode, firsts[drawID], counts[drawID],
3255 instanceCounts[drawID]))
3256 {
3257 return false;
3258 }
3259 }
3260 return true;
3261 }
3262
ValidateMultiDrawElementsInstancedANGLE(const Context * context,PrimitiveMode mode,const GLsizei * counts,DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)3263 bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
3264 PrimitiveMode mode,
3265 const GLsizei *counts,
3266 DrawElementsType type,
3267 const GLvoid *const *indices,
3268 const GLsizei *instanceCounts,
3269 GLsizei drawcount)
3270 {
3271 if (!context->getExtensions().multiDraw)
3272 {
3273 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3274 return false;
3275 }
3276 if (context->getClientMajorVersion() < 3)
3277 {
3278 if (!context->getExtensions().instancedArraysAny())
3279 {
3280 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3281 return false;
3282 }
3283 if (!ValidateDrawInstancedANGLE(context))
3284 {
3285 return false;
3286 }
3287 }
3288 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3289 {
3290 if (!ValidateDrawElementsInstancedBase(context, mode, counts[drawID], type, indices[drawID],
3291 instanceCounts[drawID]))
3292 {
3293 return false;
3294 }
3295 }
3296 return true;
3297 }
3298
ValidateDrawArraysInstancedBaseInstanceANGLE(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)3299 bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3300 PrimitiveMode mode,
3301 GLint first,
3302 GLsizei count,
3303 GLsizei instanceCount,
3304 GLuint baseInstance)
3305 {
3306 if (!context->getExtensions().baseVertexBaseInstance)
3307 {
3308 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3309 return false;
3310 }
3311 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, instanceCount))
3312 {
3313 return false;
3314 }
3315 return true;
3316 }
3317
ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const GLvoid * indices,GLsizei instanceCounts,GLint baseVertex,GLuint baseInstance)3318 bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3319 PrimitiveMode mode,
3320 GLsizei count,
3321 DrawElementsType type,
3322 const GLvoid *indices,
3323 GLsizei instanceCounts,
3324 GLint baseVertex,
3325 GLuint baseInstance)
3326 {
3327 if (!context->getExtensions().baseVertexBaseInstance)
3328 {
3329 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3330 return false;
3331 }
3332 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, instanceCounts))
3333 {
3334 return false;
3335 }
3336 return true;
3337 }
3338
ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context * context,PrimitiveMode modePacked,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)3339 bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
3340 PrimitiveMode modePacked,
3341 const GLint *firsts,
3342 const GLsizei *counts,
3343 const GLsizei *instanceCounts,
3344 const GLuint *baseInstances,
3345 GLsizei drawcount)
3346 {
3347 if (!context->getExtensions().multiDraw)
3348 {
3349 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3350 return false;
3351 }
3352 if (drawcount < 0)
3353 {
3354 return false;
3355 }
3356 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3357 {
3358 if (!ValidateDrawArraysInstancedBase(context, modePacked, firsts[drawID], counts[drawID],
3359 instanceCounts[drawID]))
3360 {
3361 return false;
3362 }
3363 }
3364 return true;
3365 }
3366
ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context * context,PrimitiveMode modePacked,const GLsizei * counts,DrawElementsType typePacked,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)3367 bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
3368 PrimitiveMode modePacked,
3369 const GLsizei *counts,
3370 DrawElementsType typePacked,
3371 const GLvoid *const *indices,
3372 const GLsizei *instanceCounts,
3373 const GLint *baseVertices,
3374 const GLuint *baseInstances,
3375 GLsizei drawcount)
3376 {
3377 if (!context->getExtensions().multiDraw)
3378 {
3379 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3380 return false;
3381 }
3382 if (drawcount < 0)
3383 {
3384 return false;
3385 }
3386 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3387 {
3388 if (!ValidateDrawElementsInstancedBase(context, modePacked, counts[drawID], typePacked,
3389 indices[drawID], instanceCounts[drawID]))
3390 {
3391 return false;
3392 }
3393 }
3394 return true;
3395 }
3396
ValidateFramebufferTextureMultiviewOVR(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level,GLint baseViewIndex,GLsizei numViews)3397 bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
3398 GLenum target,
3399 GLenum attachment,
3400 TextureID texture,
3401 GLint level,
3402 GLint baseViewIndex,
3403 GLsizei numViews)
3404 {
3405 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
3406 numViews))
3407 {
3408 return false;
3409 }
3410
3411 if (texture.value != 0)
3412 {
3413 if (baseViewIndex < 0)
3414 {
3415 context->validationError(GL_INVALID_VALUE, kNegativeBaseViewIndex);
3416 return false;
3417 }
3418
3419 Texture *tex = context->getTexture(texture);
3420 ASSERT(tex);
3421
3422 switch (tex->getType())
3423 {
3424 case TextureType::_2DArray:
3425 case TextureType::_2DMultisampleArray:
3426 {
3427 if (tex->getType() == TextureType::_2DMultisampleArray)
3428 {
3429 if (!context->getExtensions().multiviewMultisample)
3430 {
3431 context->validationError(GL_INVALID_OPERATION, kInvalidTextureType);
3432 return false;
3433 }
3434 }
3435
3436 const Caps &caps = context->getCaps();
3437 if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
3438 {
3439 context->validationError(GL_INVALID_VALUE, kViewsExceedMaxArrayLayers);
3440 return false;
3441 }
3442
3443 break;
3444 }
3445 default:
3446 context->validationError(GL_INVALID_OPERATION, kInvalidTextureType);
3447 return false;
3448 }
3449
3450 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
3451 {
3452 return false;
3453 }
3454 }
3455
3456 return true;
3457 }
3458
ValidateUniform1ui(const Context * context,UniformLocation location,GLuint v0)3459 bool ValidateUniform1ui(const Context *context, UniformLocation location, GLuint v0)
3460 {
3461 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
3462 }
3463
ValidateUniform2ui(const Context * context,UniformLocation location,GLuint v0,GLuint v1)3464 bool ValidateUniform2ui(const Context *context, UniformLocation location, GLuint v0, GLuint v1)
3465 {
3466 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
3467 }
3468
ValidateUniform3ui(const Context * context,UniformLocation location,GLuint v0,GLuint v1,GLuint v2)3469 bool ValidateUniform3ui(const Context *context,
3470 UniformLocation location,
3471 GLuint v0,
3472 GLuint v1,
3473 GLuint v2)
3474 {
3475 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
3476 }
3477
ValidateUniform4ui(const Context * context,UniformLocation location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)3478 bool ValidateUniform4ui(const Context *context,
3479 UniformLocation location,
3480 GLuint v0,
3481 GLuint v1,
3482 GLuint v2,
3483 GLuint v3)
3484 {
3485 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
3486 }
3487
ValidateUniform1uiv(const Context * context,UniformLocation location,GLsizei count,const GLuint * value)3488 bool ValidateUniform1uiv(const Context *context,
3489 UniformLocation location,
3490 GLsizei count,
3491 const GLuint *value)
3492 {
3493 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
3494 }
3495
ValidateUniform2uiv(const Context * context,UniformLocation location,GLsizei count,const GLuint * value)3496 bool ValidateUniform2uiv(const Context *context,
3497 UniformLocation location,
3498 GLsizei count,
3499 const GLuint *value)
3500 {
3501 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
3502 }
3503
ValidateUniform3uiv(const Context * context,UniformLocation location,GLsizei count,const GLuint * value)3504 bool ValidateUniform3uiv(const Context *context,
3505 UniformLocation location,
3506 GLsizei count,
3507 const GLuint *value)
3508 {
3509 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
3510 }
3511
ValidateUniform4uiv(const Context * context,UniformLocation location,GLsizei count,const GLuint * value)3512 bool ValidateUniform4uiv(const Context *context,
3513 UniformLocation location,
3514 GLsizei count,
3515 const GLuint *value)
3516 {
3517 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
3518 }
3519
ValidateIsQuery(const Context * context,QueryID id)3520 bool ValidateIsQuery(const Context *context, QueryID id)
3521 {
3522 if (context->getClientMajorVersion() < 3)
3523 {
3524 context->validationError(GL_INVALID_OPERATION, kES3Required);
3525 return false;
3526 }
3527
3528 return true;
3529 }
3530
ValidateUniformMatrix2x3fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3531 bool ValidateUniformMatrix2x3fv(const Context *context,
3532 UniformLocation location,
3533 GLsizei count,
3534 GLboolean transpose,
3535 const GLfloat *value)
3536 {
3537 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
3538 }
3539
ValidateUniformMatrix3x2fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3540 bool ValidateUniformMatrix3x2fv(const Context *context,
3541 UniformLocation location,
3542 GLsizei count,
3543 GLboolean transpose,
3544 const GLfloat *value)
3545 {
3546 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
3547 }
3548
ValidateUniformMatrix2x4fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3549 bool ValidateUniformMatrix2x4fv(const Context *context,
3550 UniformLocation location,
3551 GLsizei count,
3552 GLboolean transpose,
3553 const GLfloat *value)
3554 {
3555 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
3556 }
3557
ValidateUniformMatrix4x2fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3558 bool ValidateUniformMatrix4x2fv(const Context *context,
3559 UniformLocation location,
3560 GLsizei count,
3561 GLboolean transpose,
3562 const GLfloat *value)
3563 {
3564 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3565 }
3566
ValidateUniformMatrix3x4fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3567 bool ValidateUniformMatrix3x4fv(const Context *context,
3568 UniformLocation location,
3569 GLsizei count,
3570 GLboolean transpose,
3571 const GLfloat *value)
3572 {
3573 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3574 }
3575
ValidateUniformMatrix4x3fv(const Context * context,UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * value)3576 bool ValidateUniformMatrix4x3fv(const Context *context,
3577 UniformLocation location,
3578 GLsizei count,
3579 GLboolean transpose,
3580 const GLfloat *value)
3581 {
3582 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3583 }
3584
ValidateEndTransformFeedback(const Context * context)3585 bool ValidateEndTransformFeedback(const Context *context)
3586 {
3587 if (context->getClientMajorVersion() < 3)
3588 {
3589 context->validationError(GL_INVALID_OPERATION, kES3Required);
3590 return false;
3591 }
3592
3593 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3594 ASSERT(transformFeedback != nullptr);
3595
3596 if (!transformFeedback->isActive())
3597 {
3598 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
3599 return false;
3600 }
3601
3602 return true;
3603 }
3604
ValidateTransformFeedbackVaryings(const Context * context,ShaderProgramID program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)3605 bool ValidateTransformFeedbackVaryings(const Context *context,
3606 ShaderProgramID program,
3607 GLsizei count,
3608 const GLchar *const *varyings,
3609 GLenum bufferMode)
3610 {
3611 if (context->getClientMajorVersion() < 3)
3612 {
3613 context->validationError(GL_INVALID_OPERATION, kES3Required);
3614 return false;
3615 }
3616
3617 if (count < 0)
3618 {
3619 context->validationError(GL_INVALID_VALUE, kNegativeCount);
3620 return false;
3621 }
3622
3623 switch (bufferMode)
3624 {
3625 case GL_INTERLEAVED_ATTRIBS:
3626 break;
3627 case GL_SEPARATE_ATTRIBS:
3628 {
3629 const Caps &caps = context->getCaps();
3630 if (count > caps.maxTransformFeedbackSeparateAttributes)
3631 {
3632 context->validationError(GL_INVALID_VALUE, kInvalidTransformFeedbackAttribsCount);
3633 return false;
3634 }
3635 break;
3636 }
3637 default:
3638 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3639 return false;
3640 }
3641
3642 Program *programObject = GetValidProgram(context, program);
3643 if (!programObject)
3644 {
3645 return false;
3646 }
3647
3648 return true;
3649 }
3650
ValidateGetTransformFeedbackVarying(const Context * context,ShaderProgramID program,GLuint index,GLsizei bufSize,const GLsizei * length,const GLsizei * size,const GLenum * type,const GLchar * name)3651 bool ValidateGetTransformFeedbackVarying(const Context *context,
3652 ShaderProgramID program,
3653 GLuint index,
3654 GLsizei bufSize,
3655 const GLsizei *length,
3656 const GLsizei *size,
3657 const GLenum *type,
3658 const GLchar *name)
3659 {
3660 if (context->getClientMajorVersion() < 3)
3661 {
3662 context->validationError(GL_INVALID_OPERATION, kES3Required);
3663 return false;
3664 }
3665
3666 if (bufSize < 0)
3667 {
3668 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
3669 return false;
3670 }
3671
3672 Program *programObject = GetValidProgram(context, program);
3673 if (!programObject)
3674 {
3675 return false;
3676 }
3677
3678 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3679 {
3680 context->validationError(GL_INVALID_VALUE, kTransformFeedbackVaryingIndexOutOfRange);
3681 return false;
3682 }
3683
3684 return true;
3685 }
3686
ValidateBindTransformFeedback(const Context * context,GLenum target,TransformFeedbackID id)3687 bool ValidateBindTransformFeedback(const Context *context, GLenum target, TransformFeedbackID id)
3688 {
3689 if (context->getClientMajorVersion() < 3)
3690 {
3691 context->validationError(GL_INVALID_OPERATION, kES3Required);
3692 return false;
3693 }
3694
3695 switch (target)
3696 {
3697 case GL_TRANSFORM_FEEDBACK:
3698 {
3699 // Cannot bind a transform feedback object if the current one is started and not
3700 // paused (3.0.2 pg 85 section 2.14.1)
3701 if (context->getState().isTransformFeedbackActiveUnpaused())
3702 {
3703 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
3704 return false;
3705 }
3706
3707 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3708 // 2.14.1)
3709 if (!context->isTransformFeedbackGenerated(id))
3710 {
3711 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackDoesNotExist);
3712 return false;
3713 }
3714 }
3715 break;
3716
3717 default:
3718 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3719 return false;
3720 }
3721
3722 return true;
3723 }
3724
ValidateIsTransformFeedback(const Context * context,TransformFeedbackID id)3725 bool ValidateIsTransformFeedback(const Context *context, TransformFeedbackID id)
3726 {
3727 if (context->getClientMajorVersion() < 3)
3728 {
3729 context->validationError(GL_INVALID_OPERATION, kES3Required);
3730 return false;
3731 }
3732
3733 return true;
3734 }
3735
ValidatePauseTransformFeedback(const Context * context)3736 bool ValidatePauseTransformFeedback(const Context *context)
3737 {
3738 if (context->getClientMajorVersion() < 3)
3739 {
3740 context->validationError(GL_INVALID_OPERATION, kES3Required);
3741 return false;
3742 }
3743
3744 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3745 ASSERT(transformFeedback != nullptr);
3746
3747 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3748 if (!transformFeedback->isActive())
3749 {
3750 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
3751 return false;
3752 }
3753
3754 if (transformFeedback->isPaused())
3755 {
3756 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackPaused);
3757 return false;
3758 }
3759
3760 return true;
3761 }
3762
ValidateResumeTransformFeedback(const Context * context)3763 bool ValidateResumeTransformFeedback(const Context *context)
3764 {
3765 if (context->getClientMajorVersion() < 3)
3766 {
3767 context->validationError(GL_INVALID_OPERATION, kES3Required);
3768 return false;
3769 }
3770
3771 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
3772 ASSERT(transformFeedback != nullptr);
3773
3774 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3775 if (!transformFeedback->isActive())
3776 {
3777 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackNotActive);
3778 return false;
3779 }
3780
3781 if (!transformFeedback->isPaused())
3782 {
3783 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
3784 return false;
3785 }
3786
3787 return true;
3788 }
3789
ValidateVertexAttribI4i(const Context * context,GLuint index,GLint x,GLint y,GLint z,GLint w)3790 bool ValidateVertexAttribI4i(const Context *context,
3791 GLuint index,
3792 GLint x,
3793 GLint y,
3794 GLint z,
3795 GLint w)
3796 {
3797 if (context->getClientMajorVersion() < 3)
3798 {
3799 context->validationError(GL_INVALID_OPERATION, kES3Required);
3800 return false;
3801 }
3802
3803 return ValidateVertexAttribIndex(context, index);
3804 }
3805
ValidateVertexAttribI4ui(const Context * context,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)3806 bool ValidateVertexAttribI4ui(const Context *context,
3807 GLuint index,
3808 GLuint x,
3809 GLuint y,
3810 GLuint z,
3811 GLuint w)
3812 {
3813 if (context->getClientMajorVersion() < 3)
3814 {
3815 context->validationError(GL_INVALID_OPERATION, kES3Required);
3816 return false;
3817 }
3818
3819 return ValidateVertexAttribIndex(context, index);
3820 }
3821
ValidateVertexAttribI4iv(const Context * context,GLuint index,const GLint * v)3822 bool ValidateVertexAttribI4iv(const Context *context, GLuint index, const GLint *v)
3823 {
3824 if (context->getClientMajorVersion() < 3)
3825 {
3826 context->validationError(GL_INVALID_OPERATION, kES3Required);
3827 return false;
3828 }
3829
3830 return ValidateVertexAttribIndex(context, index);
3831 }
3832
ValidateVertexAttribI4uiv(const Context * context,GLuint index,const GLuint * v)3833 bool ValidateVertexAttribI4uiv(const Context *context, GLuint index, const GLuint *v)
3834 {
3835 if (context->getClientMajorVersion() < 3)
3836 {
3837 context->validationError(GL_INVALID_OPERATION, kES3Required);
3838 return false;
3839 }
3840
3841 return ValidateVertexAttribIndex(context, index);
3842 }
3843
ValidateGetFragDataLocation(const Context * context,ShaderProgramID program,const GLchar * name)3844 bool ValidateGetFragDataLocation(const Context *context,
3845 ShaderProgramID program,
3846 const GLchar *name)
3847 {
3848 if (context->getClientMajorVersion() < 3)
3849 {
3850 context->validationError(GL_INVALID_OPERATION, kES3Required);
3851 return false;
3852 }
3853
3854 Program *programObject = GetValidProgram(context, program);
3855 if (!programObject)
3856 {
3857 return false;
3858 }
3859
3860 if (!programObject->isLinked())
3861 {
3862 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
3863 return false;
3864 }
3865
3866 return true;
3867 }
3868
ValidateGetUniformIndices(const Context * context,ShaderProgramID program,GLsizei uniformCount,const GLchar * const * uniformNames,const GLuint * uniformIndices)3869 bool ValidateGetUniformIndices(const Context *context,
3870 ShaderProgramID program,
3871 GLsizei uniformCount,
3872 const GLchar *const *uniformNames,
3873 const GLuint *uniformIndices)
3874 {
3875 if (context->getClientMajorVersion() < 3)
3876 {
3877 context->validationError(GL_INVALID_OPERATION, kES3Required);
3878 return false;
3879 }
3880
3881 if (uniformCount < 0)
3882 {
3883 context->validationError(GL_INVALID_VALUE, kNegativeCount);
3884 return false;
3885 }
3886
3887 Program *programObject = GetValidProgram(context, program);
3888 if (!programObject)
3889 {
3890 return false;
3891 }
3892
3893 return true;
3894 }
3895
ValidateGetActiveUniformsiv(const Context * context,ShaderProgramID program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,const GLint * params)3896 bool ValidateGetActiveUniformsiv(const Context *context,
3897 ShaderProgramID program,
3898 GLsizei uniformCount,
3899 const GLuint *uniformIndices,
3900 GLenum pname,
3901 const GLint *params)
3902 {
3903 if (context->getClientMajorVersion() < 3)
3904 {
3905 context->validationError(GL_INVALID_OPERATION, kES3Required);
3906 return false;
3907 }
3908
3909 if (uniformCount < 0)
3910 {
3911 context->validationError(GL_INVALID_VALUE, kNegativeCount);
3912 return false;
3913 }
3914
3915 Program *programObject = GetValidProgram(context, program);
3916 if (!programObject)
3917 {
3918 return false;
3919 }
3920
3921 switch (pname)
3922 {
3923 case GL_UNIFORM_TYPE:
3924 case GL_UNIFORM_SIZE:
3925 break;
3926 case GL_UNIFORM_NAME_LENGTH:
3927 if (context->getExtensions().webglCompatibility)
3928 {
3929 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3930 return false;
3931 }
3932 break;
3933 case GL_UNIFORM_BLOCK_INDEX:
3934 case GL_UNIFORM_OFFSET:
3935 case GL_UNIFORM_ARRAY_STRIDE:
3936 case GL_UNIFORM_MATRIX_STRIDE:
3937 case GL_UNIFORM_IS_ROW_MAJOR:
3938 break;
3939
3940 default:
3941 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3942 return false;
3943 }
3944
3945 if (uniformCount > programObject->getActiveUniformCount())
3946 {
3947 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
3948 return false;
3949 }
3950
3951 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3952 {
3953 const GLuint index = uniformIndices[uniformId];
3954
3955 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3956 {
3957 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
3958 return false;
3959 }
3960 }
3961
3962 return true;
3963 }
3964
ValidateGetUniformBlockIndex(const Context * context,ShaderProgramID program,const GLchar * uniformBlockName)3965 bool ValidateGetUniformBlockIndex(const Context *context,
3966 ShaderProgramID program,
3967 const GLchar *uniformBlockName)
3968 {
3969 if (context->getClientMajorVersion() < 3)
3970 {
3971 context->validationError(GL_INVALID_OPERATION, kES3Required);
3972 return false;
3973 }
3974
3975 Program *programObject = GetValidProgram(context, program);
3976 if (!programObject)
3977 {
3978 return false;
3979 }
3980
3981 return true;
3982 }
3983
ValidateGetActiveUniformBlockiv(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLenum pname,const GLint * params)3984 bool ValidateGetActiveUniformBlockiv(const Context *context,
3985 ShaderProgramID program,
3986 GLuint uniformBlockIndex,
3987 GLenum pname,
3988 const GLint *params)
3989 {
3990 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3991 }
3992
ValidateGetActiveUniformBlockName(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLsizei bufSize,const GLsizei * length,const GLchar * uniformBlockName)3993 bool ValidateGetActiveUniformBlockName(const Context *context,
3994 ShaderProgramID program,
3995 GLuint uniformBlockIndex,
3996 GLsizei bufSize,
3997 const GLsizei *length,
3998 const GLchar *uniformBlockName)
3999 {
4000 if (context->getClientMajorVersion() < 3)
4001 {
4002 context->validationError(GL_INVALID_OPERATION, kES3Required);
4003 return false;
4004 }
4005
4006 Program *programObject = GetValidProgram(context, program);
4007 if (!programObject)
4008 {
4009 return false;
4010 }
4011
4012 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
4013 {
4014 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
4015 return false;
4016 }
4017
4018 return true;
4019 }
4020
ValidateUniformBlockBinding(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLuint uniformBlockBinding)4021 bool ValidateUniformBlockBinding(const Context *context,
4022 ShaderProgramID program,
4023 GLuint uniformBlockIndex,
4024 GLuint uniformBlockBinding)
4025 {
4026 if (context->getClientMajorVersion() < 3)
4027 {
4028 context->validationError(GL_INVALID_OPERATION, kES3Required);
4029 return false;
4030 }
4031
4032 if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
4033 {
4034 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4035 return false;
4036 }
4037
4038 Program *programObject = GetValidProgram(context, program);
4039 if (!programObject)
4040 {
4041 return false;
4042 }
4043
4044 // if never linked, there won't be any uniform blocks
4045 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
4046 {
4047 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxUniformBufferBindings);
4048 return false;
4049 }
4050
4051 return true;
4052 }
4053
ValidateDrawArraysInstanced(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4054 bool ValidateDrawArraysInstanced(const Context *context,
4055 PrimitiveMode mode,
4056 GLint first,
4057 GLsizei count,
4058 GLsizei primcount)
4059 {
4060 if (context->getClientMajorVersion() < 3)
4061 {
4062 context->validationError(GL_INVALID_OPERATION, kES3Required);
4063 return false;
4064 }
4065
4066 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
4067 }
4068
ValidateFenceSync(const Context * context,GLenum condition,GLbitfield flags)4069 bool ValidateFenceSync(const Context *context, GLenum condition, GLbitfield flags)
4070 {
4071 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4072 {
4073 context->validationError(GL_INVALID_OPERATION, kES3Required);
4074 return false;
4075 }
4076
4077 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
4078 {
4079 context->validationError(GL_INVALID_ENUM, kInvalidFenceCondition);
4080 return false;
4081 }
4082
4083 if (flags != 0)
4084 {
4085 context->validationError(GL_INVALID_VALUE, kInvalidFlags);
4086 return false;
4087 }
4088
4089 return true;
4090 }
4091
ValidateIsSync(const Context * context,GLsync sync)4092 bool ValidateIsSync(const Context *context, GLsync sync)
4093 {
4094 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4095 {
4096 context->validationError(GL_INVALID_OPERATION, kES3Required);
4097 return false;
4098 }
4099
4100 return true;
4101 }
4102
ValidateDeleteSync(const Context * context,GLsync sync)4103 bool ValidateDeleteSync(const Context *context, GLsync sync)
4104 {
4105 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4106 {
4107 context->validationError(GL_INVALID_OPERATION, kES3Required);
4108 return false;
4109 }
4110
4111 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
4112 {
4113 context->validationError(GL_INVALID_VALUE, kSyncMissing);
4114 return false;
4115 }
4116
4117 return true;
4118 }
4119
ValidateClientWaitSync(const Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)4120 bool ValidateClientWaitSync(const Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
4121 {
4122 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4123 {
4124 context->validationError(GL_INVALID_OPERATION, kES3Required);
4125 return false;
4126 }
4127
4128 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
4129 {
4130 context->validationError(GL_INVALID_VALUE, kInvalidFlags);
4131 return false;
4132 }
4133
4134 Sync *clientWaitSync = context->getSync(sync);
4135 if (!clientWaitSync)
4136 {
4137 context->validationError(GL_INVALID_VALUE, kSyncMissing);
4138 return false;
4139 }
4140
4141 return true;
4142 }
4143
ValidateWaitSync(const Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)4144 bool ValidateWaitSync(const Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
4145 {
4146 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4147 {
4148 context->validationError(GL_INVALID_OPERATION, kES3Required);
4149 return false;
4150 }
4151
4152 if (flags != 0)
4153 {
4154 context->validationError(GL_INVALID_VALUE, kInvalidFlags);
4155 return false;
4156 }
4157
4158 if (timeout != GL_TIMEOUT_IGNORED)
4159 {
4160 context->validationError(GL_INVALID_VALUE, kInvalidTimeout);
4161 return false;
4162 }
4163
4164 Sync *waitSync = context->getSync(sync);
4165 if (!waitSync)
4166 {
4167 context->validationError(GL_INVALID_VALUE, kSyncMissing);
4168 return false;
4169 }
4170
4171 return true;
4172 }
4173
ValidateGetInteger64v(const Context * context,GLenum pname,const GLint64 * params)4174 bool ValidateGetInteger64v(const Context *context, GLenum pname, const GLint64 *params)
4175 {
4176 if ((context->getClientMajorVersion() < 3) && !context->getExtensions().glSyncARB)
4177 {
4178 context->validationError(GL_INVALID_OPERATION, kES3Required);
4179 return false;
4180 }
4181
4182 GLenum nativeType = GL_NONE;
4183 unsigned int numParams = 0;
4184 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
4185 {
4186 return false;
4187 }
4188
4189 return true;
4190 }
4191
ValidateIsSampler(const Context * context,SamplerID sampler)4192 bool ValidateIsSampler(const Context *context, SamplerID sampler)
4193 {
4194 if (context->getClientMajorVersion() < 3)
4195 {
4196 context->validationError(GL_INVALID_OPERATION, kES3Required);
4197 return false;
4198 }
4199
4200 return true;
4201 }
4202
ValidateBindSampler(const Context * context,GLuint unit,SamplerID sampler)4203 bool ValidateBindSampler(const Context *context, GLuint unit, SamplerID sampler)
4204 {
4205 if (context->getClientMajorVersion() < 3)
4206 {
4207 context->validationError(GL_INVALID_OPERATION, kES3Required);
4208 return false;
4209 }
4210
4211 if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
4212 {
4213 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
4214 return false;
4215 }
4216
4217 if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
4218 {
4219 context->validationError(GL_INVALID_VALUE, kInvalidCombinedImageUnit);
4220 return false;
4221 }
4222
4223 return true;
4224 }
4225
ValidateVertexAttribDivisor(const Context * context,GLuint index,GLuint divisor)4226 bool ValidateVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
4227 {
4228 if (context->getClientMajorVersion() < 3)
4229 {
4230 context->validationError(GL_INVALID_OPERATION, kES3Required);
4231 return false;
4232 }
4233
4234 return ValidateVertexAttribIndex(context, index);
4235 }
4236
ValidateTexStorage2D(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)4237 bool ValidateTexStorage2D(const Context *context,
4238 TextureType target,
4239 GLsizei levels,
4240 GLenum internalformat,
4241 GLsizei width,
4242 GLsizei height)
4243 {
4244 if (context->getClientMajorVersion() < 3)
4245 {
4246 context->validationError(GL_INVALID_OPERATION, kES3Required);
4247 return false;
4248 }
4249
4250 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
4251 1))
4252 {
4253 return false;
4254 }
4255
4256 return true;
4257 }
4258
ValidateTexStorage3D(const Context * context,TextureType target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)4259 bool ValidateTexStorage3D(const Context *context,
4260 TextureType target,
4261 GLsizei levels,
4262 GLenum internalformat,
4263 GLsizei width,
4264 GLsizei height,
4265 GLsizei depth)
4266 {
4267 if (context->getClientMajorVersion() < 3)
4268 {
4269 context->validationError(GL_INVALID_OPERATION, kES3Required);
4270 return false;
4271 }
4272
4273 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
4274 depth))
4275 {
4276 return false;
4277 }
4278
4279 return true;
4280 }
4281
ValidateGetBufferParameteri64v(const Context * context,BufferBinding target,GLenum pname,const GLint64 * params)4282 bool ValidateGetBufferParameteri64v(const Context *context,
4283 BufferBinding target,
4284 GLenum pname,
4285 const GLint64 *params)
4286 {
4287 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4288 }
4289
ValidateGetSamplerParameterfv(const Context * context,SamplerID sampler,GLenum pname,const GLfloat * params)4290 bool ValidateGetSamplerParameterfv(const Context *context,
4291 SamplerID sampler,
4292 GLenum pname,
4293 const GLfloat *params)
4294 {
4295 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4296 }
4297
ValidateGetSamplerParameteriv(const Context * context,SamplerID sampler,GLenum pname,const GLint * params)4298 bool ValidateGetSamplerParameteriv(const Context *context,
4299 SamplerID sampler,
4300 GLenum pname,
4301 const GLint *params)
4302 {
4303 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4304 }
4305
ValidateGetSamplerParameterIivOES(const Context * context,SamplerID sampler,GLenum pname,const GLint * params)4306 bool ValidateGetSamplerParameterIivOES(const Context *context,
4307 SamplerID sampler,
4308 GLenum pname,
4309 const GLint *params)
4310 {
4311 if (context->getClientMajorVersion() < 3)
4312 {
4313 context->validationError(GL_INVALID_OPERATION, kES3Required);
4314 return false;
4315 }
4316 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4317 }
4318
ValidateGetSamplerParameterIuivOES(const Context * context,SamplerID sampler,GLenum pname,const GLuint * params)4319 bool ValidateGetSamplerParameterIuivOES(const Context *context,
4320 SamplerID sampler,
4321 GLenum pname,
4322 const GLuint *params)
4323 {
4324 if (context->getClientMajorVersion() < 3)
4325 {
4326 context->validationError(GL_INVALID_OPERATION, kES3Required);
4327 return false;
4328 }
4329 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4330 }
4331
ValidateSamplerParameterf(const Context * context,SamplerID sampler,GLenum pname,GLfloat param)4332 bool ValidateSamplerParameterf(const Context *context,
4333 SamplerID sampler,
4334 GLenum pname,
4335 GLfloat param)
4336 {
4337 return ValidateSamplerParameterBase(context, sampler, pname, -1, false, ¶m);
4338 }
4339
ValidateSamplerParameterfv(const Context * context,SamplerID sampler,GLenum pname,const GLfloat * params)4340 bool ValidateSamplerParameterfv(const Context *context,
4341 SamplerID sampler,
4342 GLenum pname,
4343 const GLfloat *params)
4344 {
4345 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4346 }
4347
ValidateSamplerParameteri(const Context * context,SamplerID sampler,GLenum pname,GLint param)4348 bool ValidateSamplerParameteri(const Context *context, SamplerID sampler, GLenum pname, GLint param)
4349 {
4350 return ValidateSamplerParameterBase(context, sampler, pname, -1, false, ¶m);
4351 }
4352
ValidateSamplerParameteriv(const Context * context,SamplerID sampler,GLenum pname,const GLint * params)4353 bool ValidateSamplerParameteriv(const Context *context,
4354 SamplerID sampler,
4355 GLenum pname,
4356 const GLint *params)
4357 {
4358 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4359 }
4360
ValidateSamplerParameterIivOES(const Context * context,SamplerID sampler,GLenum pname,const GLint * params)4361 bool ValidateSamplerParameterIivOES(const Context *context,
4362 SamplerID sampler,
4363 GLenum pname,
4364 const GLint *params)
4365 {
4366 if (context->getClientMajorVersion() < 3)
4367 {
4368 context->validationError(GL_INVALID_OPERATION, kES3Required);
4369 return false;
4370 }
4371 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4372 }
4373
ValidateSamplerParameterIuivOES(const Context * context,SamplerID sampler,GLenum pname,const GLuint * params)4374 bool ValidateSamplerParameterIuivOES(const Context *context,
4375 SamplerID sampler,
4376 GLenum pname,
4377 const GLuint *params)
4378 {
4379 if (context->getClientMajorVersion() < 3)
4380 {
4381 context->validationError(GL_INVALID_OPERATION, kES3Required);
4382 return false;
4383 }
4384 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4385 }
4386
ValidateGetVertexAttribIiv(const Context * context,GLuint index,GLenum pname,const GLint * params)4387 bool ValidateGetVertexAttribIiv(const Context *context,
4388 GLuint index,
4389 GLenum pname,
4390 const GLint *params)
4391 {
4392 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4393 }
4394
ValidateGetVertexAttribIuiv(const Context * context,GLuint index,GLenum pname,const GLuint * params)4395 bool ValidateGetVertexAttribIuiv(const Context *context,
4396 GLuint index,
4397 GLenum pname,
4398 const GLuint *params)
4399 {
4400 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4401 }
4402
ValidateGetInternalformativ(const Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLint * params)4403 bool ValidateGetInternalformativ(const Context *context,
4404 GLenum target,
4405 GLenum internalformat,
4406 GLenum pname,
4407 GLsizei bufSize,
4408 const GLint *params)
4409 {
4410 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4411 nullptr);
4412 }
4413
ValidateBindFragDataLocationIndexedEXT(const Context * context,ShaderProgramID program,GLuint colorNumber,GLuint index,const char * name)4414 bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
4415 ShaderProgramID program,
4416 GLuint colorNumber,
4417 GLuint index,
4418 const char *name)
4419 {
4420 if (!context->getExtensions().blendFuncExtended)
4421 {
4422 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4423 return false;
4424 }
4425 if (context->getClientMajorVersion() < 3)
4426 {
4427 context->validationError(GL_INVALID_OPERATION, kES3Required);
4428 return false;
4429 }
4430 if (index > 1)
4431 {
4432 // This error is not explicitly specified but the spec does say that "<index> may be zero or
4433 // one to specify that the color be used as either the first or second color input to the
4434 // blend equation, respectively"
4435 context->validationError(GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
4436 return false;
4437 }
4438 if (index == 1)
4439 {
4440 if (colorNumber >= context->getExtensions().maxDualSourceDrawBuffers)
4441 {
4442 context->validationError(GL_INVALID_VALUE,
4443 kColorNumberGreaterThanMaxDualSourceDrawBuffers);
4444 return false;
4445 }
4446 }
4447 else
4448 {
4449 if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
4450 {
4451 context->validationError(GL_INVALID_VALUE, kColorNumberGreaterThanMaxDrawBuffers);
4452 return false;
4453 }
4454 }
4455 Program *programObject = GetValidProgram(context, program);
4456 if (!programObject)
4457 {
4458 return false;
4459 }
4460 return true;
4461 }
4462
ValidateBindFragDataLocationEXT(const Context * context,ShaderProgramID program,GLuint colorNumber,const char * name)4463 bool ValidateBindFragDataLocationEXT(const Context *context,
4464 ShaderProgramID program,
4465 GLuint colorNumber,
4466 const char *name)
4467 {
4468 return ValidateBindFragDataLocationIndexedEXT(context, program, colorNumber, 0u, name);
4469 }
4470
ValidateGetFragDataIndexEXT(const Context * context,ShaderProgramID program,const char * name)4471 bool ValidateGetFragDataIndexEXT(const Context *context, ShaderProgramID program, const char *name)
4472 {
4473 if (!context->getExtensions().blendFuncExtended)
4474 {
4475 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4476 return false;
4477 }
4478 if (context->getClientMajorVersion() < 3)
4479 {
4480 context->validationError(GL_INVALID_OPERATION, kES3Required);
4481 return false;
4482 }
4483 Program *programObject = GetValidProgram(context, program);
4484 if (!programObject)
4485 {
4486 return false;
4487 }
4488 if (!programObject->isLinked())
4489 {
4490 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4491 return false;
4492 }
4493 return true;
4494 }
4495
ValidateTexStorage2DMultisampleANGLE(const Context * context,TextureType target,GLsizei samples,GLenum internalFormat,GLsizei width,GLsizei height,GLboolean fixedSampleLocations)4496 bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
4497 TextureType target,
4498 GLsizei samples,
4499 GLenum internalFormat,
4500 GLsizei width,
4501 GLsizei height,
4502 GLboolean fixedSampleLocations)
4503 {
4504 if (!context->getExtensions().textureMultisample)
4505 {
4506 context->validationError(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
4507 return false;
4508 }
4509
4510 return ValidateTexStorage2DMultisampleBase(context, target, samples, internalFormat, width,
4511 height);
4512 }
4513
ValidateGetTexLevelParameterfvANGLE(const Context * context,TextureTarget target,GLint level,GLenum pname,const GLfloat * params)4514 bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
4515 TextureTarget target,
4516 GLint level,
4517 GLenum pname,
4518 const GLfloat *params)
4519 {
4520 if (!context->getExtensions().textureMultisample)
4521 {
4522 context->validationError(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
4523 return false;
4524 }
4525
4526 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
4527 }
4528
ValidateGetTexLevelParameterivANGLE(const Context * context,TextureTarget target,GLint level,GLenum pname,const GLint * params)4529 bool ValidateGetTexLevelParameterivANGLE(const Context *context,
4530 TextureTarget target,
4531 GLint level,
4532 GLenum pname,
4533 const GLint *params)
4534 {
4535 if (!context->getExtensions().textureMultisample)
4536 {
4537 context->validationError(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
4538 return false;
4539 }
4540
4541 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
4542 }
4543
ValidateGetMultisamplefvANGLE(const Context * context,GLenum pname,GLuint index,const GLfloat * val)4544 bool ValidateGetMultisamplefvANGLE(const Context *context,
4545 GLenum pname,
4546 GLuint index,
4547 const GLfloat *val)
4548 {
4549 if (!context->getExtensions().textureMultisample)
4550 {
4551 context->validationError(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
4552 return false;
4553 }
4554
4555 return ValidateGetMultisamplefvBase(context, pname, index, val);
4556 }
4557
ValidateSampleMaskiANGLE(const Context * context,GLuint maskNumber,GLbitfield mask)4558 bool ValidateSampleMaskiANGLE(const Context *context, GLuint maskNumber, GLbitfield mask)
4559 {
4560 if (!context->getExtensions().textureMultisample)
4561 {
4562 context->validationError(GL_INVALID_OPERATION, kMultisampleTextureExtensionOrES31Required);
4563 return false;
4564 }
4565
4566 return ValidateSampleMaskiBase(context, maskNumber, mask);
4567 }
4568 } // namespace gl
4569