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