1 //
2 // Copyright (c) 2013-2014 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.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/formatutils.h"
21 #include "libANGLE/validationES.h"
22
23 using namespace angle;
24
25 namespace gl
26 {
27
28 namespace
29 {
ValidateFramebufferTextureMultiviewBaseANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLsizei numViews)30 bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
31 GLenum target,
32 GLenum attachment,
33 GLuint texture,
34 GLint level,
35 GLsizei numViews)
36 {
37 if (!context->getExtensions().multiview)
38 {
39 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
40 return false;
41 }
42
43 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
44 {
45 return false;
46 }
47
48 if (texture != 0 && numViews < 1)
49 {
50 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
51 return false;
52 }
53
54 const Extensions &extensions = context->getExtensions();
55 if (static_cast<GLuint>(numViews) > extensions.maxViews)
56 {
57 context->handleError(InvalidValue()
58 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
59 return false;
60 }
61
62 return true;
63 }
64
ValidateFramebufferTextureMultiviewLevelAndFormat(Context * context,Texture * texture,GLint level)65 bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
66 Texture *texture,
67 GLint level)
68 {
69 GLenum texTarget = texture->getTarget();
70 if (!ValidMipLevel(context, texTarget, level))
71 {
72 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
73 return false;
74 }
75
76 const auto &format = texture->getFormat(texTarget, level);
77 if (format.info->compressed)
78 {
79 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
80 return false;
81 }
82 return true;
83 }
84
ValidateUniformES3(Context * context,GLenum uniformType,GLint location,GLint count)85 bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
86 {
87 if (context->getClientMajorVersion() < 3)
88 {
89 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
90 return false;
91 }
92
93 return ValidateUniform(context, uniformType, location, count);
94 }
95
ValidateUniformMatrixES3(Context * context,GLenum valueType,GLint location,GLsizei count,GLboolean transpose)96 bool ValidateUniformMatrixES3(Context *context,
97 GLenum valueType,
98 GLint location,
99 GLsizei count,
100 GLboolean transpose)
101 {
102 // Check for ES3 uniform entry points
103 if (context->getClientMajorVersion() < 3)
104 {
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
106 return false;
107 }
108
109 return ValidateUniformMatrix(context, valueType, location, count, transpose);
110 }
111
ValidateGenOrDeleteES3(Context * context,GLint n)112 bool ValidateGenOrDeleteES3(Context *context, GLint n)
113 {
114 if (context->getClientMajorVersion() < 3)
115 {
116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
117 return false;
118 }
119 return ValidateGenOrDelete(context, n);
120 }
121
ValidateGenOrDeleteCountES3(Context * context,GLint count)122 bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
123 {
124 if (context->getClientMajorVersion() < 3)
125 {
126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
127 return false;
128 }
129 if (count < 0)
130 {
131 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
132 return false;
133 }
134 return true;
135 }
136
137 } // anonymous namespace
138
ValidateTexImageFormatCombination(gl::Context * context,GLenum target,GLenum internalFormat,GLenum format,GLenum type)139 static bool ValidateTexImageFormatCombination(gl::Context *context,
140 GLenum target,
141 GLenum internalFormat,
142 GLenum format,
143 GLenum type)
144 {
145
146 // The type and format are valid if any supported internal format has that type and format
147 if (!ValidES3Format(format))
148 {
149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
150 return false;
151 }
152
153 if (!ValidES3Type(type))
154 {
155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
156 return false;
157 }
158
159 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
160 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
161 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
162 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
163 if (!ValidES3InternalFormat(internalFormat))
164 {
165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
166 return false;
167 }
168
169 // From the ES 3.0 spec section 3.8.3:
170 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
171 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
172 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
173 // INVALID_OPERATION error.
174 if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
175 {
176 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
177 "GL_DEPTH_STENCIL if target is "
178 "GL_TEXTURE_3D");
179 return false;
180 }
181
182 // Check if this is a valid format combination to load texture data
183 if (!ValidES3FormatCombination(format, type, internalFormat))
184 {
185 context->handleError(InvalidOperation()
186 << "Invalid combination of format, type and internalFormat.");
187 return false;
188 }
189
190 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
191 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
192 {
193 context->handleError(InvalidOperation() << "Unsupported internal format.");
194 return false;
195 }
196
197 return true;
198 }
199
ValidateES3TexImageParametersBase(Context * context,GLenum 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)200 bool ValidateES3TexImageParametersBase(Context *context,
201 GLenum target,
202 GLint level,
203 GLenum internalformat,
204 bool isCompressed,
205 bool isSubImage,
206 GLint xoffset,
207 GLint yoffset,
208 GLint zoffset,
209 GLsizei width,
210 GLsizei height,
211 GLsizei depth,
212 GLint border,
213 GLenum format,
214 GLenum type,
215 GLsizei imageSize,
216 const void *pixels)
217 {
218 // Validate image size
219 if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
220 {
221 context->handleError(InvalidValue());
222 return false;
223 }
224
225 // Verify zero border
226 if (border != 0)
227 {
228 context->handleError(InvalidValue());
229 return false;
230 }
231
232 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
233 std::numeric_limits<GLsizei>::max() - xoffset < width ||
234 std::numeric_limits<GLsizei>::max() - yoffset < height ||
235 std::numeric_limits<GLsizei>::max() - zoffset < depth)
236 {
237 context->handleError(InvalidValue());
238 return false;
239 }
240
241 const gl::Caps &caps = context->getCaps();
242
243 switch (target)
244 {
245 case GL_TEXTURE_2D:
246 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
247 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
248 {
249 context->handleError(InvalidValue());
250 return false;
251 }
252 break;
253
254 case GL_TEXTURE_RECTANGLE_ANGLE:
255 ASSERT(level == 0);
256 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
257 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
258 {
259 context->handleError(InvalidValue());
260 return false;
261 }
262 if (isCompressed)
263 {
264 context->handleError(InvalidEnum()
265 << "Rectangle texture cannot have a compressed format.");
266 return false;
267 }
268 break;
269
270 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
271 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
272 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
276 if (!isSubImage && width != height)
277 {
278 context->handleError(InvalidValue());
279 return false;
280 }
281
282 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
283 {
284 context->handleError(InvalidValue());
285 return false;
286 }
287 break;
288
289 case GL_TEXTURE_3D:
290 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
291 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
292 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
293 {
294 context->handleError(InvalidValue());
295 return false;
296 }
297 break;
298
299 case GL_TEXTURE_2D_ARRAY:
300 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
301 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
302 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
303 {
304 context->handleError(InvalidValue());
305 return false;
306 }
307 break;
308
309 default:
310 context->handleError(InvalidEnum());
311 return false;
312 }
313
314 gl::Texture *texture =
315 context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
316 if (!texture)
317 {
318 context->handleError(InvalidOperation());
319 return false;
320 }
321
322 if (texture->getImmutableFormat() && !isSubImage)
323 {
324 context->handleError(InvalidOperation());
325 return false;
326 }
327
328 // Validate texture formats
329 GLenum actualInternalFormat =
330 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
331 if (isSubImage && actualInternalFormat == GL_NONE)
332 {
333 context->handleError(InvalidOperation() << "Texture level does not exist.");
334 return false;
335 }
336
337 const gl::InternalFormat &actualFormatInfo = isSubImage
338 ? *texture->getFormat(target, level).info
339 : GetInternalFormatInfo(internalformat, type);
340 if (isCompressed)
341 {
342 if (!actualFormatInfo.compressed)
343 {
344 context->handleError(
345 InvalidEnum() << "internalformat is not a supported compressed internal format.");
346 return false;
347 }
348
349 if (isSubImage)
350 {
351 if (!ValidCompressedSubImageSize(
352 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
353 texture->getWidth(target, level), texture->getHeight(target, level)))
354 {
355 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
356 return false;
357 }
358
359 if (format != actualInternalFormat)
360 {
361 context->handleError(InvalidOperation()
362 << "Format must match the internal format of the texture.");
363 return false;
364 }
365
366 if (actualInternalFormat == GL_ETC1_RGB8_OES)
367 {
368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
369 return false;
370 }
371 }
372 else
373 {
374 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
375 {
376 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
377 return false;
378 }
379 }
380
381 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
382 {
383 context->handleError(InvalidEnum());
384 return false;
385 }
386
387 if (target == GL_TEXTURE_3D)
388 {
389 context->handleError(InvalidOperation());
390 return false;
391 }
392 }
393 else
394 {
395 if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
396 {
397 return false;
398 }
399 }
400
401 // Validate sub image parameters
402 if (isSubImage)
403 {
404 if (isCompressed != actualFormatInfo.compressed)
405 {
406 context->handleError(InvalidOperation());
407 return false;
408 }
409
410 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
411 {
412 context->handleError(InvalidValue());
413 return false;
414 }
415
416 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
417 std::numeric_limits<GLsizei>::max() - yoffset < height ||
418 std::numeric_limits<GLsizei>::max() - zoffset < depth)
419 {
420 context->handleError(InvalidValue());
421 return false;
422 }
423
424 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
425 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
426 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
427 {
428 context->handleError(InvalidValue());
429 return false;
430 }
431
432 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
433 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
434 {
435 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
436 return false;
437 }
438 }
439
440 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
441 if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
442 imageSize))
443 {
444 return false;
445 }
446
447 // Check for pixel unpack buffer related API errors
448 gl::Buffer *pixelUnpackBuffer =
449 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
450 if (pixelUnpackBuffer != nullptr)
451 {
452 // ...data is not evenly divisible into the number of bytes needed to store in memory a
453 // datum
454 // indicated by type.
455 if (!isCompressed)
456 {
457 size_t offset = reinterpret_cast<size_t>(pixels);
458 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
459
460 if ((offset % dataBytesPerPixel) != 0)
461 {
462 context->handleError(InvalidOperation()
463 << "Reads would overflow the pixel unpack buffer.");
464 return false;
465 }
466 }
467
468 // ...the buffer object's data store is currently mapped.
469 if (pixelUnpackBuffer->isMapped())
470 {
471 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
472 return false;
473 }
474 }
475
476 return true;
477 }
478
ValidateES3TexImage2DParameters(Context * context,GLenum 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)479 bool ValidateES3TexImage2DParameters(Context *context,
480 GLenum target,
481 GLint level,
482 GLenum internalformat,
483 bool isCompressed,
484 bool isSubImage,
485 GLint xoffset,
486 GLint yoffset,
487 GLint zoffset,
488 GLsizei width,
489 GLsizei height,
490 GLsizei depth,
491 GLint border,
492 GLenum format,
493 GLenum type,
494 GLsizei imageSize,
495 const void *pixels)
496 {
497 if (!ValidTexture2DDestinationTarget(context, target))
498 {
499 context->handleError(InvalidEnum());
500 return false;
501 }
502
503 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
504 isSubImage, xoffset, yoffset, zoffset, width, height,
505 depth, border, format, type, imageSize, pixels);
506 }
507
ValidateES3TexImage3DParameters(Context * context,GLenum 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)508 bool ValidateES3TexImage3DParameters(Context *context,
509 GLenum target,
510 GLint level,
511 GLenum internalformat,
512 bool isCompressed,
513 bool isSubImage,
514 GLint xoffset,
515 GLint yoffset,
516 GLint zoffset,
517 GLsizei width,
518 GLsizei height,
519 GLsizei depth,
520 GLint border,
521 GLenum format,
522 GLenum type,
523 GLsizei bufSize,
524 const void *pixels)
525 {
526 if (!ValidTexture3DDestinationTarget(context, target))
527 {
528 context->handleError(InvalidEnum());
529 return false;
530 }
531
532 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
533 isSubImage, xoffset, yoffset, zoffset, width, height,
534 depth, border, format, type, bufSize, pixels);
535 }
536
537 struct EffectiveInternalFormatInfo
538 {
539 GLenum effectiveFormat;
540 GLenum destFormat;
541 GLuint minRedBits;
542 GLuint maxRedBits;
543 GLuint minGreenBits;
544 GLuint maxGreenBits;
545 GLuint minBlueBits;
546 GLuint maxBlueBits;
547 GLuint minAlphaBits;
548 GLuint maxAlphaBits;
549 };
550
QueryEffectiveFormatList(const InternalFormat & srcFormat,GLenum targetFormat,const EffectiveInternalFormatInfo * list,size_t size,GLenum * outEffectiveFormat)551 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
552 GLenum targetFormat,
553 const EffectiveInternalFormatInfo *list,
554 size_t size,
555 GLenum *outEffectiveFormat)
556 {
557 for (size_t curFormat = 0; curFormat < size; ++curFormat)
558 {
559 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
560 if ((formatInfo.destFormat == targetFormat) &&
561 (formatInfo.minRedBits <= srcFormat.redBits &&
562 formatInfo.maxRedBits >= srcFormat.redBits) &&
563 (formatInfo.minGreenBits <= srcFormat.greenBits &&
564 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
565 (formatInfo.minBlueBits <= srcFormat.blueBits &&
566 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
567 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
568 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
569 {
570 *outEffectiveFormat = formatInfo.effectiveFormat;
571 return true;
572 }
573 }
574
575 *outEffectiveFormat = GL_NONE;
576 return false;
577 }
578
GetSizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,GLenum * outEffectiveFormat)579 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
580 GLenum *outEffectiveFormat)
581 {
582 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
583 // Effective internal format coresponding to destination internal format and linear source
584 // buffer component sizes.
585 // | Source channel min/max sizes |
586 // Effective Internal Format | N/A | R | G | B | A |
587 // clang-format off
588 constexpr EffectiveInternalFormatInfo list[] = {
589 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
590 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
591 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
592 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
593 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
594 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
595 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
596 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
597 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
598 };
599 // clang-format on
600
601 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
602 }
603
GetUnsizedEffectiveInternalFormatInfo(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)604 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
605 const InternalFormat &destFormat,
606 GLenum *outEffectiveFormat)
607 {
608 constexpr GLuint umax = UINT_MAX;
609
610 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
611 // Effective internal format coresponding to destination internal format andlinear source buffer
612 // component sizes.
613 // | Source channel min/max sizes |
614 // Effective Internal Format | Dest Format | R | G | B | A |
615 // clang-format off
616 constexpr EffectiveInternalFormatInfo list[] = {
617 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
618 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
619 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
620 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
621 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
622 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
623 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
624 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
625 };
626 // clang-format on
627
628 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
629 outEffectiveFormat);
630 }
631
GetEffectiveInternalFormat(const InternalFormat & srcFormat,const InternalFormat & destFormat,GLenum * outEffectiveFormat)632 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
633 const InternalFormat &destFormat,
634 GLenum *outEffectiveFormat)
635 {
636 if (destFormat.sized)
637 {
638 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
639 }
640 else
641 {
642 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
643 }
644 }
645
EqualOrFirstZero(GLuint first,GLuint second)646 static bool EqualOrFirstZero(GLuint first, GLuint second)
647 {
648 return first == 0 || first == second;
649 }
650
IsValidES3CopyTexImageCombination(const InternalFormat & textureFormatInfo,const InternalFormat & framebufferFormatInfo,GLuint readBufferHandle)651 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
652 const InternalFormat &framebufferFormatInfo,
653 GLuint readBufferHandle)
654 {
655 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
656 {
657 return false;
658 }
659
660 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
661 // must both be signed, unsigned, or fixed point and both source and destinations
662 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
663 // conversion between fixed and floating point.
664
665 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
666 (framebufferFormatInfo.colorEncoding == GL_SRGB))
667 {
668 return false;
669 }
670
671 if (((textureFormatInfo.componentType == GL_INT) !=
672 (framebufferFormatInfo.componentType == GL_INT)) ||
673 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
674 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
675 {
676 return false;
677 }
678
679 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
680 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
681 textureFormatInfo.componentType == GL_FLOAT) &&
682 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
683 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
684 framebufferFormatInfo.componentType == GL_FLOAT))
685 {
686 return false;
687 }
688
689 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
690 // The effective internal format of the source buffer is determined with the following rules
691 // applied in order:
692 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
693 // format then the effective internal format is the source buffer's sized internal format.
694 // * If the source buffer is a texture that was created with an unsized base internal format,
695 // then the effective internal format is the source image array's effective internal
696 // format, as specified by table 3.12, which is determined from the <format> and <type>
697 // that were used when the source image array was specified by TexImage*.
698 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
699 // where Destination Internal Format matches internalformat and where the [source channel
700 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
701 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
702 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
703 const InternalFormat *sourceEffectiveFormat = nullptr;
704 if (readBufferHandle != 0)
705 {
706 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
707 // renderbuffer
708 if (framebufferFormatInfo.sized)
709 {
710 sourceEffectiveFormat = &framebufferFormatInfo;
711 }
712 else
713 {
714 // Renderbuffers cannot be created with an unsized internal format, so this must be an
715 // unsized-format texture. We can use the same table we use when creating textures to
716 // get its effective sized format.
717 sourceEffectiveFormat =
718 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
719 }
720 }
721 else
722 {
723 // The effective internal format must be derived from the source framebuffer's channel
724 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
725 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
726 {
727 GLenum effectiveFormat;
728 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
729 &effectiveFormat))
730 {
731 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
732 }
733 else
734 {
735 return false;
736 }
737 }
738 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
739 {
740 // SRGB buffers can only be copied to sized format destinations according to table 3.18
741 if (textureFormatInfo.sized &&
742 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
743 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
744 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
745 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
746 {
747 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
748 }
749 else
750 {
751 return false;
752 }
753 }
754 else
755 {
756 UNREACHABLE();
757 return false;
758 }
759 }
760
761 if (textureFormatInfo.sized)
762 {
763 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
764 // sized, component sizes of the source and destination formats must exactly match if the
765 // destination format exists.
766 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
767 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
768 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
769 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
770 {
771 return false;
772 }
773 }
774
775 return true; // A conversion function exists, and no rule in the specification has precluded
776 // conversion between these formats.
777 }
778
ValidateES3CopyTexImageParametersBase(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)779 bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
780 GLenum target,
781 GLint level,
782 GLenum internalformat,
783 bool isSubImage,
784 GLint xoffset,
785 GLint yoffset,
786 GLint zoffset,
787 GLint x,
788 GLint y,
789 GLsizei width,
790 GLsizei height,
791 GLint border)
792 {
793 Format textureFormat = Format::Invalid();
794 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
795 xoffset, yoffset, zoffset, x, y, width, height, border,
796 &textureFormat))
797 {
798 return false;
799 }
800 ASSERT(textureFormat.valid() || !isSubImage);
801
802 const auto &state = context->getGLState();
803 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
804 GLuint readFramebufferID = framebuffer->id();
805
806 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
807 {
808 context->handleError(InvalidFramebufferOperation());
809 return false;
810 }
811
812 if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
813 {
814 context->handleError(InvalidOperation());
815 return false;
816 }
817
818 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
819
820 if (isSubImage)
821 {
822 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
823 readFramebufferID))
824 {
825 context->handleError(InvalidOperation());
826 return false;
827 }
828 }
829 else
830 {
831 // Use format/type from the source FBO. (Might not be perfect for all cases?)
832 const InternalFormat &framebufferFormat = *source->getFormat().info;
833 const InternalFormat ©Format = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
834 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
835 {
836 context->handleError(InvalidOperation());
837 return false;
838 }
839 }
840
841 // If width or height is zero, it is a no-op. Return false without setting an error.
842 return (width > 0 && height > 0);
843 }
844
ValidateES3CopyTexImage2DParameters(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)845 bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
846 GLenum target,
847 GLint level,
848 GLenum internalformat,
849 bool isSubImage,
850 GLint xoffset,
851 GLint yoffset,
852 GLint zoffset,
853 GLint x,
854 GLint y,
855 GLsizei width,
856 GLsizei height,
857 GLint border)
858 {
859 if (!ValidTexture2DDestinationTarget(context, target))
860 {
861 context->handleError(InvalidEnum());
862 return false;
863 }
864
865 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
866 xoffset, yoffset, zoffset, x, y, width, height,
867 border);
868 }
869
ValidateES3CopyTexImage3DParameters(ValidationContext * context,GLenum target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)870 bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
871 GLenum target,
872 GLint level,
873 GLenum internalformat,
874 bool isSubImage,
875 GLint xoffset,
876 GLint yoffset,
877 GLint zoffset,
878 GLint x,
879 GLint y,
880 GLsizei width,
881 GLsizei height,
882 GLint border)
883 {
884 if (!ValidTexture3DDestinationTarget(context, target))
885 {
886 context->handleError(InvalidEnum());
887 return false;
888 }
889
890 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
891 xoffset, yoffset, zoffset, x, y, width, height,
892 border);
893 }
894
ValidateES3TexStorageParametersBase(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)895 bool ValidateES3TexStorageParametersBase(Context *context,
896 GLenum target,
897 GLsizei levels,
898 GLenum internalformat,
899 GLsizei width,
900 GLsizei height,
901 GLsizei depth)
902 {
903 if (width < 1 || height < 1 || depth < 1 || levels < 1)
904 {
905 context->handleError(InvalidValue());
906 return false;
907 }
908
909 GLsizei maxDim = std::max(width, height);
910 if (target != GL_TEXTURE_2D_ARRAY)
911 {
912 maxDim = std::max(maxDim, depth);
913 }
914
915 if (levels > gl::log2(maxDim) + 1)
916 {
917 context->handleError(InvalidOperation());
918 return false;
919 }
920
921 const gl::Caps &caps = context->getCaps();
922
923 switch (target)
924 {
925 case GL_TEXTURE_2D:
926 {
927 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
928 static_cast<GLuint>(height) > caps.max2DTextureSize)
929 {
930 context->handleError(InvalidValue());
931 return false;
932 }
933 }
934 break;
935
936 case GL_TEXTURE_RECTANGLE_ANGLE:
937 {
938 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
939 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
940 {
941 context->handleError(InvalidValue());
942 return false;
943 }
944 }
945 break;
946
947 case GL_TEXTURE_CUBE_MAP:
948 {
949 if (width != height)
950 {
951 context->handleError(InvalidValue());
952 return false;
953 }
954
955 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
956 {
957 context->handleError(InvalidValue());
958 return false;
959 }
960 }
961 break;
962
963 case GL_TEXTURE_3D:
964 {
965 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
966 static_cast<GLuint>(height) > caps.max3DTextureSize ||
967 static_cast<GLuint>(depth) > caps.max3DTextureSize)
968 {
969 context->handleError(InvalidValue());
970 return false;
971 }
972 }
973 break;
974
975 case GL_TEXTURE_2D_ARRAY:
976 {
977 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
978 static_cast<GLuint>(height) > caps.max2DTextureSize ||
979 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
980 {
981 context->handleError(InvalidValue());
982 return false;
983 }
984 }
985 break;
986
987 default:
988 UNREACHABLE();
989 return false;
990 }
991
992 gl::Texture *texture = context->getTargetTexture(target);
993 if (!texture || texture->id() == 0)
994 {
995 context->handleError(InvalidOperation());
996 return false;
997 }
998
999 if (texture->getImmutableFormat())
1000 {
1001 context->handleError(InvalidOperation());
1002 return false;
1003 }
1004
1005 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
1006 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1007 {
1008 context->handleError(InvalidEnum());
1009 return false;
1010 }
1011
1012 if (!formatInfo.sized)
1013 {
1014 context->handleError(InvalidEnum());
1015 return false;
1016 }
1017
1018 if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
1019 {
1020 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1021 return false;
1022 }
1023
1024 return true;
1025 }
1026
ValidateES3TexStorage2DParameters(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1027 bool ValidateES3TexStorage2DParameters(Context *context,
1028 GLenum target,
1029 GLsizei levels,
1030 GLenum internalformat,
1031 GLsizei width,
1032 GLsizei height,
1033 GLsizei depth)
1034 {
1035 if (!ValidTexture2DTarget(context, target))
1036 {
1037 context->handleError(InvalidEnum());
1038 return false;
1039 }
1040
1041 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1042 height, depth);
1043 }
1044
ValidateES3TexStorage3DParameters(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)1045 bool ValidateES3TexStorage3DParameters(Context *context,
1046 GLenum target,
1047 GLsizei levels,
1048 GLenum internalformat,
1049 GLsizei width,
1050 GLsizei height,
1051 GLsizei depth)
1052 {
1053 if (!ValidTexture3DTarget(context, target))
1054 {
1055 context->handleError(InvalidEnum());
1056 return false;
1057 }
1058
1059 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1060 height, depth);
1061 }
1062
ValidateBeginQuery(gl::Context * context,GLenum target,GLuint id)1063 bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
1064 {
1065 if (context->getClientMajorVersion() < 3)
1066 {
1067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1068 return false;
1069 }
1070
1071 return ValidateBeginQueryBase(context, target, id);
1072 }
1073
ValidateEndQuery(gl::Context * context,GLenum target)1074 bool ValidateEndQuery(gl::Context *context, GLenum target)
1075 {
1076 if (context->getClientMajorVersion() < 3)
1077 {
1078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1079 return false;
1080 }
1081
1082 return ValidateEndQueryBase(context, target);
1083 }
1084
ValidateGetQueryiv(Context * context,GLenum target,GLenum pname,GLint * params)1085 bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
1086 {
1087 if (context->getClientMajorVersion() < 3)
1088 {
1089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1090 return false;
1091 }
1092
1093 return ValidateGetQueryivBase(context, target, pname, nullptr);
1094 }
1095
ValidateGetQueryObjectuiv(Context * context,GLuint id,GLenum pname,GLuint * params)1096 bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1097 {
1098 if (context->getClientMajorVersion() < 3)
1099 {
1100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1101 return false;
1102 }
1103
1104 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1105 }
1106
ValidateFramebufferTextureLayer(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint layer)1107 bool ValidateFramebufferTextureLayer(Context *context,
1108 GLenum target,
1109 GLenum attachment,
1110 GLuint texture,
1111 GLint level,
1112 GLint layer)
1113 {
1114 if (context->getClientMajorVersion() < 3)
1115 {
1116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1117 return false;
1118 }
1119
1120 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1121 {
1122 return false;
1123 }
1124
1125 const gl::Caps &caps = context->getCaps();
1126 if (texture != 0)
1127 {
1128 if (layer < 0)
1129 {
1130 context->handleError(InvalidValue());
1131 return false;
1132 }
1133
1134 gl::Texture *tex = context->getTexture(texture);
1135 ASSERT(tex);
1136
1137 switch (tex->getTarget())
1138 {
1139 case GL_TEXTURE_2D_ARRAY:
1140 {
1141 if (level > gl::log2(caps.max2DTextureSize))
1142 {
1143 context->handleError(InvalidValue());
1144 return false;
1145 }
1146
1147 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1148 {
1149 context->handleError(InvalidValue());
1150 return false;
1151 }
1152 }
1153 break;
1154
1155 case GL_TEXTURE_3D:
1156 {
1157 if (level > gl::log2(caps.max3DTextureSize))
1158 {
1159 context->handleError(InvalidValue());
1160 return false;
1161 }
1162
1163 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1164 {
1165 context->handleError(InvalidValue());
1166 return false;
1167 }
1168 }
1169 break;
1170
1171 default:
1172 context->handleError(InvalidOperation());
1173 return false;
1174 }
1175
1176 const auto &format = tex->getFormat(tex->getTarget(), level);
1177 if (format.info->compressed)
1178 {
1179 context->handleError(InvalidOperation());
1180 return false;
1181 }
1182 }
1183
1184 return true;
1185 }
1186
ValidateInvalidateFramebuffer(Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments)1187 bool ValidateInvalidateFramebuffer(Context *context,
1188 GLenum target,
1189 GLsizei numAttachments,
1190 const GLenum *attachments)
1191 {
1192 if (context->getClientMajorVersion() < 3)
1193 {
1194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1195 return false;
1196 }
1197
1198 bool defaultFramebuffer = false;
1199
1200 switch (target)
1201 {
1202 case GL_DRAW_FRAMEBUFFER:
1203 case GL_FRAMEBUFFER:
1204 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1205 break;
1206 case GL_READ_FRAMEBUFFER:
1207 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1208 break;
1209 default:
1210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
1211 return false;
1212 }
1213
1214 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1215 defaultFramebuffer);
1216 }
1217
ValidateInvalidateSubFramebuffer(Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,GLint x,GLint y,GLsizei width,GLsizei height)1218 bool ValidateInvalidateSubFramebuffer(Context *context,
1219 GLenum target,
1220 GLsizei numAttachments,
1221 const GLenum *attachments,
1222 GLint x,
1223 GLint y,
1224 GLsizei width,
1225 GLsizei height)
1226 {
1227 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1228 }
1229
ValidateClearBuffer(ValidationContext * context)1230 bool ValidateClearBuffer(ValidationContext *context)
1231 {
1232 if (context->getClientMajorVersion() < 3)
1233 {
1234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1235 return false;
1236 }
1237
1238 if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
1239 {
1240 context->handleError(InvalidFramebufferOperation());
1241 return false;
1242 }
1243
1244 return true;
1245 }
1246
ValidateDrawRangeElements(Context * context,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const void * indices)1247 bool ValidateDrawRangeElements(Context *context,
1248 GLenum mode,
1249 GLuint start,
1250 GLuint end,
1251 GLsizei count,
1252 GLenum type,
1253 const void *indices)
1254 {
1255 if (context->getClientMajorVersion() < 3)
1256 {
1257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1258 return false;
1259 }
1260
1261 if (end < start)
1262 {
1263 context->handleError(InvalidValue() << "end < start");
1264 return false;
1265 }
1266
1267 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
1268 {
1269 return false;
1270 }
1271
1272 // Use the parameter buffer to retrieve and cache the index range.
1273 const auto ¶ms = context->getParams<HasIndexRange>();
1274 const auto &indexRangeOpt = params.getIndexRange();
1275 if (!indexRangeOpt.valid())
1276 {
1277 // Unexpected error.
1278 return false;
1279 }
1280
1281 if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
1282 {
1283 // GL spec says that behavior in this case is undefined - generating an error is fine.
1284 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
1285 return false;
1286 }
1287 return true;
1288 }
1289
ValidateGetUniformuiv(Context * context,GLuint program,GLint location,GLuint * params)1290 bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
1291 {
1292 if (context->getClientMajorVersion() < 3)
1293 {
1294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1295 return false;
1296 }
1297
1298 return ValidateGetUniformBase(context, program, location);
1299 }
1300
ValidateReadBuffer(Context * context,GLenum src)1301 bool ValidateReadBuffer(Context *context, GLenum src)
1302 {
1303 if (context->getClientMajorVersion() < 3)
1304 {
1305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1306 return false;
1307 }
1308
1309 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
1310
1311 if (readFBO == nullptr)
1312 {
1313 context->handleError(InvalidOperation() << "No active read framebuffer.");
1314 return false;
1315 }
1316
1317 if (src == GL_NONE)
1318 {
1319 return true;
1320 }
1321
1322 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
1323 {
1324 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
1325 return false;
1326 }
1327
1328 if (readFBO->id() == 0)
1329 {
1330 if (src != GL_BACK)
1331 {
1332 context->handleError(
1333 InvalidOperation()
1334 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
1335 return false;
1336 }
1337 }
1338 else
1339 {
1340 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1341
1342 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1343 {
1344 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
1345 return false;
1346 }
1347 }
1348
1349 return true;
1350 }
1351
ValidateCompressedTexImage3D(Context * context,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const void * data)1352 bool ValidateCompressedTexImage3D(Context *context,
1353 GLenum target,
1354 GLint level,
1355 GLenum internalformat,
1356 GLsizei width,
1357 GLsizei height,
1358 GLsizei depth,
1359 GLint border,
1360 GLsizei imageSize,
1361 const void *data)
1362 {
1363 if (context->getClientMajorVersion() < 3)
1364 {
1365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1366 return false;
1367 }
1368
1369 if (!ValidTextureTarget(context, target))
1370 {
1371 context->handleError(InvalidEnum());
1372 return false;
1373 }
1374
1375 // Validate image size
1376 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1377 {
1378 context->handleError(InvalidValue());
1379 return false;
1380 }
1381
1382 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
1383 if (!formatInfo.compressed)
1384 {
1385 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
1386 return false;
1387 }
1388
1389 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
1390 if (blockSizeOrErr.isError())
1391 {
1392 context->handleError(InvalidValue());
1393 return false;
1394 }
1395 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
1396 {
1397 context->handleError(InvalidValue());
1398 return false;
1399 }
1400
1401 // 3D texture target validation
1402 if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
1403 {
1404 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
1405 return false;
1406 }
1407
1408 // validateES3TexImageFormat sets the error code if there is an error
1409 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
1410 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1411 data))
1412 {
1413 return false;
1414 }
1415
1416 return true;
1417 }
1418
ValidateCompressedTexImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,GLsizei dataSize,const void * data)1419 bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
1420 GLenum target,
1421 GLint level,
1422 GLenum internalformat,
1423 GLsizei width,
1424 GLsizei height,
1425 GLsizei depth,
1426 GLint border,
1427 GLsizei imageSize,
1428 GLsizei dataSize,
1429 const void *data)
1430 {
1431 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1432 {
1433 return false;
1434 }
1435
1436 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1437 depth, border, imageSize, data);
1438 }
1439
ValidateBindVertexArray(Context * context,GLuint array)1440 bool ValidateBindVertexArray(Context *context, GLuint array)
1441 {
1442 if (context->getClientMajorVersion() < 3)
1443 {
1444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1445 return false;
1446 }
1447
1448 return ValidateBindVertexArrayBase(context, array);
1449 }
1450
ValidateIsVertexArray(Context * context,GLuint array)1451 bool ValidateIsVertexArray(Context *context, GLuint array)
1452 {
1453 if (context->getClientMajorVersion() < 3)
1454 {
1455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1456 return false;
1457 }
1458
1459 return true;
1460 }
1461
ValidateBindBufferCommon(Context * context,BufferBinding target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)1462 static bool ValidateBindBufferCommon(Context *context,
1463 BufferBinding target,
1464 GLuint index,
1465 GLuint buffer,
1466 GLintptr offset,
1467 GLsizeiptr size)
1468 {
1469 if (context->getClientMajorVersion() < 3)
1470 {
1471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1472 return false;
1473 }
1474
1475 if (buffer != 0 && offset < 0)
1476 {
1477 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
1478 return false;
1479 }
1480
1481 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1482 !context->isBufferGenerated(buffer))
1483 {
1484 context->handleError(InvalidOperation() << "Buffer was not generated.");
1485 return false;
1486 }
1487
1488 const Caps &caps = context->getCaps();
1489 switch (target)
1490 {
1491 case BufferBinding::TransformFeedback:
1492 {
1493 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1494 {
1495 context->handleError(InvalidValue() << "index is greater than or equal to the "
1496 "number of TRANSFORM_FEEDBACK_BUFFER "
1497 "indexed binding points.");
1498 return false;
1499 }
1500 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1501 {
1502 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
1503 return false;
1504 }
1505
1506 TransformFeedback *curTransformFeedback =
1507 context->getGLState().getCurrentTransformFeedback();
1508 if (curTransformFeedback && curTransformFeedback->isActive())
1509 {
1510 context->handleError(InvalidOperation()
1511 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1512 "feedback is currently active.");
1513 return false;
1514 }
1515 break;
1516 }
1517 case BufferBinding::Uniform:
1518 {
1519 if (index >= caps.maxUniformBufferBindings)
1520 {
1521 context->handleError(InvalidValue() << "index is greater than or equal to the "
1522 "number of UNIFORM_BUFFER indexed "
1523 "binding points.");
1524 return false;
1525 }
1526
1527 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1528 {
1529 context->handleError(
1530 InvalidValue()
1531 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
1532 return false;
1533 }
1534 break;
1535 }
1536 case BufferBinding::AtomicCounter:
1537 {
1538 if (context->getClientVersion() < ES_3_1)
1539 {
1540 context->handleError(InvalidEnum()
1541 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
1542 return false;
1543 }
1544 if (index >= caps.maxAtomicCounterBufferBindings)
1545 {
1546 context->handleError(InvalidValue() << "index is greater than or equal to the "
1547 "number of ATOMIC_COUNTER_BUFFER "
1548 "indexed binding points.");
1549 return false;
1550 }
1551 if (buffer != 0 && (offset % 4) != 0)
1552 {
1553 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
1554 return false;
1555 }
1556 break;
1557 }
1558 case BufferBinding::ShaderStorage:
1559 {
1560 if (context->getClientVersion() < ES_3_1)
1561 {
1562 context->handleError(InvalidEnum()
1563 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
1564 return false;
1565 }
1566 if (index >= caps.maxShaderStorageBufferBindings)
1567 {
1568 context->handleError(InvalidValue() << "index is greater than or equal to the "
1569 "number of SHADER_STORAGE_BUFFER "
1570 "indexed binding points.");
1571 return false;
1572 }
1573 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1574 {
1575 context->handleError(InvalidValue() << "offset must be multiple of value of "
1576 "SHADER_STORAGE_BUFFER_OFFSET_"
1577 "ALIGNMENT.");
1578 return false;
1579 }
1580 break;
1581 }
1582 default:
1583 context->handleError(InvalidEnum() << "the target is not supported.");
1584 return false;
1585 }
1586
1587 return true;
1588 }
1589
ValidateBindBufferBase(Context * context,BufferBinding target,GLuint index,GLuint buffer)1590 bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
1591 {
1592 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1593 }
1594
ValidateBindBufferRange(Context * context,BufferBinding target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size)1595 bool ValidateBindBufferRange(Context *context,
1596 BufferBinding target,
1597 GLuint index,
1598 GLuint buffer,
1599 GLintptr offset,
1600 GLsizeiptr size)
1601 {
1602 if (buffer != 0 && size <= 0)
1603 {
1604 context->handleError(InvalidValue()
1605 << "buffer is non-zero and size is less than or equal to zero.");
1606 return false;
1607 }
1608 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1609 }
1610
ValidateProgramBinary(Context * context,GLuint program,GLenum binaryFormat,const void * binary,GLint length)1611 bool ValidateProgramBinary(Context *context,
1612 GLuint program,
1613 GLenum binaryFormat,
1614 const void *binary,
1615 GLint length)
1616 {
1617 if (context->getClientMajorVersion() < 3)
1618 {
1619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1620 return false;
1621 }
1622
1623 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1624 }
1625
ValidateGetProgramBinary(Context * context,GLuint program,GLsizei bufSize,GLsizei * length,GLenum * binaryFormat,void * binary)1626 bool ValidateGetProgramBinary(Context *context,
1627 GLuint program,
1628 GLsizei bufSize,
1629 GLsizei *length,
1630 GLenum *binaryFormat,
1631 void *binary)
1632 {
1633 if (context->getClientMajorVersion() < 3)
1634 {
1635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1636 return false;
1637 }
1638
1639 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1640 }
1641
ValidateProgramParameteri(Context * context,GLuint program,GLenum pname,GLint value)1642 bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
1643 {
1644 if (context->getClientMajorVersion() < 3)
1645 {
1646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1647 return false;
1648 }
1649
1650 if (GetValidProgram(context, program) == nullptr)
1651 {
1652 return false;
1653 }
1654
1655 switch (pname)
1656 {
1657 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
1658 if (value != GL_FALSE && value != GL_TRUE)
1659 {
1660 context->handleError(InvalidValue()
1661 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
1662 return false;
1663 }
1664 break;
1665
1666 case GL_PROGRAM_SEPARABLE:
1667 if (context->getClientVersion() < ES_3_1)
1668 {
1669 context->handleError(InvalidEnum()
1670 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
1671 return false;
1672 }
1673
1674 if (value != GL_FALSE && value != GL_TRUE)
1675 {
1676 context->handleError(InvalidValue()
1677 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
1678 return false;
1679 }
1680 break;
1681
1682 default:
1683 context->handleError(InvalidEnum()
1684 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
1685 return false;
1686 }
1687
1688 return true;
1689 }
1690
ValidateBlitFramebuffer(Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1691 bool ValidateBlitFramebuffer(Context *context,
1692 GLint srcX0,
1693 GLint srcY0,
1694 GLint srcX1,
1695 GLint srcY1,
1696 GLint dstX0,
1697 GLint dstY0,
1698 GLint dstX1,
1699 GLint dstY1,
1700 GLbitfield mask,
1701 GLenum filter)
1702 {
1703 if (context->getClientMajorVersion() < 3)
1704 {
1705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1706 return false;
1707 }
1708
1709 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1710 dstX1, dstY1, mask, filter);
1711 }
1712
ValidateClearBufferiv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLint * value)1713 bool ValidateClearBufferiv(ValidationContext *context,
1714 GLenum buffer,
1715 GLint drawbuffer,
1716 const GLint *value)
1717 {
1718 switch (buffer)
1719 {
1720 case GL_COLOR:
1721 if (drawbuffer < 0 ||
1722 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1723 {
1724 context->handleError(InvalidValue());
1725 return false;
1726 }
1727 if (context->getExtensions().webglCompatibility)
1728 {
1729 constexpr GLenum validComponentTypes[] = {GL_INT};
1730 if (!ValidateWebGLFramebufferAttachmentClearType(
1731 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1732 {
1733 return false;
1734 }
1735 }
1736 break;
1737
1738 case GL_STENCIL:
1739 if (drawbuffer != 0)
1740 {
1741 context->handleError(InvalidValue());
1742 return false;
1743 }
1744 break;
1745
1746 default:
1747 context->handleError(InvalidEnum());
1748 return false;
1749 }
1750
1751 return ValidateClearBuffer(context);
1752 }
1753
ValidateClearBufferuiv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLuint * value)1754 bool ValidateClearBufferuiv(ValidationContext *context,
1755 GLenum buffer,
1756 GLint drawbuffer,
1757 const GLuint *value)
1758 {
1759 switch (buffer)
1760 {
1761 case GL_COLOR:
1762 if (drawbuffer < 0 ||
1763 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1764 {
1765 context->handleError(InvalidValue());
1766 return false;
1767 }
1768 if (context->getExtensions().webglCompatibility)
1769 {
1770 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
1771 if (!ValidateWebGLFramebufferAttachmentClearType(
1772 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1773 {
1774 return false;
1775 }
1776 }
1777 break;
1778
1779 default:
1780 context->handleError(InvalidEnum());
1781 return false;
1782 }
1783
1784 return ValidateClearBuffer(context);
1785 }
1786
ValidateClearBufferfv(ValidationContext * context,GLenum buffer,GLint drawbuffer,const GLfloat * value)1787 bool ValidateClearBufferfv(ValidationContext *context,
1788 GLenum buffer,
1789 GLint drawbuffer,
1790 const GLfloat *value)
1791 {
1792 switch (buffer)
1793 {
1794 case GL_COLOR:
1795 if (drawbuffer < 0 ||
1796 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1797 {
1798 context->handleError(InvalidValue());
1799 return false;
1800 }
1801 if (context->getExtensions().webglCompatibility)
1802 {
1803 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1804 GL_SIGNED_NORMALIZED};
1805 if (!ValidateWebGLFramebufferAttachmentClearType(
1806 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1807 {
1808 return false;
1809 }
1810 }
1811 break;
1812
1813 case GL_DEPTH:
1814 if (drawbuffer != 0)
1815 {
1816 context->handleError(InvalidValue());
1817 return false;
1818 }
1819 break;
1820
1821 default:
1822 context->handleError(InvalidEnum());
1823 return false;
1824 }
1825
1826 return ValidateClearBuffer(context);
1827 }
1828
ValidateClearBufferfi(ValidationContext * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)1829 bool ValidateClearBufferfi(ValidationContext *context,
1830 GLenum buffer,
1831 GLint drawbuffer,
1832 GLfloat depth,
1833 GLint stencil)
1834 {
1835 switch (buffer)
1836 {
1837 case GL_DEPTH_STENCIL:
1838 if (drawbuffer != 0)
1839 {
1840 context->handleError(InvalidValue());
1841 return false;
1842 }
1843 break;
1844
1845 default:
1846 context->handleError(InvalidEnum());
1847 return false;
1848 }
1849
1850 return ValidateClearBuffer(context);
1851 }
1852
ValidateDrawBuffers(ValidationContext * context,GLsizei n,const GLenum * bufs)1853 bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
1854 {
1855 if (context->getClientMajorVersion() < 3)
1856 {
1857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1858 return false;
1859 }
1860
1861 return ValidateDrawBuffersBase(context, n, bufs);
1862 }
1863
ValidateCopyTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)1864 bool ValidateCopyTexSubImage3D(Context *context,
1865 GLenum target,
1866 GLint level,
1867 GLint xoffset,
1868 GLint yoffset,
1869 GLint zoffset,
1870 GLint x,
1871 GLint y,
1872 GLsizei width,
1873 GLsizei height)
1874 {
1875 if (context->getClientMajorVersion() < 3)
1876 {
1877 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1878 return false;
1879 }
1880
1881 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
1882 yoffset, zoffset, x, y, width, height, 0);
1883 }
1884
ValidateTexImage3D(Context * context,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,const void * pixels)1885 bool ValidateTexImage3D(Context *context,
1886 GLenum target,
1887 GLint level,
1888 GLint internalformat,
1889 GLsizei width,
1890 GLsizei height,
1891 GLsizei depth,
1892 GLint border,
1893 GLenum format,
1894 GLenum type,
1895 const void *pixels)
1896 {
1897 if (context->getClientMajorVersion() < 3)
1898 {
1899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1900 return false;
1901 }
1902
1903 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1904 0, 0, width, height, depth, border, format, type, -1,
1905 pixels);
1906 }
1907
ValidateTexImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1908 bool ValidateTexImage3DRobustANGLE(Context *context,
1909 GLenum target,
1910 GLint level,
1911 GLint internalformat,
1912 GLsizei width,
1913 GLsizei height,
1914 GLsizei depth,
1915 GLint border,
1916 GLenum format,
1917 GLenum type,
1918 GLsizei bufSize,
1919 const void *pixels)
1920 {
1921 if (context->getClientMajorVersion() < 3)
1922 {
1923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1924 return false;
1925 }
1926
1927 if (!ValidateRobustEntryPoint(context, bufSize))
1928 {
1929 return false;
1930 }
1931
1932 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
1933 0, 0, width, height, depth, border, format, type,
1934 bufSize, pixels);
1935 }
1936
ValidateTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels)1937 bool ValidateTexSubImage3D(Context *context,
1938 GLenum target,
1939 GLint level,
1940 GLint xoffset,
1941 GLint yoffset,
1942 GLint zoffset,
1943 GLsizei width,
1944 GLsizei height,
1945 GLsizei depth,
1946 GLenum format,
1947 GLenum type,
1948 const void *pixels)
1949 {
1950 if (context->getClientMajorVersion() < 3)
1951 {
1952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1953 return false;
1954 }
1955
1956 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1957 yoffset, zoffset, width, height, depth, 0, format, type,
1958 -1, pixels);
1959 }
1960
ValidateTexSubImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1961 bool ValidateTexSubImage3DRobustANGLE(Context *context,
1962 GLenum target,
1963 GLint level,
1964 GLint xoffset,
1965 GLint yoffset,
1966 GLint zoffset,
1967 GLsizei width,
1968 GLsizei height,
1969 GLsizei depth,
1970 GLenum format,
1971 GLenum type,
1972 GLsizei bufSize,
1973 const void *pixels)
1974 {
1975 if (context->getClientMajorVersion() < 3)
1976 {
1977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
1978 return false;
1979 }
1980
1981 if (!ValidateRobustEntryPoint(context, bufSize))
1982 {
1983 return false;
1984 }
1985
1986 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
1987 yoffset, zoffset, width, height, depth, 0, format, type,
1988 bufSize, pixels);
1989 }
1990
ValidateCompressedTexSubImage3D(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const void * data)1991 bool ValidateCompressedTexSubImage3D(Context *context,
1992 GLenum target,
1993 GLint level,
1994 GLint xoffset,
1995 GLint yoffset,
1996 GLint zoffset,
1997 GLsizei width,
1998 GLsizei height,
1999 GLsizei depth,
2000 GLenum format,
2001 GLsizei imageSize,
2002 const void *data)
2003 {
2004 if (context->getClientMajorVersion() < 3)
2005 {
2006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2007 return false;
2008 }
2009
2010 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
2011 if (!formatInfo.compressed)
2012 {
2013 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
2014 return false;
2015 }
2016
2017 auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
2018 if (blockSizeOrErr.isError())
2019 {
2020 context->handleError(blockSizeOrErr.getError());
2021 return false;
2022 }
2023 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
2024 {
2025 context->handleError(InvalidValue());
2026 return false;
2027 }
2028
2029 if (!data)
2030 {
2031 context->handleError(InvalidValue());
2032 return false;
2033 }
2034
2035 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2036 yoffset, zoffset, width, height, depth, 0, format,
2037 GL_NONE, -1, data);
2038 }
ValidateCompressedTexSubImage3DRobustANGLE(Context * context,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,GLsizei dataSize,const void * data)2039 bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
2040 GLenum target,
2041 GLint level,
2042 GLint xoffset,
2043 GLint yoffset,
2044 GLint zoffset,
2045 GLsizei width,
2046 GLsizei height,
2047 GLsizei depth,
2048 GLenum format,
2049 GLsizei imageSize,
2050 GLsizei dataSize,
2051 const void *data)
2052 {
2053 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2054 {
2055 return false;
2056 }
2057
2058 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2059 height, depth, format, imageSize, data);
2060 }
2061
ValidateGenQueries(Context * context,GLint n,GLuint *)2062 bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2063 {
2064 return ValidateGenOrDeleteES3(context, n);
2065 }
2066
ValidateDeleteQueries(Context * context,GLint n,const GLuint *)2067 bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2068 {
2069 return ValidateGenOrDeleteES3(context, n);
2070 }
2071
ValidateGenSamplers(Context * context,GLint count,GLuint *)2072 bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2073 {
2074 return ValidateGenOrDeleteCountES3(context, count);
2075 }
2076
ValidateDeleteSamplers(Context * context,GLint count,const GLuint *)2077 bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2078 {
2079 return ValidateGenOrDeleteCountES3(context, count);
2080 }
2081
ValidateGenTransformFeedbacks(Context * context,GLint n,GLuint *)2082 bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2083 {
2084 return ValidateGenOrDeleteES3(context, n);
2085 }
2086
ValidateDeleteTransformFeedbacks(Context * context,GLint n,const GLuint * ids)2087 bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2088 {
2089 if (!ValidateGenOrDeleteES3(context, n))
2090 {
2091 return false;
2092 }
2093 for (GLint i = 0; i < n; ++i)
2094 {
2095 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2096 if (transformFeedback != nullptr && transformFeedback->isActive())
2097 {
2098 // ES 3.0.4 section 2.15.1 page 86
2099 context->handleError(InvalidOperation()
2100 << "Attempt to delete active transform feedback.");
2101 return false;
2102 }
2103 }
2104 return true;
2105 }
2106
ValidateGenVertexArrays(Context * context,GLint n,GLuint *)2107 bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2108 {
2109 return ValidateGenOrDeleteES3(context, n);
2110 }
2111
ValidateDeleteVertexArrays(Context * context,GLint n,const GLuint *)2112 bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2113 {
2114 return ValidateGenOrDeleteES3(context, n);
2115 }
2116
ValidateBeginTransformFeedback(Context * context,GLenum primitiveMode)2117 bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
2118 {
2119 if (context->getClientMajorVersion() < 3)
2120 {
2121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2122 return false;
2123 }
2124 switch (primitiveMode)
2125 {
2126 case GL_TRIANGLES:
2127 case GL_LINES:
2128 case GL_POINTS:
2129 break;
2130
2131 default:
2132 context->handleError(InvalidEnum() << "Invalid primitive mode.");
2133 return false;
2134 }
2135
2136 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2137 ASSERT(transformFeedback != nullptr);
2138
2139 if (transformFeedback->isActive())
2140 {
2141 context->handleError(InvalidOperation() << "Transform feedback is already active.");
2142 return false;
2143 }
2144
2145 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2146 {
2147 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2148 if (buffer.get() && buffer->isMapped())
2149 {
2150 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2151 return false;
2152 }
2153 }
2154
2155 Program *program = context->getGLState().getProgram();
2156
2157 if (!program)
2158 {
2159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2160 return false;
2161 }
2162
2163 if (program->getTransformFeedbackVaryingCount() == 0)
2164 {
2165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2166 return false;
2167 }
2168
2169 return true;
2170 }
2171
ValidateGetBufferPointerv(Context * context,BufferBinding target,GLenum pname,void ** params)2172 bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
2173 {
2174 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2175 }
2176
ValidateGetBufferPointervRobustANGLE(Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,GLsizei * length,void ** params)2177 bool ValidateGetBufferPointervRobustANGLE(Context *context,
2178 BufferBinding target,
2179 GLenum pname,
2180 GLsizei bufSize,
2181 GLsizei *length,
2182 void **params)
2183 {
2184 if (!ValidateRobustEntryPoint(context, bufSize))
2185 {
2186 return false;
2187 }
2188
2189 if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
2190 {
2191 return false;
2192 }
2193
2194 if (!ValidateRobustBufferSize(context, bufSize, *length))
2195 {
2196 return false;
2197 }
2198
2199 return true;
2200 }
2201
ValidateUnmapBuffer(Context * context,BufferBinding target)2202 bool ValidateUnmapBuffer(Context *context, BufferBinding target)
2203 {
2204 if (context->getClientMajorVersion() < 3)
2205 {
2206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2207 return false;
2208 }
2209
2210 return ValidateUnmapBufferBase(context, target);
2211 }
2212
ValidateMapBufferRange(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)2213 bool ValidateMapBufferRange(Context *context,
2214 BufferBinding target,
2215 GLintptr offset,
2216 GLsizeiptr length,
2217 GLbitfield access)
2218 {
2219 if (context->getClientMajorVersion() < 3)
2220 {
2221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2222 return false;
2223 }
2224
2225 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2226 }
2227
ValidateFlushMappedBufferRange(Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)2228 bool ValidateFlushMappedBufferRange(Context *context,
2229 BufferBinding target,
2230 GLintptr offset,
2231 GLsizeiptr length)
2232 {
2233 if (context->getClientMajorVersion() < 3)
2234 {
2235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2236 return false;
2237 }
2238
2239 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2240 }
2241
ValidateIndexedStateQuery(ValidationContext * context,GLenum pname,GLuint index,GLsizei * length)2242 bool ValidateIndexedStateQuery(ValidationContext *context,
2243 GLenum pname,
2244 GLuint index,
2245 GLsizei *length)
2246 {
2247 if (length)
2248 {
2249 *length = 0;
2250 }
2251
2252 GLenum nativeType;
2253 unsigned int numParams;
2254 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2255 {
2256 context->handleError(InvalidEnum());
2257 return false;
2258 }
2259
2260 const Caps &caps = context->getCaps();
2261 switch (pname)
2262 {
2263 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2264 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2265 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2266 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2267 {
2268 context->handleError(InvalidValue());
2269 return false;
2270 }
2271 break;
2272
2273 case GL_UNIFORM_BUFFER_START:
2274 case GL_UNIFORM_BUFFER_SIZE:
2275 case GL_UNIFORM_BUFFER_BINDING:
2276 if (index >= caps.maxUniformBufferBindings)
2277 {
2278 context->handleError(InvalidValue());
2279 return false;
2280 }
2281 break;
2282
2283 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2284 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2285 if (index >= 3u)
2286 {
2287 context->handleError(InvalidValue());
2288 return false;
2289 }
2290 break;
2291
2292 case GL_ATOMIC_COUNTER_BUFFER_START:
2293 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2294 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2295 if (context->getClientVersion() < ES_3_1)
2296 {
2297 context->handleError(
2298 InvalidEnum()
2299 << "Atomic Counter buffers are not supported in this version of GL");
2300 return false;
2301 }
2302 if (index >= caps.maxAtomicCounterBufferBindings)
2303 {
2304 context->handleError(
2305 InvalidValue()
2306 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
2307 return false;
2308 }
2309 break;
2310
2311 case GL_SHADER_STORAGE_BUFFER_START:
2312 case GL_SHADER_STORAGE_BUFFER_SIZE:
2313 case GL_SHADER_STORAGE_BUFFER_BINDING:
2314 if (context->getClientVersion() < ES_3_1)
2315 {
2316 context->handleError(
2317 InvalidEnum()
2318 << "Shader storage buffers are not supported in this version of GL");
2319 return false;
2320 }
2321 if (index >= caps.maxShaderStorageBufferBindings)
2322 {
2323 context->handleError(
2324 InvalidValue()
2325 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
2326 return false;
2327 }
2328 break;
2329
2330 case GL_VERTEX_BINDING_BUFFER:
2331 case GL_VERTEX_BINDING_DIVISOR:
2332 case GL_VERTEX_BINDING_OFFSET:
2333 case GL_VERTEX_BINDING_STRIDE:
2334 if (context->getClientVersion() < ES_3_1)
2335 {
2336 context->handleError(
2337 InvalidEnum()
2338 << "Vertex Attrib Bindings are not supported in this version of GL");
2339 return false;
2340 }
2341 if (index >= caps.maxVertexAttribBindings)
2342 {
2343 context->handleError(
2344 InvalidValue()
2345 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
2346 return false;
2347 }
2348 break;
2349 case GL_SAMPLE_MASK_VALUE:
2350 if (context->getClientVersion() < ES_3_1)
2351 {
2352 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2353 return false;
2354 }
2355 if (index >= caps.maxSampleMaskWords)
2356 {
2357 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2358 return false;
2359 }
2360 break;
2361 default:
2362 context->handleError(InvalidEnum());
2363 return false;
2364 }
2365
2366 if (length)
2367 {
2368 *length = 1;
2369 }
2370
2371 return true;
2372 }
2373
ValidateGetIntegeri_v(ValidationContext * context,GLenum target,GLuint index,GLint * data)2374 bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
2375 {
2376 if (context->getClientVersion() < ES_3_0)
2377 {
2378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2379 return false;
2380 }
2381 return ValidateIndexedStateQuery(context, target, index, nullptr);
2382 }
2383
ValidateGetIntegeri_vRobustANGLE(ValidationContext * context,GLenum target,GLuint index,GLsizei bufSize,GLsizei * length,GLint * data)2384 bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
2385 GLenum target,
2386 GLuint index,
2387 GLsizei bufSize,
2388 GLsizei *length,
2389 GLint *data)
2390 {
2391 if (context->getClientVersion() < ES_3_0)
2392 {
2393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2394 return false;
2395 }
2396
2397 if (!ValidateRobustEntryPoint(context, bufSize))
2398 {
2399 return false;
2400 }
2401
2402 if (!ValidateIndexedStateQuery(context, target, index, length))
2403 {
2404 return false;
2405 }
2406
2407 if (!ValidateRobustBufferSize(context, bufSize, *length))
2408 {
2409 return false;
2410 }
2411
2412 return true;
2413 }
2414
ValidateGetInteger64i_v(ValidationContext * context,GLenum target,GLuint index,GLint64 * data)2415 bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
2416 {
2417 if (context->getClientVersion() < ES_3_0)
2418 {
2419 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2420 return false;
2421 }
2422 return ValidateIndexedStateQuery(context, target, index, nullptr);
2423 }
2424
ValidateGetInteger64i_vRobustANGLE(ValidationContext * context,GLenum target,GLuint index,GLsizei bufSize,GLsizei * length,GLint64 * data)2425 bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
2426 GLenum target,
2427 GLuint index,
2428 GLsizei bufSize,
2429 GLsizei *length,
2430 GLint64 *data)
2431 {
2432 if (context->getClientVersion() < ES_3_0)
2433 {
2434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2435 return false;
2436 }
2437
2438 if (!ValidateRobustEntryPoint(context, bufSize))
2439 {
2440 return false;
2441 }
2442
2443 if (!ValidateIndexedStateQuery(context, target, index, length))
2444 {
2445 return false;
2446 }
2447
2448 if (!ValidateRobustBufferSize(context, bufSize, *length))
2449 {
2450 return false;
2451 }
2452
2453 return true;
2454 }
2455
ValidateCopyBufferSubData(ValidationContext * context,BufferBinding readTarget,BufferBinding writeTarget,GLintptr readOffset,GLintptr writeOffset,GLsizeiptr size)2456 bool ValidateCopyBufferSubData(ValidationContext *context,
2457 BufferBinding readTarget,
2458 BufferBinding writeTarget,
2459 GLintptr readOffset,
2460 GLintptr writeOffset,
2461 GLsizeiptr size)
2462 {
2463 if (context->getClientMajorVersion() < 3)
2464 {
2465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2466 return false;
2467 }
2468
2469 if (!ValidBufferType(context, readTarget) || !ValidBufferType(context, writeTarget))
2470 {
2471 context->handleError(InvalidEnum() << "Invalid buffer target");
2472 return false;
2473 }
2474
2475 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2476 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2477
2478 if (!readBuffer || !writeBuffer)
2479 {
2480 context->handleError(InvalidOperation() << "No buffer bound to target");
2481 return false;
2482 }
2483
2484 // Verify that readBuffer and writeBuffer are not currently mapped
2485 if (readBuffer->isMapped() || writeBuffer->isMapped())
2486 {
2487 context->handleError(InvalidOperation()
2488 << "Cannot call CopyBufferSubData on a mapped buffer");
2489 return false;
2490 }
2491
2492 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2493 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2494 CheckedNumeric<GLintptr> checkedSize(size);
2495
2496 auto checkedReadSum = checkedReadOffset + checkedSize;
2497 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2498
2499 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2500 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2501 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
2502 {
2503 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
2504 return false;
2505 }
2506
2507 if (readOffset < 0 || writeOffset < 0 || size < 0)
2508 {
2509 context->handleError(InvalidValue()
2510 << "readOffset, writeOffset and size must all be non-negative");
2511 return false;
2512 }
2513
2514 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2515 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2516 {
2517 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
2518 return false;
2519 }
2520
2521 if (readBuffer == writeBuffer)
2522 {
2523 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2524 if (!checkedOffsetDiff.IsValid())
2525 {
2526 // This shold not be possible.
2527 UNREACHABLE();
2528 context->handleError(InvalidValue()
2529 << "Integer overflow when validating same buffer copy.");
2530 return false;
2531 }
2532
2533 if (checkedOffsetDiff.ValueOrDie() < size)
2534 {
2535 context->handleError(InvalidValue());
2536 return false;
2537 }
2538 }
2539
2540 return true;
2541 }
2542
ValidateGetStringi(Context * context,GLenum name,GLuint index)2543 bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2544 {
2545 if (context->getClientMajorVersion() < 3)
2546 {
2547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2548 return false;
2549 }
2550
2551 switch (name)
2552 {
2553 case GL_EXTENSIONS:
2554 if (index >= context->getExtensionStringCount())
2555 {
2556 context->handleError(InvalidValue()
2557 << "index must be less than the number of extension strings.");
2558 return false;
2559 }
2560 break;
2561
2562 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2563 if (!context->getExtensions().requestExtension)
2564 {
2565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
2566 return false;
2567 }
2568 if (index >= context->getRequestableExtensionStringCount())
2569 {
2570 context->handleError(
2571 InvalidValue()
2572 << "index must be less than the number of requestable extension strings.");
2573 return false;
2574 }
2575 break;
2576
2577 default:
2578 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
2579 return false;
2580 }
2581
2582 return true;
2583 }
2584
ValidateRenderbufferStorageMultisample(ValidationContext * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)2585 bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
2586 GLenum target,
2587 GLsizei samples,
2588 GLenum internalformat,
2589 GLsizei width,
2590 GLsizei height)
2591 {
2592 if (context->getClientMajorVersion() < 3)
2593 {
2594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2595 return false;
2596 }
2597
2598 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2599 height))
2600 {
2601 return false;
2602 }
2603
2604 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
2605 // format if samples is greater than zero.
2606 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
2607 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
2608 samples > 0)
2609 {
2610 context->handleError(InvalidOperation());
2611 return false;
2612 }
2613
2614 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2615 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2616 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2617 {
2618 context->handleError(
2619 InvalidOperation()
2620 << "Samples must not be greater than maximum supported value for the format.");
2621 return false;
2622 }
2623
2624 return true;
2625 }
2626
ValidateVertexAttribIPointer(ValidationContext * context,GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer)2627 bool ValidateVertexAttribIPointer(ValidationContext *context,
2628 GLuint index,
2629 GLint size,
2630 GLenum type,
2631 GLsizei stride,
2632 const void *pointer)
2633 {
2634 if (context->getClientMajorVersion() < 3)
2635 {
2636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2637 return false;
2638 }
2639
2640 if (!ValidateVertexFormatBase(context, index, size, type, true))
2641 {
2642 return false;
2643 }
2644
2645 if (stride < 0)
2646 {
2647 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
2648 return false;
2649 }
2650
2651 const Caps &caps = context->getCaps();
2652 if (context->getClientVersion() >= ES_3_1)
2653 {
2654 if (stride > caps.maxVertexAttribStride)
2655 {
2656 context->handleError(InvalidValue()
2657 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
2658 return false;
2659 }
2660
2661 // [OpenGL ES 3.1] Section 10.3.1 page 245:
2662 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
2663 // validation should be inherited.
2664 if (index >= caps.maxVertexAttribBindings)
2665 {
2666 context->handleError(InvalidValue()
2667 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
2668 return false;
2669 }
2670 }
2671
2672 // [OpenGL ES 3.0.2] Section 2.8 page 24:
2673 // An INVALID_OPERATION error is generated when a non-zero vertex array object
2674 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
2675 // and the pointer argument is not NULL.
2676 if (context->getGLState().getVertexArrayId() != 0 &&
2677 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
2678 {
2679 context
2680 ->handleError(InvalidOperation()
2681 << "Client data cannot be used with a non-default vertex array object.");
2682 return false;
2683 }
2684
2685 if (context->getExtensions().webglCompatibility)
2686 {
2687 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
2688 {
2689 return false;
2690 }
2691 }
2692
2693 return true;
2694 }
2695
ValidateGetSynciv(Context * context,GLsync sync,GLenum pname,GLsizei bufSize,GLsizei * length,GLint * values)2696 bool ValidateGetSynciv(Context *context,
2697 GLsync sync,
2698 GLenum pname,
2699 GLsizei bufSize,
2700 GLsizei *length,
2701 GLint *values)
2702 {
2703 if (context->getClientMajorVersion() < 3)
2704 {
2705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2706 return false;
2707 }
2708
2709 if (bufSize < 0)
2710 {
2711 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
2712 return false;
2713 }
2714
2715 Sync *syncObject = context->getSync(sync);
2716 if (!syncObject)
2717 {
2718 context->handleError(InvalidValue() << "Invalid sync object.");
2719 return false;
2720 }
2721
2722 switch (pname)
2723 {
2724 case GL_OBJECT_TYPE:
2725 case GL_SYNC_CONDITION:
2726 case GL_SYNC_FLAGS:
2727 case GL_SYNC_STATUS:
2728 break;
2729
2730 default:
2731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
2732 return false;
2733 }
2734
2735 return true;
2736 }
2737
ValidateDrawElementsInstanced(ValidationContext * context,GLenum mode,GLsizei count,GLenum type,const void * indices,GLsizei instanceCount)2738 bool ValidateDrawElementsInstanced(ValidationContext *context,
2739 GLenum mode,
2740 GLsizei count,
2741 GLenum type,
2742 const void *indices,
2743 GLsizei instanceCount)
2744 {
2745 if (context->getClientMajorVersion() < 3)
2746 {
2747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2748 return false;
2749 }
2750
2751 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
2752 }
2753
ValidateFramebufferTextureMultiviewLayeredANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLint baseViewIndex,GLsizei numViews)2754 bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
2755 GLenum target,
2756 GLenum attachment,
2757 GLuint texture,
2758 GLint level,
2759 GLint baseViewIndex,
2760 GLsizei numViews)
2761 {
2762
2763 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2764 numViews))
2765 {
2766 return false;
2767 }
2768
2769 if (texture != 0)
2770 {
2771 if (baseViewIndex < 0)
2772 {
2773 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
2774 return false;
2775 }
2776
2777 Texture *tex = context->getTexture(texture);
2778 ASSERT(tex);
2779
2780 switch (tex->getTarget())
2781 {
2782 case GL_TEXTURE_2D_ARRAY:
2783 {
2784 const Caps &caps = context->getCaps();
2785 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
2786 {
2787 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
2788 "greater than "
2789 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
2790 return false;
2791 }
2792 }
2793 break;
2794 default:
2795 context->handleError(InvalidOperation()
2796 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
2797 return false;
2798 }
2799
2800 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2801 {
2802 return false;
2803 }
2804 }
2805
2806 return true;
2807 }
2808
ValidateFramebufferTextureMultiviewSideBySideANGLE(Context * context,GLenum target,GLenum attachment,GLuint texture,GLint level,GLsizei numViews,const GLint * viewportOffsets)2809 bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
2810 GLenum target,
2811 GLenum attachment,
2812 GLuint texture,
2813 GLint level,
2814 GLsizei numViews,
2815 const GLint *viewportOffsets)
2816 {
2817 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
2818 numViews))
2819 {
2820 return false;
2821 }
2822
2823 if (texture != 0)
2824 {
2825 const GLsizei numViewportOffsetValues = numViews * 2;
2826 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
2827 {
2828 if (viewportOffsets[i] < 0)
2829 {
2830 context->handleError(InvalidValue()
2831 << "viewportOffsets cannot contain negative values.");
2832 return false;
2833 }
2834 }
2835
2836 Texture *tex = context->getTexture(texture);
2837 ASSERT(tex);
2838
2839 switch (tex->getTarget())
2840 {
2841 case GL_TEXTURE_2D:
2842 break;
2843 default:
2844 context->handleError(InvalidOperation()
2845 << "Texture's target must be GL_TEXTURE_2D.");
2846 return false;
2847 }
2848
2849 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
2850 {
2851 return false;
2852 }
2853 }
2854
2855 return true;
2856 }
2857
ValidateUniform1ui(Context * context,GLint location,GLuint v0)2858 bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
2859 {
2860 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
2861 }
2862
ValidateUniform2ui(Context * context,GLint location,GLuint v0,GLuint v1)2863 bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
2864 {
2865 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
2866 }
2867
ValidateUniform3ui(Context * context,GLint location,GLuint v0,GLuint v1,GLuint v2)2868 bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
2869 {
2870 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
2871 }
2872
ValidateUniform4ui(Context * context,GLint location,GLuint v0,GLuint v1,GLuint v2,GLuint v3)2873 bool ValidateUniform4ui(Context *context,
2874 GLint location,
2875 GLuint v0,
2876 GLuint v1,
2877 GLuint v2,
2878 GLuint v3)
2879 {
2880 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
2881 }
2882
ValidateUniform1uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2883 bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2884 {
2885 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
2886 }
2887
ValidateUniform2uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2888 bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2889 {
2890 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
2891 }
2892
ValidateUniform3uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2893 bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2894 {
2895 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
2896 }
2897
ValidateUniform4uiv(Context * context,GLint location,GLsizei count,const GLuint * value)2898 bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
2899 {
2900 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
2901 }
2902
ValidateIsQuery(Context * context,GLuint id)2903 bool ValidateIsQuery(Context *context, GLuint id)
2904 {
2905 if (context->getClientMajorVersion() < 3)
2906 {
2907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2908 return false;
2909 }
2910
2911 return true;
2912 }
2913
ValidateUniformMatrix2x3fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2914 bool ValidateUniformMatrix2x3fv(Context *context,
2915 GLint location,
2916 GLsizei count,
2917 GLboolean transpose,
2918 const GLfloat *value)
2919 {
2920 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
2921 }
2922
ValidateUniformMatrix3x2fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2923 bool ValidateUniformMatrix3x2fv(Context *context,
2924 GLint location,
2925 GLsizei count,
2926 GLboolean transpose,
2927 const GLfloat *value)
2928 {
2929 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
2930 }
2931
ValidateUniformMatrix2x4fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2932 bool ValidateUniformMatrix2x4fv(Context *context,
2933 GLint location,
2934 GLsizei count,
2935 GLboolean transpose,
2936 const GLfloat *value)
2937 {
2938 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
2939 }
2940
ValidateUniformMatrix4x2fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2941 bool ValidateUniformMatrix4x2fv(Context *context,
2942 GLint location,
2943 GLsizei count,
2944 GLboolean transpose,
2945 const GLfloat *value)
2946 {
2947 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
2948 }
2949
ValidateUniformMatrix3x4fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2950 bool ValidateUniformMatrix3x4fv(Context *context,
2951 GLint location,
2952 GLsizei count,
2953 GLboolean transpose,
2954 const GLfloat *value)
2955 {
2956 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
2957 }
2958
ValidateUniformMatrix4x3fv(Context * context,GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2959 bool ValidateUniformMatrix4x3fv(Context *context,
2960 GLint location,
2961 GLsizei count,
2962 GLboolean transpose,
2963 const GLfloat *value)
2964 {
2965 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
2966 }
2967
ValidateEndTransformFeedback(Context * context)2968 bool ValidateEndTransformFeedback(Context *context)
2969 {
2970 if (context->getClientMajorVersion() < 3)
2971 {
2972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2973 return false;
2974 }
2975
2976 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
2977 ASSERT(transformFeedback != nullptr);
2978
2979 if (!transformFeedback->isActive())
2980 {
2981 context->handleError(InvalidOperation());
2982 return false;
2983 }
2984
2985 return true;
2986 }
2987
ValidateTransformFeedbackVaryings(Context * context,GLuint program,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2988 bool ValidateTransformFeedbackVaryings(Context *context,
2989 GLuint program,
2990 GLsizei count,
2991 const GLchar *const *varyings,
2992 GLenum bufferMode)
2993 {
2994 if (context->getClientMajorVersion() < 3)
2995 {
2996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
2997 return false;
2998 }
2999
3000 if (count < 0)
3001 {
3002 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3003 return false;
3004 }
3005
3006 switch (bufferMode)
3007 {
3008 case GL_INTERLEAVED_ATTRIBS:
3009 break;
3010 case GL_SEPARATE_ATTRIBS:
3011 {
3012 const Caps &caps = context->getCaps();
3013 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3014 {
3015 context->handleError(InvalidValue());
3016 return false;
3017 }
3018 break;
3019 }
3020 default:
3021 context->handleError(InvalidEnum());
3022 return false;
3023 }
3024
3025 Program *programObject = GetValidProgram(context, program);
3026 if (!programObject)
3027 {
3028 return false;
3029 }
3030
3031 return true;
3032 }
3033
ValidateGetTransformFeedbackVarying(Context * context,GLuint program,GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name)3034 bool ValidateGetTransformFeedbackVarying(Context *context,
3035 GLuint program,
3036 GLuint index,
3037 GLsizei bufSize,
3038 GLsizei *length,
3039 GLsizei *size,
3040 GLenum *type,
3041 GLchar *name)
3042 {
3043 if (context->getClientMajorVersion() < 3)
3044 {
3045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3046 return false;
3047 }
3048
3049 if (bufSize < 0)
3050 {
3051 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3052 return false;
3053 }
3054
3055 Program *programObject = GetValidProgram(context, program);
3056 if (!programObject)
3057 {
3058 return false;
3059 }
3060
3061 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3062 {
3063 context->handleError(InvalidValue());
3064 return false;
3065 }
3066
3067 return true;
3068 }
3069
ValidateBindTransformFeedback(Context * context,GLenum target,GLuint id)3070 bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3071 {
3072 if (context->getClientMajorVersion() < 3)
3073 {
3074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3075 return false;
3076 }
3077
3078 switch (target)
3079 {
3080 case GL_TRANSFORM_FEEDBACK:
3081 {
3082 // Cannot bind a transform feedback object if the current one is started and not
3083 // paused (3.0.2 pg 85 section 2.14.1)
3084 TransformFeedback *curTransformFeedback =
3085 context->getGLState().getCurrentTransformFeedback();
3086 if (curTransformFeedback && curTransformFeedback->isActive() &&
3087 !curTransformFeedback->isPaused())
3088 {
3089 context->handleError(InvalidOperation());
3090 return false;
3091 }
3092
3093 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3094 // 2.14.1)
3095 if (!context->isTransformFeedbackGenerated(id))
3096 {
3097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3098 return false;
3099 }
3100 }
3101 break;
3102
3103 default:
3104 context->handleError(InvalidEnum());
3105 return false;
3106 }
3107
3108 return true;
3109 }
3110
ValidateIsTransformFeedback(Context * context,GLuint id)3111 bool ValidateIsTransformFeedback(Context *context, GLuint id)
3112 {
3113 if (context->getClientMajorVersion() < 3)
3114 {
3115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3116 return false;
3117 }
3118
3119 return true;
3120 }
3121
ValidatePauseTransformFeedback(Context * context)3122 bool ValidatePauseTransformFeedback(Context *context)
3123 {
3124 if (context->getClientMajorVersion() < 3)
3125 {
3126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3127 return false;
3128 }
3129
3130 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3131 ASSERT(transformFeedback != nullptr);
3132
3133 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3134 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3135 {
3136 context->handleError(InvalidOperation());
3137 return false;
3138 }
3139
3140 return true;
3141 }
3142
ValidateResumeTransformFeedback(Context * context)3143 bool ValidateResumeTransformFeedback(Context *context)
3144 {
3145 if (context->getClientMajorVersion() < 3)
3146 {
3147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3148 return false;
3149 }
3150
3151 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3152 ASSERT(transformFeedback != nullptr);
3153
3154 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3155 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3156 {
3157 context->handleError(InvalidOperation());
3158 return false;
3159 }
3160
3161 return true;
3162 }
3163
ValidateVertexAttribI4i(Context * context,GLuint index,GLint x,GLint y,GLint z,GLint w)3164 bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3165 {
3166 if (context->getClientMajorVersion() < 3)
3167 {
3168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3169 return false;
3170 }
3171
3172 return ValidateVertexAttribIndex(context, index);
3173 }
3174
ValidateVertexAttribI4ui(Context * context,GLuint index,GLuint x,GLuint y,GLuint z,GLuint w)3175 bool ValidateVertexAttribI4ui(Context *context,
3176 GLuint index,
3177 GLuint x,
3178 GLuint y,
3179 GLuint z,
3180 GLuint w)
3181 {
3182 if (context->getClientMajorVersion() < 3)
3183 {
3184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3185 return false;
3186 }
3187
3188 return ValidateVertexAttribIndex(context, index);
3189 }
3190
ValidateVertexAttribI4iv(Context * context,GLuint index,const GLint * v)3191 bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3192 {
3193 if (context->getClientMajorVersion() < 3)
3194 {
3195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3196 return false;
3197 }
3198
3199 return ValidateVertexAttribIndex(context, index);
3200 }
3201
ValidateVertexAttribI4uiv(Context * context,GLuint index,const GLuint * v)3202 bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3203 {
3204 if (context->getClientMajorVersion() < 3)
3205 {
3206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3207 return false;
3208 }
3209
3210 return ValidateVertexAttribIndex(context, index);
3211 }
3212
ValidateGetFragDataLocation(Context * context,GLuint program,const GLchar * name)3213 bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3214 {
3215 if (context->getClientMajorVersion() < 3)
3216 {
3217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3218 return false;
3219 }
3220
3221 Program *programObject = GetValidProgram(context, program);
3222 if (!programObject)
3223 {
3224 return false;
3225 }
3226
3227 if (!programObject->isLinked())
3228 {
3229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3230 return false;
3231 }
3232
3233 return true;
3234 }
3235
ValidateGetUniformIndices(Context * context,GLuint program,GLsizei uniformCount,const GLchar * const * uniformNames,GLuint * uniformIndices)3236 bool ValidateGetUniformIndices(Context *context,
3237 GLuint program,
3238 GLsizei uniformCount,
3239 const GLchar *const *uniformNames,
3240 GLuint *uniformIndices)
3241 {
3242 if (context->getClientMajorVersion() < 3)
3243 {
3244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3245 return false;
3246 }
3247
3248 if (uniformCount < 0)
3249 {
3250 context->handleError(InvalidValue());
3251 return false;
3252 }
3253
3254 Program *programObject = GetValidProgram(context, program);
3255 if (!programObject)
3256 {
3257 return false;
3258 }
3259
3260 return true;
3261 }
3262
ValidateGetActiveUniformsiv(Context * context,GLuint program,GLsizei uniformCount,const GLuint * uniformIndices,GLenum pname,GLint * params)3263 bool ValidateGetActiveUniformsiv(Context *context,
3264 GLuint program,
3265 GLsizei uniformCount,
3266 const GLuint *uniformIndices,
3267 GLenum pname,
3268 GLint *params)
3269 {
3270 if (context->getClientMajorVersion() < 3)
3271 {
3272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3273 return false;
3274 }
3275
3276 if (uniformCount < 0)
3277 {
3278 context->handleError(InvalidValue());
3279 return false;
3280 }
3281
3282 Program *programObject = GetValidProgram(context, program);
3283 if (!programObject)
3284 {
3285 return false;
3286 }
3287
3288 switch (pname)
3289 {
3290 case GL_UNIFORM_TYPE:
3291 case GL_UNIFORM_SIZE:
3292 case GL_UNIFORM_NAME_LENGTH:
3293 case GL_UNIFORM_BLOCK_INDEX:
3294 case GL_UNIFORM_OFFSET:
3295 case GL_UNIFORM_ARRAY_STRIDE:
3296 case GL_UNIFORM_MATRIX_STRIDE:
3297 case GL_UNIFORM_IS_ROW_MAJOR:
3298 break;
3299
3300 default:
3301 context->handleError(InvalidEnum());
3302 return false;
3303 }
3304
3305 if (uniformCount > programObject->getActiveUniformCount())
3306 {
3307 context->handleError(InvalidValue());
3308 return false;
3309 }
3310
3311 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3312 {
3313 const GLuint index = uniformIndices[uniformId];
3314
3315 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3316 {
3317 context->handleError(InvalidValue());
3318 return false;
3319 }
3320 }
3321
3322 return true;
3323 }
3324
ValidateGetUniformBlockIndex(Context * context,GLuint program,const GLchar * uniformBlockName)3325 bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3326 {
3327 if (context->getClientMajorVersion() < 3)
3328 {
3329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3330 return false;
3331 }
3332
3333 Program *programObject = GetValidProgram(context, program);
3334 if (!programObject)
3335 {
3336 return false;
3337 }
3338
3339 return true;
3340 }
3341
ValidateGetActiveUniformBlockiv(Context * context,GLuint program,GLuint uniformBlockIndex,GLenum pname,GLint * params)3342 bool ValidateGetActiveUniformBlockiv(Context *context,
3343 GLuint program,
3344 GLuint uniformBlockIndex,
3345 GLenum pname,
3346 GLint *params)
3347 {
3348 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3349 }
3350
ValidateGetActiveUniformBlockName(Context * context,GLuint program,GLuint uniformBlockIndex,GLsizei bufSize,GLsizei * length,GLchar * uniformBlockName)3351 bool ValidateGetActiveUniformBlockName(Context *context,
3352 GLuint program,
3353 GLuint uniformBlockIndex,
3354 GLsizei bufSize,
3355 GLsizei *length,
3356 GLchar *uniformBlockName)
3357 {
3358 if (context->getClientMajorVersion() < 3)
3359 {
3360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3361 return false;
3362 }
3363
3364 Program *programObject = GetValidProgram(context, program);
3365 if (!programObject)
3366 {
3367 return false;
3368 }
3369
3370 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3371 {
3372 context->handleError(InvalidValue());
3373 return false;
3374 }
3375
3376 return true;
3377 }
3378
ValidateUniformBlockBinding(Context * context,GLuint program,GLuint uniformBlockIndex,GLuint uniformBlockBinding)3379 bool ValidateUniformBlockBinding(Context *context,
3380 GLuint program,
3381 GLuint uniformBlockIndex,
3382 GLuint uniformBlockBinding)
3383 {
3384 if (context->getClientMajorVersion() < 3)
3385 {
3386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3387 return false;
3388 }
3389
3390 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3391 {
3392 context->handleError(InvalidValue());
3393 return false;
3394 }
3395
3396 Program *programObject = GetValidProgram(context, program);
3397 if (!programObject)
3398 {
3399 return false;
3400 }
3401
3402 // if never linked, there won't be any uniform blocks
3403 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3404 {
3405 context->handleError(InvalidValue());
3406 return false;
3407 }
3408
3409 return true;
3410 }
3411
ValidateDrawArraysInstanced(Context * context,GLenum mode,GLint first,GLsizei count,GLsizei primcount)3412 bool ValidateDrawArraysInstanced(Context *context,
3413 GLenum mode,
3414 GLint first,
3415 GLsizei count,
3416 GLsizei primcount)
3417 {
3418 if (context->getClientMajorVersion() < 3)
3419 {
3420 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3421 return false;
3422 }
3423
3424 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3425 }
3426
ValidateFenceSync(Context * context,GLenum condition,GLbitfield flags)3427 bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3428 {
3429 if (context->getClientMajorVersion() < 3)
3430 {
3431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3432 return false;
3433 }
3434
3435 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3436 {
3437 context->handleError(InvalidEnum());
3438 return false;
3439 }
3440
3441 if (flags != 0)
3442 {
3443 context->handleError(InvalidValue());
3444 return false;
3445 }
3446
3447 return true;
3448 }
3449
ValidateIsSync(Context * context,GLsync sync)3450 bool ValidateIsSync(Context *context, GLsync sync)
3451 {
3452 if (context->getClientMajorVersion() < 3)
3453 {
3454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3455 return false;
3456 }
3457
3458 return true;
3459 }
3460
ValidateDeleteSync(Context * context,GLsync sync)3461 bool ValidateDeleteSync(Context *context, GLsync sync)
3462 {
3463 if (context->getClientMajorVersion() < 3)
3464 {
3465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3466 return false;
3467 }
3468
3469 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
3470 {
3471 context->handleError(InvalidValue());
3472 return false;
3473 }
3474
3475 return true;
3476 }
3477
ValidateClientWaitSync(Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)3478 bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3479 {
3480 if (context->getClientMajorVersion() < 3)
3481 {
3482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3483 return false;
3484 }
3485
3486 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3487 {
3488 context->handleError(InvalidValue());
3489 return false;
3490 }
3491
3492 Sync *clientWaitSync = context->getSync(sync);
3493 if (!clientWaitSync)
3494 {
3495 context->handleError(InvalidValue());
3496 return false;
3497 }
3498
3499 return true;
3500 }
3501
ValidateWaitSync(Context * context,GLsync sync,GLbitfield flags,GLuint64 timeout)3502 bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3503 {
3504 if (context->getClientMajorVersion() < 3)
3505 {
3506 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3507 return false;
3508 }
3509
3510 if (flags != 0)
3511 {
3512 context->handleError(InvalidValue());
3513 return false;
3514 }
3515
3516 if (timeout != GL_TIMEOUT_IGNORED)
3517 {
3518 context->handleError(InvalidValue());
3519 return false;
3520 }
3521
3522 Sync *waitSync = context->getSync(sync);
3523 if (!waitSync)
3524 {
3525 context->handleError(InvalidValue());
3526 return false;
3527 }
3528
3529 return true;
3530 }
3531
ValidateGetInteger64v(Context * context,GLenum pname,GLint64 * params)3532 bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3533 {
3534 if (context->getClientMajorVersion() < 3)
3535 {
3536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3537 return false;
3538 }
3539
3540 GLenum nativeType = GL_NONE;
3541 unsigned int numParams = 0;
3542 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3543 {
3544 return false;
3545 }
3546
3547 return true;
3548 }
3549
ValidateIsSampler(Context * context,GLuint sampler)3550 bool ValidateIsSampler(Context *context, GLuint sampler)
3551 {
3552 if (context->getClientMajorVersion() < 3)
3553 {
3554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3555 return false;
3556 }
3557
3558 return true;
3559 }
3560
ValidateBindSampler(Context * context,GLuint unit,GLuint sampler)3561 bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
3562 {
3563 if (context->getClientMajorVersion() < 3)
3564 {
3565 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3566 return false;
3567 }
3568
3569 if (sampler != 0 && !context->isSampler(sampler))
3570 {
3571 context->handleError(InvalidOperation());
3572 return false;
3573 }
3574
3575 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
3576 {
3577 context->handleError(InvalidValue());
3578 return false;
3579 }
3580
3581 return true;
3582 }
3583
ValidateVertexAttribDivisor(Context * context,GLuint index,GLuint divisor)3584 bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
3585 {
3586 if (context->getClientMajorVersion() < 3)
3587 {
3588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3589 return false;
3590 }
3591
3592 return ValidateVertexAttribIndex(context, index);
3593 }
3594
ValidateTexStorage2D(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height)3595 bool ValidateTexStorage2D(Context *context,
3596 GLenum target,
3597 GLsizei levels,
3598 GLenum internalformat,
3599 GLsizei width,
3600 GLsizei height)
3601 {
3602 if (context->getClientMajorVersion() < 3)
3603 {
3604 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3605 return false;
3606 }
3607
3608 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
3609 1))
3610 {
3611 return false;
3612 }
3613
3614 return true;
3615 }
3616
ValidateTexStorage3D(Context * context,GLenum target,GLsizei levels,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)3617 bool ValidateTexStorage3D(Context *context,
3618 GLenum target,
3619 GLsizei levels,
3620 GLenum internalformat,
3621 GLsizei width,
3622 GLsizei height,
3623 GLsizei depth)
3624 {
3625 if (context->getClientMajorVersion() < 3)
3626 {
3627 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3628 return false;
3629 }
3630
3631 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
3632 depth))
3633 {
3634 return false;
3635 }
3636
3637 return true;
3638 }
3639
ValidateGetBufferParameteri64v(ValidationContext * context,BufferBinding target,GLenum pname,GLint64 * params)3640 bool ValidateGetBufferParameteri64v(ValidationContext *context,
3641 BufferBinding target,
3642 GLenum pname,
3643 GLint64 *params)
3644 {
3645 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
3646 }
3647
ValidateGetSamplerParameterfv(Context * context,GLuint sampler,GLenum pname,GLfloat * params)3648 bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
3649 {
3650 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3651 }
3652
ValidateGetSamplerParameteriv(Context * context,GLuint sampler,GLenum pname,GLint * params)3653 bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
3654 {
3655 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
3656 }
3657
ValidateSamplerParameterf(Context * context,GLuint sampler,GLenum pname,GLfloat param)3658 bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
3659 {
3660 return ValidateSamplerParameterBase(context, sampler, pname, -1, ¶m);
3661 }
3662
ValidateSamplerParameterfv(Context * context,GLuint sampler,GLenum pname,const GLfloat * params)3663 bool ValidateSamplerParameterfv(Context *context,
3664 GLuint sampler,
3665 GLenum pname,
3666 const GLfloat *params)
3667 {
3668 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3669 }
3670
ValidateSamplerParameteri(Context * context,GLuint sampler,GLenum pname,GLint param)3671 bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
3672 {
3673 return ValidateSamplerParameterBase(context, sampler, pname, -1, ¶m);
3674 }
3675
ValidateSamplerParameteriv(Context * context,GLuint sampler,GLenum pname,const GLint * params)3676 bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
3677 {
3678 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
3679 }
3680
ValidateGetVertexAttribIiv(Context * context,GLuint index,GLenum pname,GLint * params)3681 bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
3682 {
3683 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3684 }
3685
ValidateGetVertexAttribIuiv(Context * context,GLuint index,GLenum pname,GLuint * params)3686 bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
3687 {
3688 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
3689 }
3690
ValidateGetInternalformativ(Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLint * params)3691 bool ValidateGetInternalformativ(Context *context,
3692 GLenum target,
3693 GLenum internalformat,
3694 GLenum pname,
3695 GLsizei bufSize,
3696 GLint *params)
3697 {
3698 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
3699 nullptr);
3700 }
3701
3702 } // namespace gl
3703