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