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