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