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