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