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