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