1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
9 #include "libANGLE/validationES.h"
10
11 #include "libANGLE/Context.h"
12 #include "libANGLE/Display.h"
13 #include "libANGLE/ErrorStrings.h"
14 #include "libANGLE/Framebuffer.h"
15 #include "libANGLE/FramebufferAttachment.h"
16 #include "libANGLE/Image.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/Query.h"
19 #include "libANGLE/Texture.h"
20 #include "libANGLE/TransformFeedback.h"
21 #include "libANGLE/angletypes.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/queryconversions.h"
24 #include "libANGLE/queryutils.h"
25 #include "libANGLE/validationES2.h"
26 #include "libANGLE/validationES3.h"
27
28 #include "common/mathutil.h"
29 #include "common/utilities.h"
30
31 using namespace angle;
32
33 namespace gl
34 {
35 using namespace err;
36
37 namespace
38 {
CompressedTextureFormatRequiresExactSize(GLenum internalFormat)39 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
40 {
41 // List of compressed format that require that the texture size is smaller than or a multiple of
42 // the compressed block size.
43 switch (internalFormat)
44 {
45 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
48 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
49 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
52 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
53 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
54 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
58 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
60 case GL_COMPRESSED_RED_RGTC1_EXT:
61 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
62 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
63 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
64 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
65 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
66 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
67 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
68 return true;
69
70 default:
71 return false;
72 }
73 }
CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)74 bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
75 {
76 // Compressed sub textures have additional formats that requires exact size.
77 // ES 3.1, Section 8.7, Page 171
78 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
79 IsETC2EACFormat(internalFormat);
80 }
81
DifferenceCanOverflow(GLint a,GLint b)82 bool DifferenceCanOverflow(GLint a, GLint b)
83 {
84 CheckedNumeric<GLint> checkedA(a);
85 checkedA -= b;
86 // Use negation to make sure that the difference can't overflow regardless of the order.
87 checkedA = -checkedA;
88 return !checkedA.IsValid();
89 }
90
ValidReadPixelsTypeEnum(const Context * context,GLenum type)91 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
92 {
93 switch (type)
94 {
95 // Types referenced in Table 3.4 of the ES 2.0.25 spec
96 case GL_UNSIGNED_BYTE:
97 case GL_UNSIGNED_SHORT_4_4_4_4:
98 case GL_UNSIGNED_SHORT_5_5_5_1:
99 case GL_UNSIGNED_SHORT_5_6_5:
100 return context->getClientVersion() >= ES_2_0;
101
102 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
103 case GL_BYTE:
104 case GL_INT:
105 case GL_SHORT:
106 case GL_UNSIGNED_INT:
107 case GL_UNSIGNED_INT_10F_11F_11F_REV:
108 case GL_UNSIGNED_INT_24_8:
109 case GL_UNSIGNED_INT_2_10_10_10_REV:
110 case GL_UNSIGNED_INT_5_9_9_9_REV:
111 case GL_UNSIGNED_SHORT:
112 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
113 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
114 return context->getClientVersion() >= ES_3_0;
115
116 case GL_FLOAT:
117 return context->getClientVersion() >= ES_3_0 ||
118 context->getExtensions().textureFloatOES ||
119 context->getExtensions().colorBufferHalfFloat;
120
121 case GL_HALF_FLOAT:
122 return context->getClientVersion() >= ES_3_0 ||
123 context->getExtensions().textureHalfFloat;
124
125 case GL_HALF_FLOAT_OES:
126 return context->getExtensions().colorBufferHalfFloat;
127
128 default:
129 return false;
130 }
131 }
132
ValidReadPixelsFormatEnum(const Context * context,GLenum format)133 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
134 {
135 switch (format)
136 {
137 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
138 case GL_RGBA:
139 case GL_RGB:
140 case GL_ALPHA:
141 return context->getClientVersion() >= ES_2_0;
142
143 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
144 case GL_RG:
145 case GL_RED:
146 case GL_RGBA_INTEGER:
147 case GL_RGB_INTEGER:
148 case GL_RG_INTEGER:
149 case GL_RED_INTEGER:
150 return context->getClientVersion() >= ES_3_0;
151
152 case GL_SRGB_ALPHA_EXT:
153 case GL_SRGB_EXT:
154 return context->getExtensions().sRGB;
155
156 case GL_BGRA_EXT:
157 return context->getExtensions().readFormatBGRA;
158
159 default:
160 return false;
161 }
162 }
163
ValidReadPixelsUnsignedNormalizedDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)164 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
165 const gl::InternalFormat *info,
166 GLenum type)
167 {
168 bool supportsReadDepthNV = (context->getExtensions().readDepthNV && (info->depthBits > 0) &&
169 (info->componentCount == 1));
170 switch (type)
171 {
172 case GL_UNSIGNED_SHORT:
173 case GL_UNSIGNED_INT:
174 case GL_UNSIGNED_INT_24_8:
175 return supportsReadDepthNV;
176 default:
177 return false;
178 }
179 }
180
ValidReadPixelsFloatDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)181 bool ValidReadPixelsFloatDepthType(const Context *context,
182 const gl::InternalFormat *info,
183 GLenum type)
184 {
185 return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
186 context->getExtensions().depthBufferFloat2NV && (info->componentCount == 1);
187 }
188
ValidReadPixelsFormatType(const Context * context,const gl::InternalFormat * info,GLenum format,GLenum type)189 bool ValidReadPixelsFormatType(const Context *context,
190 const gl::InternalFormat *info,
191 GLenum format,
192 GLenum type)
193 {
194 switch (info->componentType)
195 {
196 case GL_UNSIGNED_NORMALIZED:
197 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
198 // ReadPixels with BGRA even if the extension is not present
199 switch (format)
200 {
201 case GL_RGBA:
202 return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) ||
203 (context->getExtensions().textureNorm16 && (type == GL_UNSIGNED_SHORT) &&
204 info->pixelBytes >= 2);
205 case GL_BGRA_EXT:
206 return context->getExtensions().readFormatBGRA && (type == GL_UNSIGNED_BYTE);
207 case GL_STENCIL_INDEX_OES:
208 return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
209 case GL_DEPTH_COMPONENT:
210 return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
211 default:
212 return false;
213 }
214 case GL_SIGNED_NORMALIZED:
215 return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) ||
216 (context->getExtensions().textureNorm16 && format == GL_RGBA &&
217 type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2);
218
219 case GL_INT:
220 return (format == GL_RGBA_INTEGER && type == GL_INT);
221
222 case GL_UNSIGNED_INT:
223 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
224
225 case GL_FLOAT:
226 switch (format)
227 {
228 case GL_RGBA:
229 return (type == GL_FLOAT);
230 case GL_DEPTH_COMPONENT:
231 return ValidReadPixelsFloatDepthType(context, info, type);
232 default:
233 return false;
234 }
235 default:
236 UNREACHABLE();
237 return false;
238 }
239 }
240
241 template <typename ParamType>
ValidateTextureWrapModeValue(const Context * context,const ParamType * params,bool restrictedWrapModes)242 bool ValidateTextureWrapModeValue(const Context *context,
243 const ParamType *params,
244 bool restrictedWrapModes)
245 {
246 switch (ConvertToGLenum(params[0]))
247 {
248 case GL_CLAMP_TO_EDGE:
249 break;
250
251 case GL_CLAMP_TO_BORDER:
252 if (!context->getExtensions().textureBorderClampOES)
253 {
254 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
255 return false;
256 }
257 break;
258
259 case GL_REPEAT:
260 case GL_MIRRORED_REPEAT:
261 if (restrictedWrapModes)
262 {
263 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
264 context->validationError(GL_INVALID_ENUM, kInvalidWrapModeTexture);
265 return false;
266 }
267 break;
268
269 default:
270 context->validationError(GL_INVALID_ENUM, kInvalidTextureWrap);
271 return false;
272 }
273
274 return true;
275 }
276
277 template <typename ParamType>
ValidateTextureMinFilterValue(const Context * context,const ParamType * params,bool restrictedMinFilter)278 bool ValidateTextureMinFilterValue(const Context *context,
279 const ParamType *params,
280 bool restrictedMinFilter)
281 {
282 switch (ConvertToGLenum(params[0]))
283 {
284 case GL_NEAREST:
285 case GL_LINEAR:
286 break;
287
288 case GL_NEAREST_MIPMAP_NEAREST:
289 case GL_LINEAR_MIPMAP_NEAREST:
290 case GL_NEAREST_MIPMAP_LINEAR:
291 case GL_LINEAR_MIPMAP_LINEAR:
292 if (restrictedMinFilter)
293 {
294 // OES_EGL_image_external specifies this error.
295 context->validationError(GL_INVALID_ENUM, kInvalidFilterTexture);
296 return false;
297 }
298 break;
299
300 default:
301 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
302 return false;
303 }
304
305 return true;
306 }
307
308 template <typename ParamType>
ValidateTextureMagFilterValue(const Context * context,const ParamType * params)309 bool ValidateTextureMagFilterValue(const Context *context, const ParamType *params)
310 {
311 switch (ConvertToGLenum(params[0]))
312 {
313 case GL_NEAREST:
314 case GL_LINEAR:
315 break;
316
317 default:
318 context->validationError(GL_INVALID_ENUM, kInvalidTextureFilterParam);
319 return false;
320 }
321
322 return true;
323 }
324
325 template <typename ParamType>
ValidateTextureCompareModeValue(const Context * context,const ParamType * params)326 bool ValidateTextureCompareModeValue(const Context *context, const ParamType *params)
327 {
328 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
329 switch (ConvertToGLenum(params[0]))
330 {
331 case GL_NONE:
332 case GL_COMPARE_REF_TO_TEXTURE:
333 break;
334
335 default:
336 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
337 return false;
338 }
339
340 return true;
341 }
342
343 template <typename ParamType>
ValidateTextureCompareFuncValue(const Context * context,const ParamType * params)344 bool ValidateTextureCompareFuncValue(const Context *context, const ParamType *params)
345 {
346 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
347 switch (ConvertToGLenum(params[0]))
348 {
349 case GL_LEQUAL:
350 case GL_GEQUAL:
351 case GL_LESS:
352 case GL_GREATER:
353 case GL_EQUAL:
354 case GL_NOTEQUAL:
355 case GL_ALWAYS:
356 case GL_NEVER:
357 break;
358
359 default:
360 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
361 return false;
362 }
363
364 return true;
365 }
366
367 template <typename ParamType>
ValidateTextureSRGBDecodeValue(const Context * context,const ParamType * params)368 bool ValidateTextureSRGBDecodeValue(const Context *context, const ParamType *params)
369 {
370 if (!context->getExtensions().textureSRGBDecode)
371 {
372 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
373 return false;
374 }
375
376 switch (ConvertToGLenum(params[0]))
377 {
378 case GL_DECODE_EXT:
379 case GL_SKIP_DECODE_EXT:
380 break;
381
382 default:
383 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
384 return false;
385 }
386
387 return true;
388 }
389
390 template <typename ParamType>
ValidateTextureSRGBOverrideValue(const Context * context,const ParamType * params)391 bool ValidateTextureSRGBOverrideValue(const Context *context, const ParamType *params)
392 {
393 if (!context->getExtensions().textureSRGBOverride)
394 {
395 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
396 return false;
397 }
398
399 switch (ConvertToGLenum(params[0]))
400 {
401 case GL_SRGB:
402 case GL_NONE:
403 break;
404
405 default:
406 context->validationError(GL_INVALID_ENUM, kUnknownParameter);
407 return false;
408 }
409
410 return true;
411 }
412
ValidateTextureMaxAnisotropyExtensionEnabled(const Context * context)413 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context)
414 {
415 if (!context->getExtensions().textureFilterAnisotropic)
416 {
417 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
418 return false;
419 }
420
421 return true;
422 }
423
ValidateTextureMaxAnisotropyValue(const Context * context,GLfloat paramValue)424 bool ValidateTextureMaxAnisotropyValue(const Context *context, GLfloat paramValue)
425 {
426 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
427 {
428 return false;
429 }
430
431 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
432
433 if (paramValue < 1 || paramValue > largest)
434 {
435 context->validationError(GL_INVALID_VALUE, kOutsideOfBounds);
436 return false;
437 }
438
439 return true;
440 }
441
ValidateFragmentShaderColorBufferMaskMatch(const Context * context)442 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
443 {
444 const Program *program = context->getActiveLinkedProgram();
445 const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
446
447 auto drawBufferMask = framebuffer->getDrawBufferMask().to_ulong();
448 auto fragmentOutputMask = program->getActiveOutputVariables().to_ulong();
449
450 return drawBufferMask == (drawBufferMask & fragmentOutputMask);
451 }
452
ValidateFragmentShaderColorBufferTypeMatch(const Context * context)453 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
454 {
455 const Program *program = context->getActiveLinkedProgram();
456 const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
457
458 return ValidateComponentTypeMasks(program->getDrawBufferTypeMask().to_ulong(),
459 framebuffer->getDrawBufferTypeMask().to_ulong(),
460 program->getActiveOutputVariables().to_ulong(),
461 framebuffer->getDrawBufferMask().to_ulong());
462 }
463
ValidateVertexShaderAttributeTypeMatch(const Context * context)464 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
465 {
466 const auto &glState = context->getState();
467 const Program *program = context->getActiveLinkedProgram();
468 const VertexArray *vao = context->getState().getVertexArray();
469
470 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
471 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
472 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
473
474 vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
475 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
476 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
477
478 return program &&
479 ValidateComponentTypeMasks(
480 program->getExecutable().getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
481 program->getExecutable().getAttributesMask().to_ulong(), 0xFFFF);
482 }
483
IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,PrimitiveMode geometryShaderInputPrimitiveType)484 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
485 PrimitiveMode geometryShaderInputPrimitiveType)
486 {
487 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
488 switch (drawMode)
489 {
490 case PrimitiveMode::Points:
491 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
492 case PrimitiveMode::Lines:
493 case PrimitiveMode::LineStrip:
494 case PrimitiveMode::LineLoop:
495 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
496 case PrimitiveMode::LinesAdjacency:
497 case PrimitiveMode::LineStripAdjacency:
498 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
499 case PrimitiveMode::Triangles:
500 case PrimitiveMode::TriangleFan:
501 case PrimitiveMode::TriangleStrip:
502 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
503 case PrimitiveMode::TrianglesAdjacency:
504 case PrimitiveMode::TriangleStripAdjacency:
505 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
506 default:
507 UNREACHABLE();
508 return false;
509 }
510 }
511
512 // GLES1 texture parameters are a small subset of the others
IsValidGLES1TextureParameter(GLenum pname)513 bool IsValidGLES1TextureParameter(GLenum pname)
514 {
515 switch (pname)
516 {
517 case GL_TEXTURE_MAG_FILTER:
518 case GL_TEXTURE_MIN_FILTER:
519 case GL_TEXTURE_WRAP_S:
520 case GL_TEXTURE_WRAP_T:
521 case GL_TEXTURE_WRAP_R:
522 case GL_GENERATE_MIPMAP:
523 case GL_TEXTURE_CROP_RECT_OES:
524 return true;
525 default:
526 return false;
527 }
528 }
529
GetSamplerParameterCount(GLenum pname)530 unsigned int GetSamplerParameterCount(GLenum pname)
531 {
532 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
533 }
534
535 } // anonymous namespace
536
SetRobustLengthParam(const GLsizei * length,GLsizei value)537 void SetRobustLengthParam(const GLsizei *length, GLsizei value)
538 {
539 if (length)
540 {
541 // Currently we modify robust length parameters in the validation layer. We should be only
542 // doing this in the Context instead.
543 // TODO(http://anglebug.com/4406): Remove when possible.
544 *const_cast<GLsizei *>(length) = value;
545 }
546 }
547
ValidTextureTarget(const Context * context,TextureType type)548 bool ValidTextureTarget(const Context *context, TextureType type)
549 {
550 switch (type)
551 {
552 case TextureType::_2D:
553 case TextureType::CubeMap:
554 return true;
555
556 case TextureType::Rectangle:
557 return context->getExtensions().textureRectangle;
558
559 case TextureType::_3D:
560 return ((context->getClientMajorVersion() >= 3) ||
561 context->getExtensions().texture3DOES);
562
563 case TextureType::_2DArray:
564 return (context->getClientMajorVersion() >= 3);
565
566 case TextureType::_2DMultisample:
567 return (context->getClientVersion() >= Version(3, 1) ||
568 context->getExtensions().textureMultisample);
569 case TextureType::_2DMultisampleArray:
570 return context->getExtensions().textureStorageMultisample2DArrayOES;
571
572 case TextureType::CubeMapArray:
573 return (context->getClientVersion() >= Version(3, 2) ||
574 context->getExtensions().textureCubeMapArrayAny());
575
576 case TextureType::VideoImage:
577 return context->getExtensions().webglVideoTexture;
578
579 default:
580 return false;
581 }
582 }
583
ValidTexture2DTarget(const Context * context,TextureType type)584 bool ValidTexture2DTarget(const Context *context, TextureType type)
585 {
586 switch (type)
587 {
588 case TextureType::_2D:
589 case TextureType::CubeMap:
590 return true;
591
592 case TextureType::Rectangle:
593 return context->getExtensions().textureRectangle;
594
595 default:
596 return false;
597 }
598 }
599
ValidTexture3DTarget(const Context * context,TextureType target)600 bool ValidTexture3DTarget(const Context *context, TextureType target)
601 {
602 switch (target)
603 {
604 case TextureType::_3D:
605 case TextureType::_2DArray:
606 return (context->getClientMajorVersion() >= 3);
607
608 case TextureType::CubeMapArray:
609 return (context->getClientVersion() >= Version(3, 2) ||
610 context->getExtensions().textureCubeMapArrayAny());
611
612 default:
613 return false;
614 }
615 }
616
617 // Most texture GL calls are not compatible with external textures, so we have a separate validation
618 // function for use in the GL calls that do
ValidTextureExternalTarget(const Context * context,TextureType target)619 bool ValidTextureExternalTarget(const Context *context, TextureType target)
620 {
621 return (target == TextureType::External) &&
622 (context->getExtensions().eglImageExternalOES ||
623 context->getExtensions().eglStreamConsumerExternalNV);
624 }
625
ValidTextureExternalTarget(const Context * context,TextureTarget target)626 bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
627 {
628 return (target == TextureTarget::External) &&
629 ValidTextureExternalTarget(context, TextureType::External);
630 }
631
632 // This function differs from ValidTextureTarget in that the target must be
633 // usable as the destination of a 2D operation-- so a cube face is valid, but
634 // GL_TEXTURE_CUBE_MAP is not.
635 // Note: duplicate of IsInternalTextureTarget
ValidTexture2DDestinationTarget(const Context * context,TextureTarget target)636 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
637 {
638 switch (target)
639 {
640 case TextureTarget::_2D:
641 case TextureTarget::CubeMapNegativeX:
642 case TextureTarget::CubeMapNegativeY:
643 case TextureTarget::CubeMapNegativeZ:
644 case TextureTarget::CubeMapPositiveX:
645 case TextureTarget::CubeMapPositiveY:
646 case TextureTarget::CubeMapPositiveZ:
647 return true;
648 case TextureTarget::Rectangle:
649 return context->getExtensions().textureRectangle;
650 case TextureTarget::VideoImage:
651 return context->getExtensions().webglVideoTexture;
652 default:
653 return false;
654 }
655 }
656
ValidateTransformFeedbackPrimitiveMode(const Context * context,PrimitiveMode transformFeedbackPrimitiveMode,PrimitiveMode renderPrimitiveMode)657 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
658 PrimitiveMode transformFeedbackPrimitiveMode,
659 PrimitiveMode renderPrimitiveMode)
660 {
661 ASSERT(context);
662
663 if (!context->getExtensions().geometryShader)
664 {
665 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
666 // that does not match the current transform feedback object's draw mode (if transform
667 // feedback is active), (3.0.2, section 2.14, pg 86)
668 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
669 }
670
671 // [GL_EXT_geometry_shader] Table 12.1gs
672 switch (renderPrimitiveMode)
673 {
674 case PrimitiveMode::Points:
675 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
676 case PrimitiveMode::Lines:
677 case PrimitiveMode::LineStrip:
678 case PrimitiveMode::LineLoop:
679 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
680 case PrimitiveMode::Triangles:
681 case PrimitiveMode::TriangleFan:
682 case PrimitiveMode::TriangleStrip:
683 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
684 default:
685 UNREACHABLE();
686 return false;
687 }
688 }
689
ValidateDrawElementsInstancedBase(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)690 bool ValidateDrawElementsInstancedBase(const Context *context,
691 PrimitiveMode mode,
692 GLsizei count,
693 DrawElementsType type,
694 const void *indices,
695 GLsizei primcount)
696 {
697 if (primcount <= 0)
698 {
699 if (primcount < 0)
700 {
701 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
702 return false;
703 }
704
705 // Early exit.
706 return ValidateDrawElementsCommon(context, mode, count, type, indices, primcount);
707 }
708
709 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
710 {
711 return false;
712 }
713
714 if (count == 0)
715 {
716 // Early exit.
717 return true;
718 }
719
720 return ValidateDrawInstancedAttribs(context, primcount);
721 }
722
ValidateDrawArraysInstancedBase(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)723 bool ValidateDrawArraysInstancedBase(const Context *context,
724 PrimitiveMode mode,
725 GLint first,
726 GLsizei count,
727 GLsizei primcount)
728 {
729 if (primcount <= 0)
730 {
731 if (primcount < 0)
732 {
733 context->validationError(GL_INVALID_VALUE, kNegativePrimcount);
734 return false;
735 }
736
737 // Early exit.
738 return ValidateDrawArraysCommon(context, mode, first, count, primcount);
739 }
740
741 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
742 {
743 return false;
744 }
745
746 if (count == 0)
747 {
748 // Early exit.
749 return true;
750 }
751
752 return ValidateDrawInstancedAttribs(context, primcount);
753 }
754
ValidateDrawInstancedANGLE(const Context * context)755 bool ValidateDrawInstancedANGLE(const Context *context)
756 {
757 // Verify there is at least one active attribute with a divisor of zero
758 const State &state = context->getState();
759 const ProgramExecutable *executable = state.getProgramExecutable();
760
761 if (!executable)
762 {
763 // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
764 // an error.
765 context->getState().getDebug().insertMessage(
766 GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
767 std::string("Attempting to draw without a program"), gl::LOG_WARN);
768 return true;
769 }
770
771 const auto &attribs = state.getVertexArray()->getVertexAttributes();
772 const auto &bindings = state.getVertexArray()->getVertexBindings();
773 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
774 {
775 const VertexAttribute &attrib = attribs[attributeIndex];
776 const VertexBinding &binding = bindings[attrib.bindingIndex];
777 if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
778 {
779 return true;
780 }
781 }
782
783 context->validationError(GL_INVALID_OPERATION, kNoZeroDivisor);
784 return false;
785 }
786
ValidTexture3DDestinationTarget(const Context * context,TextureTarget target)787 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
788 {
789 switch (target)
790 {
791 case TextureTarget::_3D:
792 case TextureTarget::_2DArray:
793 case TextureTarget::CubeMapArray:
794 return true;
795 default:
796 return false;
797 }
798 }
799
ValidTexLevelDestinationTarget(const Context * context,TextureType type)800 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
801 {
802 switch (type)
803 {
804 case TextureType::_2D:
805 case TextureType::_2DArray:
806 case TextureType::_2DMultisample:
807 case TextureType::CubeMap:
808 case TextureType::_3D:
809 return true;
810 case TextureType::CubeMapArray:
811 return (context->getClientVersion() >= Version(3, 2) ||
812 context->getExtensions().textureCubeMapArrayAny());
813 case TextureType::Rectangle:
814 return context->getExtensions().textureRectangle;
815 case TextureType::_2DMultisampleArray:
816 return context->getExtensions().textureStorageMultisample2DArrayOES;
817 default:
818 return false;
819 }
820 }
821
ValidFramebufferTarget(const Context * context,GLenum target)822 bool ValidFramebufferTarget(const Context *context, GLenum target)
823 {
824 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
825 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
826 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
827
828 switch (target)
829 {
830 case GL_FRAMEBUFFER:
831 return true;
832
833 case GL_READ_FRAMEBUFFER:
834 case GL_DRAW_FRAMEBUFFER:
835 return (context->getExtensions().framebufferBlit ||
836 context->getClientMajorVersion() >= 3);
837
838 default:
839 return false;
840 }
841 }
842
ValidMipLevel(const Context * context,TextureType type,GLint level)843 bool ValidMipLevel(const Context *context, TextureType type, GLint level)
844 {
845 const auto &caps = context->getCaps();
846 int maxDimension = 0;
847 switch (type)
848 {
849 case TextureType::_2D:
850 case TextureType::_2DArray:
851 case TextureType::_2DMultisample:
852 case TextureType::_2DMultisampleArray:
853 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
854 // level-of-detail" for multisample textures should be. Could maybe make it zero.
855 maxDimension = caps.max2DTextureSize;
856 break;
857
858 case TextureType::CubeMap:
859 case TextureType::CubeMapArray:
860 maxDimension = caps.maxCubeMapTextureSize;
861 break;
862
863 case TextureType::External:
864 case TextureType::Rectangle:
865 case TextureType::VideoImage:
866 return level == 0;
867
868 case TextureType::_3D:
869 maxDimension = caps.max3DTextureSize;
870 break;
871
872 default:
873 UNREACHABLE();
874 }
875
876 return level <= log2(maxDimension) && level >= 0;
877 }
878
ValidImageSizeParameters(const Context * context,TextureType target,GLint level,GLsizei width,GLsizei height,GLsizei depth,bool isSubImage)879 bool ValidImageSizeParameters(const Context *context,
880 TextureType target,
881 GLint level,
882 GLsizei width,
883 GLsizei height,
884 GLsizei depth,
885 bool isSubImage)
886 {
887 if (width < 0 || height < 0 || depth < 0)
888 {
889 context->validationError(GL_INVALID_VALUE, kNegativeSize);
890 return false;
891 }
892 // TexSubImage parameters can be NPOT without textureNPOT extension,
893 // as long as the destination texture is POT.
894 bool hasNPOTSupport =
895 context->getExtensions().textureNPOTOES || context->getClientVersion() >= Version(3, 0);
896 if (!isSubImage && !hasNPOTSupport &&
897 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
898 {
899 context->validationError(GL_INVALID_VALUE, kTextureNotPow2);
900 return false;
901 }
902
903 if (!ValidMipLevel(context, target, level))
904 {
905 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
906 return false;
907 }
908
909 return true;
910 }
911
ValidCompressedDimension(GLsizei size,GLuint blockSize,bool smallerThanBlockSizeAllowed)912 bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
913 {
914 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
915 (size % blockSize == 0);
916 }
917
ValidCompressedImageSize(const Context * context,GLenum internalFormat,GLint level,GLsizei width,GLsizei height,GLsizei depth)918 bool ValidCompressedImageSize(const Context *context,
919 GLenum internalFormat,
920 GLint level,
921 GLsizei width,
922 GLsizei height,
923 GLsizei depth)
924 {
925 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
926 if (!formatInfo.compressed)
927 {
928 return false;
929 }
930
931 if (width < 0 || height < 0)
932 {
933 return false;
934 }
935
936 if (CompressedTextureFormatRequiresExactSize(internalFormat))
937 {
938 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
939 // block size for level 0 but WebGL disallows this.
940 bool smallerThanBlockSizeAllowed =
941 level > 0 || !context->getExtensions().webglCompatibility;
942
943 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
944 smallerThanBlockSizeAllowed) ||
945 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
946 smallerThanBlockSizeAllowed) ||
947 !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth,
948 smallerThanBlockSizeAllowed))
949 {
950 return false;
951 }
952 }
953
954 return true;
955 }
956
ValidCompressedSubImageSize(const Context * context,GLenum internalFormat,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,size_t textureWidth,size_t textureHeight,size_t textureDepth)957 bool ValidCompressedSubImageSize(const Context *context,
958 GLenum internalFormat,
959 GLint xoffset,
960 GLint yoffset,
961 GLint zoffset,
962 GLsizei width,
963 GLsizei height,
964 GLsizei depth,
965 size_t textureWidth,
966 size_t textureHeight,
967 size_t textureDepth)
968 {
969 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
970 if (!formatInfo.compressed)
971 {
972 return false;
973 }
974
975 if (xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0 || depth < 0)
976 {
977 return false;
978 }
979
980 bool fillsEntireMip =
981 xoffset == 0 && yoffset == 0 && static_cast<size_t>(width) == textureWidth &&
982 static_cast<size_t>(height) == textureHeight && static_cast<size_t>(depth) == textureDepth;
983
984 if (CompressedFormatRequiresWholeImage(internalFormat))
985 {
986 return fillsEntireMip;
987 }
988
989 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
990 {
991 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
992 yoffset % formatInfo.compressedBlockHeight != 0 ||
993 zoffset % formatInfo.compressedBlockDepth != 0)
994 {
995 return false;
996 }
997
998 // Allowed to either have data that is a multiple of block size or is smaller than the block
999 // size but fills the entire mip
1000 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1001 (height % formatInfo.compressedBlockHeight) == 0 &&
1002 (depth % formatInfo.compressedBlockDepth) == 0;
1003 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
1004 {
1005 return false;
1006 }
1007 }
1008
1009 return true;
1010 }
1011
ValidImageDataSize(const Context * context,TextureType texType,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels,GLsizei imageSize)1012 bool ValidImageDataSize(const Context *context,
1013 TextureType texType,
1014 GLsizei width,
1015 GLsizei height,
1016 GLsizei depth,
1017 GLenum format,
1018 GLenum type,
1019 const void *pixels,
1020 GLsizei imageSize)
1021 {
1022 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
1023 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1024 {
1025 // Checks are not required
1026 return true;
1027 }
1028
1029 // ...the data would be unpacked from the buffer object such that the memory reads required
1030 // would exceed the data store size.
1031 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
1032 ASSERT(formatInfo.internalFormat != GL_NONE);
1033 const Extents size(width, height, depth);
1034 const auto &unpack = context->getState().getUnpackState();
1035
1036 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
1037 GLuint endByte = 0;
1038 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
1039 {
1040 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
1041 return false;
1042 }
1043
1044 if (pixelUnpackBuffer)
1045 {
1046 CheckedNumeric<size_t> checkedEndByte(endByte);
1047 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1048 checkedEndByte += checkedOffset;
1049
1050 if (!checkedEndByte.IsValid() ||
1051 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1052 {
1053 // Overflow past the end of the buffer
1054 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
1055 return false;
1056 }
1057 if (context->getExtensions().webglCompatibility &&
1058 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
1059 {
1060 context->validationError(GL_INVALID_OPERATION,
1061 kPixelUnpackBufferBoundForTransformFeedback);
1062 return false;
1063 }
1064 }
1065 else
1066 {
1067 ASSERT(imageSize >= 0);
1068 if (pixels == nullptr && imageSize != 0)
1069 {
1070 context->validationError(GL_INVALID_OPERATION, kImageSizeMustBeZero);
1071 return false;
1072 }
1073
1074 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
1075 {
1076 context->validationError(GL_INVALID_OPERATION, kImageSizeTooSmall);
1077 return false;
1078 }
1079 }
1080
1081 return true;
1082 }
1083
ValidQueryType(const Context * context,QueryType queryType)1084 bool ValidQueryType(const Context *context, QueryType queryType)
1085 {
1086 switch (queryType)
1087 {
1088 case QueryType::AnySamples:
1089 case QueryType::AnySamplesConservative:
1090 return context->getClientMajorVersion() >= 3 ||
1091 context->getExtensions().occlusionQueryBoolean;
1092 case QueryType::TransformFeedbackPrimitivesWritten:
1093 return (context->getClientMajorVersion() >= 3);
1094 case QueryType::TimeElapsed:
1095 return context->getExtensions().disjointTimerQuery;
1096 case QueryType::CommandsCompleted:
1097 return context->getExtensions().syncQuery;
1098 case QueryType::PrimitivesGenerated:
1099 return context->getExtensions().geometryShader;
1100 default:
1101 return false;
1102 }
1103 }
1104
ValidateWebGLVertexAttribPointer(const Context * context,VertexAttribType type,GLboolean normalized,GLsizei stride,const void * ptr,bool pureInteger)1105 bool ValidateWebGLVertexAttribPointer(const Context *context,
1106 VertexAttribType type,
1107 GLboolean normalized,
1108 GLsizei stride,
1109 const void *ptr,
1110 bool pureInteger)
1111 {
1112 ASSERT(context->getExtensions().webglCompatibility);
1113 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1114 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1115 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1116 // parameter exceeds 255.
1117 constexpr GLsizei kMaxWebGLStride = 255;
1118 if (stride > kMaxWebGLStride)
1119 {
1120 context->validationError(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
1121 return false;
1122 }
1123
1124 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1125 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1126 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1127 // or an INVALID_OPERATION error is generated.
1128 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1129 size_t typeSize = GetVertexFormatSize(internalType);
1130
1131 ASSERT(isPow2(typeSize) && typeSize > 0);
1132 size_t sizeMask = (typeSize - 1);
1133 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1134 {
1135 context->validationError(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
1136 return false;
1137 }
1138
1139 if ((stride & sizeMask) != 0)
1140 {
1141 context->validationError(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
1142 return false;
1143 }
1144
1145 return true;
1146 }
1147
GetValidProgramNoResolve(const Context * context,ShaderProgramID id)1148 Program *GetValidProgramNoResolve(const Context *context, ShaderProgramID id)
1149 {
1150 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1151 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1152 // or program object and INVALID_OPERATION if the provided name identifies an object
1153 // that is not the expected type."
1154
1155 Program *validProgram = context->getProgramNoResolveLink(id);
1156
1157 if (!validProgram)
1158 {
1159 if (context->getShader(id))
1160 {
1161 context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
1162 }
1163 else
1164 {
1165 context->validationError(GL_INVALID_VALUE, kInvalidProgramName);
1166 }
1167 }
1168
1169 return validProgram;
1170 }
1171
GetValidProgram(const Context * context,ShaderProgramID id)1172 Program *GetValidProgram(const Context *context, ShaderProgramID id)
1173 {
1174 Program *program = GetValidProgramNoResolve(context, id);
1175 if (program)
1176 {
1177 program->resolveLink(context);
1178 }
1179 return program;
1180 }
1181
GetValidShader(const Context * context,ShaderProgramID id)1182 Shader *GetValidShader(const Context *context, ShaderProgramID id)
1183 {
1184 // See ValidProgram for spec details.
1185
1186 Shader *validShader = context->getShader(id);
1187
1188 if (!validShader)
1189 {
1190 if (context->getProgramNoResolveLink(id))
1191 {
1192 context->validationError(GL_INVALID_OPERATION, kExpectedShaderName);
1193 }
1194 else
1195 {
1196 context->validationError(GL_INVALID_VALUE, kInvalidShaderName);
1197 }
1198 }
1199
1200 return validShader;
1201 }
1202
ValidateAttachmentTarget(const Context * context,GLenum attachment)1203 bool ValidateAttachmentTarget(const Context *context, GLenum attachment)
1204 {
1205 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1206 {
1207 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1208 {
1209 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1210 return false;
1211 }
1212
1213 // Color attachment 0 is validated below because it is always valid
1214 const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1215 if (colorAttachment >= context->getCaps().maxColorAttachments)
1216 {
1217 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
1218 return false;
1219 }
1220 }
1221 else
1222 {
1223 switch (attachment)
1224 {
1225 case GL_COLOR_ATTACHMENT0:
1226 case GL_DEPTH_ATTACHMENT:
1227 case GL_STENCIL_ATTACHMENT:
1228 break;
1229
1230 case GL_DEPTH_STENCIL_ATTACHMENT:
1231 if (!context->getExtensions().webglCompatibility &&
1232 context->getClientMajorVersion() < 3)
1233 {
1234 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1235 return false;
1236 }
1237 break;
1238
1239 default:
1240 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
1241 return false;
1242 }
1243 }
1244
1245 return true;
1246 }
1247
ValidateRenderbufferStorageParametersBase(const Context * context,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1248 bool ValidateRenderbufferStorageParametersBase(const Context *context,
1249 GLenum target,
1250 GLsizei samples,
1251 GLenum internalformat,
1252 GLsizei width,
1253 GLsizei height)
1254 {
1255 switch (target)
1256 {
1257 case GL_RENDERBUFFER:
1258 break;
1259 default:
1260 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1261 return false;
1262 }
1263
1264 if (width < 0 || height < 0 || samples < 0)
1265 {
1266 context->validationError(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
1267 return false;
1268 }
1269
1270 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1271 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1272
1273 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
1274 if (!formatCaps.renderbuffer)
1275 {
1276 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1277 return false;
1278 }
1279
1280 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1281 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
1282 // only sized internal formats.
1283 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
1284 if (formatInfo.internalFormat == GL_NONE)
1285 {
1286 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1287 return false;
1288 }
1289
1290 if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
1291 {
1292 context->validationError(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
1293 return false;
1294 }
1295
1296 RenderbufferID id = context->getState().getRenderbufferId();
1297 if (id.value == 0)
1298 {
1299 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1300 return false;
1301 }
1302
1303 return true;
1304 }
1305
ValidateFramebufferRenderbufferParameters(const Context * context,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)1306 bool ValidateFramebufferRenderbufferParameters(const Context *context,
1307 GLenum target,
1308 GLenum attachment,
1309 GLenum renderbuffertarget,
1310 RenderbufferID renderbuffer)
1311 {
1312 if (!ValidFramebufferTarget(context, target))
1313 {
1314 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1315 return false;
1316 }
1317
1318 Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1319
1320 ASSERT(framebuffer);
1321 if (framebuffer->isDefault())
1322 {
1323 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
1324 return false;
1325 }
1326
1327 if (!ValidateAttachmentTarget(context, attachment))
1328 {
1329 return false;
1330 }
1331
1332 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1333 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1334 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1335 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1336 if (renderbuffer.value != 0)
1337 {
1338 if (!context->getRenderbuffer(renderbuffer))
1339 {
1340 context->validationError(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1341 return false;
1342 }
1343 }
1344
1345 return true;
1346 }
1347
ValidateBlitFramebufferParameters(const Context * context,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1348 bool ValidateBlitFramebufferParameters(const Context *context,
1349 GLint srcX0,
1350 GLint srcY0,
1351 GLint srcX1,
1352 GLint srcY1,
1353 GLint dstX0,
1354 GLint dstY0,
1355 GLint dstX1,
1356 GLint dstY1,
1357 GLbitfield mask,
1358 GLenum filter)
1359 {
1360 switch (filter)
1361 {
1362 case GL_NEAREST:
1363 break;
1364 case GL_LINEAR:
1365 break;
1366 default:
1367 context->validationError(GL_INVALID_ENUM, kBlitInvalidFilter);
1368 return false;
1369 }
1370
1371 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1372 {
1373 context->validationError(GL_INVALID_VALUE, kBlitInvalidMask);
1374 return false;
1375 }
1376
1377 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1378 // color buffer, leaving only nearest being unfiltered from above
1379 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1380 {
1381 context->validationError(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
1382 return false;
1383 }
1384
1385 const auto &glState = context->getState();
1386 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1387 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1388
1389 if (!readFramebuffer || !drawFramebuffer)
1390 {
1391 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
1392 return false;
1393 }
1394
1395 if (!ValidateFramebufferComplete(context, readFramebuffer))
1396 {
1397 return false;
1398 }
1399
1400 if (!ValidateFramebufferComplete(context, drawFramebuffer))
1401 {
1402 return false;
1403 }
1404
1405 // The draw and read framebuffers can only match if:
1406 // - They are the default framebuffer AND
1407 // - The read/draw surfaces are different
1408 if ((readFramebuffer->id() == drawFramebuffer->id()) &&
1409 ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
1410 (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
1411 {
1412 context->validationError(GL_INVALID_OPERATION, kBlitFeedbackLoop);
1413 return false;
1414 }
1415
1416 // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
1417 // consider it MS. needResourceSamples = false
1418 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer, false))
1419 {
1420 return false;
1421 }
1422
1423 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1424 // always run it in order to avoid triggering driver bugs.
1425 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1426 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1427 {
1428 context->validationError(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
1429 return false;
1430 }
1431
1432 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1433
1434 if (mask & GL_COLOR_BUFFER_BIT)
1435 {
1436 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
1437 const Extensions &extensions = context->getExtensions();
1438
1439 if (readColorBuffer)
1440 {
1441 const Format &readFormat = readColorBuffer->getFormat();
1442
1443 for (size_t drawbufferIdx = 0;
1444 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
1445 {
1446 const FramebufferAttachment *attachment =
1447 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1448 if (attachment)
1449 {
1450 const Format &drawFormat = attachment->getFormat();
1451
1452 // The GL ES 3.0.2 spec (pg 193) states that:
1453 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1454 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1455 // as well
1456 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1457 // well
1458 // Changes with EXT_color_buffer_float:
1459 // Case 1) is changed to fixed point OR floating point
1460 GLenum readComponentType = readFormat.info->componentType;
1461 GLenum drawComponentType = drawFormat.info->componentType;
1462 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1463 readComponentType == GL_SIGNED_NORMALIZED);
1464 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1465 drawComponentType == GL_SIGNED_NORMALIZED);
1466
1467 if (extensions.colorBufferFloat)
1468 {
1469 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1470 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1471
1472 if (readFixedOrFloat != drawFixedOrFloat)
1473 {
1474 context->validationError(GL_INVALID_OPERATION,
1475 kBlitTypeMismatchFixedOrFloat);
1476 return false;
1477 }
1478 }
1479 else if (readFixedPoint != drawFixedPoint)
1480 {
1481 context->validationError(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
1482 return false;
1483 }
1484
1485 if (readComponentType == GL_UNSIGNED_INT &&
1486 drawComponentType != GL_UNSIGNED_INT)
1487 {
1488 context->validationError(GL_INVALID_OPERATION,
1489 kBlitTypeMismatchUnsignedInteger);
1490 return false;
1491 }
1492
1493 if (readComponentType == GL_INT && drawComponentType != GL_INT)
1494 {
1495 context->validationError(GL_INVALID_OPERATION,
1496 kBlitTypeMismatchSignedInteger);
1497 return false;
1498 }
1499
1500 if (readColorBuffer->getSamples() > 0 &&
1501 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
1502 {
1503 context->validationError(GL_INVALID_OPERATION,
1504 kBlitMultisampledFormatOrBoundsMismatch);
1505 return false;
1506 }
1507
1508 if (context->getExtensions().webglCompatibility &&
1509 *readColorBuffer == *attachment)
1510 {
1511 context->validationError(GL_INVALID_OPERATION, kBlitSameImageColor);
1512 return false;
1513 }
1514 }
1515 }
1516
1517 if (readFormat.info->isInt() && filter == GL_LINEAR)
1518 {
1519 context->validationError(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
1520 return false;
1521 }
1522 }
1523 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1524 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1525 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1526 // situation is an application error that would lead to a crash in ANGLE.
1527 else if (drawFramebuffer->hasEnabledDrawBuffer())
1528 {
1529 context->validationError(GL_INVALID_OPERATION, kBlitMissingColor);
1530 return false;
1531 }
1532 }
1533
1534 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1535 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1536 for (size_t i = 0; i < 2; i++)
1537 {
1538 if (mask & masks[i])
1539 {
1540 const FramebufferAttachment *readBuffer =
1541 readFramebuffer->getAttachment(context, attachments[i]);
1542 const FramebufferAttachment *drawBuffer =
1543 drawFramebuffer->getAttachment(context, attachments[i]);
1544
1545 if (readBuffer && drawBuffer)
1546 {
1547 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
1548 {
1549 context->validationError(GL_INVALID_OPERATION,
1550 kBlitDepthOrStencilFormatMismatch);
1551 return false;
1552 }
1553
1554 if (readBuffer->getSamples() > 0 && !sameBounds)
1555 {
1556 context->validationError(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
1557 return false;
1558 }
1559
1560 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1561 {
1562 context->validationError(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
1563 return false;
1564 }
1565 }
1566 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1567 else if (drawBuffer)
1568 {
1569 context->validationError(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
1570 return false;
1571 }
1572 }
1573 }
1574
1575 // OVR_multiview2:
1576 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1577 // current draw framebuffer isMultiview() or the number of
1578 // views in the current read framebuffer is more than one.
1579 if (readFramebuffer->readDisallowedByMultiview())
1580 {
1581 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
1582 return false;
1583 }
1584 if (drawFramebuffer->isMultiview())
1585 {
1586 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
1587 return false;
1588 }
1589
1590 return true;
1591 }
1592
ValidateReadPixelsRobustANGLE(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const GLsizei * length,const GLsizei * columns,const GLsizei * rows,const void * pixels)1593 bool ValidateReadPixelsRobustANGLE(const Context *context,
1594 GLint x,
1595 GLint y,
1596 GLsizei width,
1597 GLsizei height,
1598 GLenum format,
1599 GLenum type,
1600 GLsizei bufSize,
1601 const GLsizei *length,
1602 const GLsizei *columns,
1603 const GLsizei *rows,
1604 const void *pixels)
1605 {
1606 if (!ValidateRobustEntryPoint(context, bufSize))
1607 {
1608 return false;
1609 }
1610
1611 GLsizei writeLength = 0;
1612 GLsizei writeColumns = 0;
1613 GLsizei writeRows = 0;
1614
1615 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1616 &writeColumns, &writeRows, pixels))
1617 {
1618 return false;
1619 }
1620
1621 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
1622 {
1623 return false;
1624 }
1625
1626 SetRobustLengthParam(length, writeLength);
1627 SetRobustLengthParam(columns, writeColumns);
1628 SetRobustLengthParam(rows, writeRows);
1629
1630 return true;
1631 }
1632
ValidateReadnPixelsEXT(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)1633 bool ValidateReadnPixelsEXT(const Context *context,
1634 GLint x,
1635 GLint y,
1636 GLsizei width,
1637 GLsizei height,
1638 GLenum format,
1639 GLenum type,
1640 GLsizei bufSize,
1641 const void *pixels)
1642 {
1643 if (bufSize < 0)
1644 {
1645 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
1646 return false;
1647 }
1648
1649 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1650 nullptr, nullptr, pixels);
1651 }
1652
ValidateReadnPixelsRobustANGLE(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const GLsizei * length,const GLsizei * columns,const GLsizei * rows,const void * data)1653 bool ValidateReadnPixelsRobustANGLE(const Context *context,
1654 GLint x,
1655 GLint y,
1656 GLsizei width,
1657 GLsizei height,
1658 GLenum format,
1659 GLenum type,
1660 GLsizei bufSize,
1661 const GLsizei *length,
1662 const GLsizei *columns,
1663 const GLsizei *rows,
1664 const void *data)
1665 {
1666 GLsizei writeLength = 0;
1667 GLsizei writeColumns = 0;
1668 GLsizei writeRows = 0;
1669
1670 if (!ValidateRobustEntryPoint(context, bufSize))
1671 {
1672 return false;
1673 }
1674
1675 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1676 &writeColumns, &writeRows, data))
1677 {
1678 return false;
1679 }
1680
1681 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
1682 {
1683 return false;
1684 }
1685
1686 SetRobustLengthParam(length, writeLength);
1687 SetRobustLengthParam(columns, writeColumns);
1688 SetRobustLengthParam(rows, writeRows);
1689
1690 return true;
1691 }
1692
ValidateGenQueriesEXT(const Context * context,GLsizei n,const QueryID * ids)1693 bool ValidateGenQueriesEXT(const Context *context, GLsizei n, const QueryID *ids)
1694 {
1695 if (!context->getExtensions().occlusionQueryBoolean &&
1696 !context->getExtensions().disjointTimerQuery)
1697 {
1698 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1699 return false;
1700 }
1701
1702 return ValidateGenOrDelete(context, n);
1703 }
1704
ValidateDeleteQueriesEXT(const Context * context,GLsizei n,const QueryID * ids)1705 bool ValidateDeleteQueriesEXT(const Context *context, GLsizei n, const QueryID *ids)
1706 {
1707 if (!context->getExtensions().occlusionQueryBoolean &&
1708 !context->getExtensions().disjointTimerQuery)
1709 {
1710 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1711 return false;
1712 }
1713
1714 return ValidateGenOrDelete(context, n);
1715 }
1716
ValidateIsQueryEXT(const Context * context,QueryID id)1717 bool ValidateIsQueryEXT(const Context *context, QueryID id)
1718 {
1719 if (!context->getExtensions().occlusionQueryBoolean &&
1720 !context->getExtensions().disjointTimerQuery)
1721 {
1722 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1723 return false;
1724 }
1725
1726 return true;
1727 }
1728
ValidateBeginQueryBase(const Context * context,QueryType target,QueryID id)1729 bool ValidateBeginQueryBase(const Context *context, QueryType target, QueryID id)
1730 {
1731 if (!ValidQueryType(context, target))
1732 {
1733 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1734 return false;
1735 }
1736
1737 if (id.value == 0)
1738 {
1739 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1740 return false;
1741 }
1742
1743 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1744 // of zero, if the active query object name for <target> is non-zero (for the
1745 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1746 // the active query for either target is non-zero), if <id> is the name of an
1747 // existing query object whose type does not match <target>, or if <id> is the
1748 // active query object name for any query type, the error INVALID_OPERATION is
1749 // generated.
1750
1751 // Ensure no other queries are active
1752 // NOTE: If other queries than occlusion are supported, we will need to check
1753 // separately that:
1754 // a) The query ID passed is not the current active query for any target/type
1755 // b) There are no active queries for the requested target (and in the case
1756 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1757 // no query may be active for either if glBeginQuery targets either.
1758
1759 if (context->getState().isQueryActive(target))
1760 {
1761 context->validationError(GL_INVALID_OPERATION, kOtherQueryActive);
1762 return false;
1763 }
1764
1765 // check that name was obtained with glGenQueries
1766 if (!context->isQueryGenerated(id))
1767 {
1768 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1769 return false;
1770 }
1771
1772 // Check for type mismatch. If query is not yet started we're good to go.
1773 Query *queryObject = context->getQuery(id);
1774 if (queryObject && queryObject->getType() != target)
1775 {
1776 context->validationError(GL_INVALID_OPERATION, kQueryTargetMismatch);
1777 return false;
1778 }
1779
1780 return true;
1781 }
1782
ValidateBeginQueryEXT(const Context * context,QueryType target,QueryID id)1783 bool ValidateBeginQueryEXT(const Context *context, QueryType target, QueryID id)
1784 {
1785 if (!context->getExtensions().occlusionQueryBoolean &&
1786 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1787 {
1788 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1789 return false;
1790 }
1791
1792 return ValidateBeginQueryBase(context, target, id);
1793 }
1794
ValidateEndQueryBase(const Context * context,QueryType target)1795 bool ValidateEndQueryBase(const Context *context, QueryType target)
1796 {
1797 if (!ValidQueryType(context, target))
1798 {
1799 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1800 return false;
1801 }
1802
1803 const Query *queryObject = context->getState().getActiveQuery(target);
1804
1805 if (queryObject == nullptr)
1806 {
1807 context->validationError(GL_INVALID_OPERATION, kQueryInactive);
1808 return false;
1809 }
1810
1811 return true;
1812 }
1813
ValidateEndQueryEXT(const Context * context,QueryType target)1814 bool ValidateEndQueryEXT(const Context *context, QueryType target)
1815 {
1816 if (!context->getExtensions().occlusionQueryBoolean &&
1817 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1818 {
1819 context->validationError(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
1820 return false;
1821 }
1822
1823 return ValidateEndQueryBase(context, target);
1824 }
1825
ValidateQueryCounterEXT(const Context * context,QueryID id,QueryType target)1826 bool ValidateQueryCounterEXT(const Context *context, QueryID id, QueryType target)
1827 {
1828 if (!context->getExtensions().disjointTimerQuery)
1829 {
1830 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1831 return false;
1832 }
1833
1834 if (target != QueryType::Timestamp)
1835 {
1836 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
1837 return false;
1838 }
1839
1840 if (!context->isQueryGenerated(id))
1841 {
1842 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1843 return false;
1844 }
1845
1846 // If query object is not started, that's fine.
1847 Query *queryObject = context->getQuery(id);
1848 if (queryObject && context->getState().isQueryActive(queryObject))
1849 {
1850 context->validationError(GL_INVALID_OPERATION, kQueryActive);
1851 return false;
1852 }
1853
1854 return true;
1855 }
1856
ValidateGetQueryivBase(const Context * context,QueryType target,GLenum pname,GLsizei * numParams)1857 bool ValidateGetQueryivBase(const Context *context,
1858 QueryType target,
1859 GLenum pname,
1860 GLsizei *numParams)
1861 {
1862 if (numParams)
1863 {
1864 *numParams = 0;
1865 }
1866
1867 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
1868 {
1869 context->validationError(GL_INVALID_ENUM, kInvalidQueryType);
1870 return false;
1871 }
1872
1873 switch (pname)
1874 {
1875 case GL_CURRENT_QUERY_EXT:
1876 if (target == QueryType::Timestamp)
1877 {
1878 context->validationError(GL_INVALID_ENUM, kInvalidQueryTarget);
1879 return false;
1880 }
1881 break;
1882 case GL_QUERY_COUNTER_BITS_EXT:
1883 if (!context->getExtensions().disjointTimerQuery ||
1884 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
1885 {
1886 context->validationError(GL_INVALID_ENUM, kInvalidPname);
1887 return false;
1888 }
1889 break;
1890 default:
1891 context->validationError(GL_INVALID_ENUM, kInvalidPname);
1892 return false;
1893 }
1894
1895 if (numParams)
1896 {
1897 // All queries return only one value
1898 *numParams = 1;
1899 }
1900
1901 return true;
1902 }
1903
ValidateGetQueryivEXT(const Context * context,QueryType target,GLenum pname,const GLint * params)1904 bool ValidateGetQueryivEXT(const Context *context,
1905 QueryType target,
1906 GLenum pname,
1907 const GLint *params)
1908 {
1909 if (!context->getExtensions().occlusionQueryBoolean &&
1910 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
1911 {
1912 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
1913 return false;
1914 }
1915
1916 return ValidateGetQueryivBase(context, target, pname, nullptr);
1917 }
1918
ValidateGetQueryivRobustANGLE(const Context * context,QueryType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)1919 bool ValidateGetQueryivRobustANGLE(const Context *context,
1920 QueryType target,
1921 GLenum pname,
1922 GLsizei bufSize,
1923 const GLsizei *length,
1924 const GLint *params)
1925 {
1926 if (!ValidateRobustEntryPoint(context, bufSize))
1927 {
1928 return false;
1929 }
1930
1931 GLsizei numParams = 0;
1932
1933 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
1934 {
1935 return false;
1936 }
1937
1938 if (!ValidateRobustBufferSize(context, bufSize, numParams))
1939 {
1940 return false;
1941 }
1942
1943 SetRobustLengthParam(length, numParams);
1944
1945 return true;
1946 }
1947
ValidateGetQueryObjectValueBase(const Context * context,QueryID id,GLenum pname,GLsizei * numParams)1948 bool ValidateGetQueryObjectValueBase(const Context *context,
1949 QueryID id,
1950 GLenum pname,
1951 GLsizei *numParams)
1952 {
1953 if (numParams)
1954 {
1955 *numParams = 1;
1956 }
1957
1958 if (context->isContextLost())
1959 {
1960 context->validationError(GL_CONTEXT_LOST, kContextLost);
1961
1962 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
1963 {
1964 // Generate an error but still return true, the context still needs to return a
1965 // value in this case.
1966 return true;
1967 }
1968 else
1969 {
1970 return false;
1971 }
1972 }
1973
1974 Query *queryObject = context->getQuery(id);
1975
1976 if (!queryObject)
1977 {
1978 context->validationError(GL_INVALID_OPERATION, kInvalidQueryId);
1979 return false;
1980 }
1981
1982 if (context->getState().isQueryActive(queryObject))
1983 {
1984 context->validationError(GL_INVALID_OPERATION, kQueryActive);
1985 return false;
1986 }
1987
1988 switch (pname)
1989 {
1990 case GL_QUERY_RESULT_EXT:
1991 case GL_QUERY_RESULT_AVAILABLE_EXT:
1992 break;
1993
1994 default:
1995 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
1996 return false;
1997 }
1998
1999 return true;
2000 }
2001
ValidateGetQueryObjectivEXT(const Context * context,QueryID id,GLenum pname,const GLint * params)2002 bool ValidateGetQueryObjectivEXT(const Context *context,
2003 QueryID id,
2004 GLenum pname,
2005 const GLint *params)
2006 {
2007 if (!context->getExtensions().disjointTimerQuery)
2008 {
2009 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2010 return false;
2011 }
2012 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2013 }
2014
ValidateGetQueryObjectivRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)2015 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
2016 QueryID id,
2017 GLenum pname,
2018 GLsizei bufSize,
2019 const GLsizei *length,
2020 const GLint *params)
2021 {
2022 if (!context->getExtensions().disjointTimerQuery)
2023 {
2024 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2025 return false;
2026 }
2027
2028 if (!ValidateRobustEntryPoint(context, bufSize))
2029 {
2030 return false;
2031 }
2032
2033 GLsizei numParams = 0;
2034
2035 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2036 {
2037 return false;
2038 }
2039
2040 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2041 {
2042 return false;
2043 }
2044
2045 SetRobustLengthParam(length, numParams);
2046
2047 return true;
2048 }
2049
ValidateGetQueryObjectuivEXT(const Context * context,QueryID id,GLenum pname,const GLuint * params)2050 bool ValidateGetQueryObjectuivEXT(const Context *context,
2051 QueryID id,
2052 GLenum pname,
2053 const GLuint *params)
2054 {
2055 if (!context->getExtensions().disjointTimerQuery &&
2056 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2057 {
2058 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2059 return false;
2060 }
2061 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2062 }
2063
ValidateGetQueryObjectuivRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)2064 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
2065 QueryID id,
2066 GLenum pname,
2067 GLsizei bufSize,
2068 const GLsizei *length,
2069 const GLuint *params)
2070 {
2071 if (!context->getExtensions().disjointTimerQuery &&
2072 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2073 {
2074 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2075 return false;
2076 }
2077
2078 if (!ValidateRobustEntryPoint(context, bufSize))
2079 {
2080 return false;
2081 }
2082
2083 GLsizei numParams = 0;
2084
2085 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2086 {
2087 return false;
2088 }
2089
2090 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2091 {
2092 return false;
2093 }
2094
2095 SetRobustLengthParam(length, numParams);
2096
2097 return true;
2098 }
2099
ValidateGetQueryObjecti64vEXT(const Context * context,QueryID id,GLenum pname,GLint64 * params)2100 bool ValidateGetQueryObjecti64vEXT(const Context *context,
2101 QueryID id,
2102 GLenum pname,
2103 GLint64 *params)
2104 {
2105 if (!context->getExtensions().disjointTimerQuery)
2106 {
2107 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2108 return false;
2109 }
2110 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2111 }
2112
ValidateGetQueryObjecti64vRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * params)2113 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
2114 QueryID id,
2115 GLenum pname,
2116 GLsizei bufSize,
2117 const GLsizei *length,
2118 GLint64 *params)
2119 {
2120 if (!context->getExtensions().disjointTimerQuery)
2121 {
2122 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2123 return false;
2124 }
2125
2126 if (!ValidateRobustEntryPoint(context, bufSize))
2127 {
2128 return false;
2129 }
2130
2131 GLsizei numParams = 0;
2132
2133 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2134 {
2135 return false;
2136 }
2137
2138 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2139 {
2140 return false;
2141 }
2142
2143 SetRobustLengthParam(length, numParams);
2144
2145 return true;
2146 }
2147
ValidateGetQueryObjectui64vEXT(const Context * context,QueryID id,GLenum pname,GLuint64 * params)2148 bool ValidateGetQueryObjectui64vEXT(const Context *context,
2149 QueryID id,
2150 GLenum pname,
2151 GLuint64 *params)
2152 {
2153 if (!context->getExtensions().disjointTimerQuery)
2154 {
2155 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2156 return false;
2157 }
2158 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2159 }
2160
ValidateGetQueryObjectui64vRobustANGLE(const Context * context,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLuint64 * params)2161 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
2162 QueryID id,
2163 GLenum pname,
2164 GLsizei bufSize,
2165 const GLsizei *length,
2166 GLuint64 *params)
2167 {
2168 if (!context->getExtensions().disjointTimerQuery)
2169 {
2170 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
2171 return false;
2172 }
2173
2174 if (!ValidateRobustEntryPoint(context, bufSize))
2175 {
2176 return false;
2177 }
2178
2179 GLsizei numParams = 0;
2180
2181 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
2182 {
2183 return false;
2184 }
2185
2186 if (!ValidateRobustBufferSize(context, bufSize, numParams))
2187 {
2188 return false;
2189 }
2190
2191 SetRobustLengthParam(length, numParams);
2192
2193 return true;
2194 }
2195
ValidateUniformCommonBase(const Context * context,const Program * program,UniformLocation location,GLsizei count,const LinkedUniform ** uniformOut)2196 bool ValidateUniformCommonBase(const Context *context,
2197 const Program *program,
2198 UniformLocation location,
2199 GLsizei count,
2200 const LinkedUniform **uniformOut)
2201 {
2202 // TODO(Jiajia): Add image uniform check in future.
2203 if (count < 0)
2204 {
2205 context->validationError(GL_INVALID_VALUE, kNegativeCount);
2206 return false;
2207 }
2208
2209 if (!program)
2210 {
2211 context->validationError(GL_INVALID_OPERATION, kInvalidProgramName);
2212 return false;
2213 }
2214
2215 if (!program->isLinked())
2216 {
2217 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
2218 return false;
2219 }
2220
2221 if (location.value == -1)
2222 {
2223 // Silently ignore the uniform command
2224 return false;
2225 }
2226
2227 const auto &uniformLocations = program->getUniformLocations();
2228 size_t castedLocation = static_cast<size_t>(location.value);
2229 if (castedLocation >= uniformLocations.size())
2230 {
2231 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
2232 return false;
2233 }
2234
2235 const auto &uniformLocation = uniformLocations[castedLocation];
2236 if (uniformLocation.ignored)
2237 {
2238 // Silently ignore the uniform command
2239 return false;
2240 }
2241
2242 if (!uniformLocation.used())
2243 {
2244 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
2245 return false;
2246 }
2247
2248 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2249
2250 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2251 if (count > 1 && !uniform.isArray())
2252 {
2253 context->validationError(GL_INVALID_OPERATION, kInvalidUniformCount);
2254 return false;
2255 }
2256
2257 *uniformOut = &uniform;
2258 return true;
2259 }
2260
ValidateUniform1ivValue(const Context * context,GLenum uniformType,GLsizei count,const GLint * value)2261 bool ValidateUniform1ivValue(const Context *context,
2262 GLenum uniformType,
2263 GLsizei count,
2264 const GLint *value)
2265 {
2266 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2267 // It is compatible with INT or BOOL.
2268 // Do these cheap tests first, for a little extra speed.
2269 if (GL_INT == uniformType || GL_BOOL == uniformType)
2270 {
2271 return true;
2272 }
2273
2274 if (IsSamplerType(uniformType))
2275 {
2276 // Check that the values are in range.
2277 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2278 for (GLsizei i = 0; i < count; ++i)
2279 {
2280 if (value[i] < 0 || value[i] >= max)
2281 {
2282 context->validationError(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
2283 return false;
2284 }
2285 }
2286 return true;
2287 }
2288
2289 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
2290 return false;
2291 }
2292
ValidateUniformMatrixValue(const Context * context,GLenum valueType,GLenum uniformType)2293 bool ValidateUniformMatrixValue(const Context *context, GLenum valueType, GLenum uniformType)
2294 {
2295 // Check that the value type is compatible with uniform type.
2296 if (valueType == uniformType)
2297 {
2298 return true;
2299 }
2300
2301 context->validationError(GL_INVALID_OPERATION, kUniformTypeMismatch);
2302 return false;
2303 }
2304
ValidateUniform(const Context * context,GLenum valueType,UniformLocation location,GLsizei count)2305 bool ValidateUniform(const Context *context,
2306 GLenum valueType,
2307 UniformLocation location,
2308 GLsizei count)
2309 {
2310 const LinkedUniform *uniform = nullptr;
2311 Program *programObject = context->getActiveLinkedProgram();
2312 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2313 ValidateUniformValue(context, valueType, uniform->type);
2314 }
2315
ValidateUniform1iv(const Context * context,UniformLocation location,GLsizei count,const GLint * value)2316 bool ValidateUniform1iv(const Context *context,
2317 UniformLocation location,
2318 GLsizei count,
2319 const GLint *value)
2320 {
2321 const LinkedUniform *uniform = nullptr;
2322 Program *programObject = context->getActiveLinkedProgram();
2323 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2324 ValidateUniform1ivValue(context, uniform->type, count, value);
2325 }
2326
ValidateUniformMatrix(const Context * context,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)2327 bool ValidateUniformMatrix(const Context *context,
2328 GLenum valueType,
2329 UniformLocation location,
2330 GLsizei count,
2331 GLboolean transpose)
2332 {
2333 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
2334 {
2335 context->validationError(GL_INVALID_VALUE, kES3Required);
2336 return false;
2337 }
2338
2339 const LinkedUniform *uniform = nullptr;
2340 Program *programObject = context->getActiveLinkedProgram();
2341 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2342 ValidateUniformMatrixValue(context, valueType, uniform->type);
2343 }
2344
ValidateStateQuery(const Context * context,GLenum pname,GLenum * nativeType,unsigned int * numParams)2345 bool ValidateStateQuery(const Context *context,
2346 GLenum pname,
2347 GLenum *nativeType,
2348 unsigned int *numParams)
2349 {
2350 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2351 {
2352 context->validationError(GL_INVALID_ENUM, kInvalidPname);
2353 return false;
2354 }
2355
2356 const Caps &caps = context->getCaps();
2357
2358 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2359 {
2360 int colorAttachment = (pname - GL_DRAW_BUFFER0);
2361
2362 if (colorAttachment >= caps.maxDrawBuffers)
2363 {
2364 context->validationError(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
2365 return false;
2366 }
2367 }
2368
2369 switch (pname)
2370 {
2371 case GL_TEXTURE_BINDING_2D:
2372 case GL_TEXTURE_BINDING_CUBE_MAP:
2373 case GL_TEXTURE_BINDING_3D:
2374 case GL_TEXTURE_BINDING_2D_ARRAY:
2375 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
2376 break;
2377 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
2378 if (!context->getExtensions().textureStorageMultisample2DArrayOES)
2379 {
2380 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
2381 return false;
2382 }
2383 break;
2384 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2385 if (!context->getExtensions().textureRectangle)
2386 {
2387 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2388 return false;
2389 }
2390 break;
2391 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2392 if (!context->getExtensions().eglStreamConsumerExternalNV &&
2393 !context->getExtensions().eglImageExternalOES)
2394 {
2395 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2396 return false;
2397 }
2398 break;
2399
2400 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2401 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2402 {
2403 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
2404 ASSERT(readFramebuffer);
2405
2406 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, readFramebuffer))
2407 {
2408 return false;
2409 }
2410
2411 if (readFramebuffer->getReadBufferState() == GL_NONE)
2412 {
2413 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
2414 return false;
2415 }
2416
2417 const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
2418 if (!attachment)
2419 {
2420 context->validationError(GL_INVALID_OPERATION, kReadBufferNotAttached);
2421 return false;
2422 }
2423 }
2424 break;
2425
2426 default:
2427 break;
2428 }
2429
2430 // pname is valid, but there are no parameters to return
2431 if (*numParams == 0)
2432 {
2433 return false;
2434 }
2435
2436 return true;
2437 }
2438
ValidateGetBooleanvRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLboolean * params)2439 bool ValidateGetBooleanvRobustANGLE(const Context *context,
2440 GLenum pname,
2441 GLsizei bufSize,
2442 const GLsizei *length,
2443 const GLboolean *params)
2444 {
2445 GLenum nativeType;
2446 unsigned int numParams = 0;
2447
2448 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2449 {
2450 return false;
2451 }
2452
2453 SetRobustLengthParam(length, numParams);
2454
2455 return true;
2456 }
2457
ValidateGetFloatvRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)2458 bool ValidateGetFloatvRobustANGLE(const Context *context,
2459 GLenum pname,
2460 GLsizei bufSize,
2461 const GLsizei *length,
2462 const GLfloat *params)
2463 {
2464 GLenum nativeType;
2465 unsigned int numParams = 0;
2466
2467 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2468 {
2469 return false;
2470 }
2471
2472 SetRobustLengthParam(length, numParams);
2473
2474 return true;
2475 }
2476
ValidateGetIntegervRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * data)2477 bool ValidateGetIntegervRobustANGLE(const Context *context,
2478 GLenum pname,
2479 GLsizei bufSize,
2480 const GLsizei *length,
2481 const GLint *data)
2482 {
2483 GLenum nativeType;
2484 unsigned int numParams = 0;
2485
2486 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2487 {
2488 return false;
2489 }
2490
2491 SetRobustLengthParam(length, numParams);
2492
2493 return true;
2494 }
2495
ValidateGetInteger64vRobustANGLE(const Context * context,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * data)2496 bool ValidateGetInteger64vRobustANGLE(const Context *context,
2497 GLenum pname,
2498 GLsizei bufSize,
2499 const GLsizei *length,
2500 GLint64 *data)
2501 {
2502 GLenum nativeType;
2503 unsigned int numParams = 0;
2504
2505 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2506 {
2507 return false;
2508 }
2509
2510 if (nativeType == GL_INT_64_ANGLEX)
2511 {
2512 CastStateValues(context, nativeType, pname, numParams, data);
2513 return false;
2514 }
2515
2516 SetRobustLengthParam(length, numParams);
2517 return true;
2518 }
2519
ValidateRobustStateQuery(const Context * context,GLenum pname,GLsizei bufSize,GLenum * nativeType,unsigned int * numParams)2520 bool ValidateRobustStateQuery(const Context *context,
2521 GLenum pname,
2522 GLsizei bufSize,
2523 GLenum *nativeType,
2524 unsigned int *numParams)
2525 {
2526 if (!ValidateRobustEntryPoint(context, bufSize))
2527 {
2528 return false;
2529 }
2530
2531 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2532 {
2533 return false;
2534 }
2535
2536 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
2537 {
2538 return false;
2539 }
2540
2541 return true;
2542 }
2543
ValidateCopyTexImageParametersBase(const Context * context,TextureTarget target,GLint level,GLenum internalformat,bool isSubImage,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,GLint border,Format * textureFormatOut)2544 bool ValidateCopyTexImageParametersBase(const Context *context,
2545 TextureTarget target,
2546 GLint level,
2547 GLenum internalformat,
2548 bool isSubImage,
2549 GLint xoffset,
2550 GLint yoffset,
2551 GLint zoffset,
2552 GLint x,
2553 GLint y,
2554 GLsizei width,
2555 GLsizei height,
2556 GLint border,
2557 Format *textureFormatOut)
2558 {
2559 TextureType texType = TextureTargetToType(target);
2560
2561 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2562 {
2563 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
2564 return false;
2565 }
2566
2567 if (width < 0 || height < 0)
2568 {
2569 context->validationError(GL_INVALID_VALUE, kNegativeSize);
2570 return false;
2571 }
2572
2573 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2574 std::numeric_limits<GLsizei>::max() - yoffset < height)
2575 {
2576 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
2577 return false;
2578 }
2579
2580 if (border != 0)
2581 {
2582 context->validationError(GL_INVALID_VALUE, kInvalidBorder);
2583 return false;
2584 }
2585
2586 if (!ValidMipLevel(context, texType, level))
2587 {
2588 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
2589 return false;
2590 }
2591
2592 const State &state = context->getState();
2593 Framebuffer *readFramebuffer = state.getReadFramebuffer();
2594 if (!ValidateFramebufferComplete(context, readFramebuffer))
2595 {
2596 return false;
2597 }
2598
2599 // needResourceSamples = true. Treat renderToTexture textures as single sample since they will
2600 // be resolved before copying
2601 if (!readFramebuffer->isDefault() &&
2602 !ValidateFramebufferNotMultisampled(context, readFramebuffer, true))
2603 {
2604 return false;
2605 }
2606
2607 if (readFramebuffer->getReadBufferState() == GL_NONE)
2608 {
2609 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
2610 return false;
2611 }
2612
2613 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2614 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
2615 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2616 // situation is an application error that would lead to a crash in ANGLE.
2617 const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
2618 if (source == nullptr)
2619 {
2620 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
2621 return false;
2622 }
2623
2624 // ANGLE_multiview spec, Revision 1:
2625 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2626 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2627 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2628 // framebuffer is more than one.
2629 if (readFramebuffer->readDisallowedByMultiview())
2630 {
2631 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
2632 return false;
2633 }
2634
2635 const Caps &caps = context->getCaps();
2636
2637 GLint maxDimension = 0;
2638 switch (texType)
2639 {
2640 case TextureType::_2D:
2641 maxDimension = caps.max2DTextureSize;
2642 break;
2643
2644 case TextureType::CubeMap:
2645 case TextureType::CubeMapArray:
2646 maxDimension = caps.maxCubeMapTextureSize;
2647 break;
2648
2649 case TextureType::Rectangle:
2650 maxDimension = caps.maxRectangleTextureSize;
2651 break;
2652
2653 case TextureType::_2DArray:
2654 maxDimension = caps.max2DTextureSize;
2655 break;
2656
2657 case TextureType::_3D:
2658 maxDimension = caps.max3DTextureSize;
2659 break;
2660
2661 default:
2662 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
2663 return false;
2664 }
2665
2666 Texture *texture = state.getTargetTexture(texType);
2667 if (!texture)
2668 {
2669 context->validationError(GL_INVALID_OPERATION, kTextureNotBound);
2670 return false;
2671 }
2672
2673 if (texture->getImmutableFormat() && !isSubImage)
2674 {
2675 context->validationError(GL_INVALID_OPERATION, kTextureIsImmutable);
2676 return false;
2677 }
2678
2679 const InternalFormat &formatInfo =
2680 isSubImage ? *texture->getFormat(target, level).info
2681 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
2682
2683 if (formatInfo.depthBits > 0 || formatInfo.compressed)
2684 {
2685 context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
2686 return false;
2687 }
2688
2689 if (isSubImage)
2690 {
2691 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2692 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2693 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
2694 {
2695 context->validationError(GL_INVALID_VALUE, kOffsetOverflow);
2696 return false;
2697 }
2698 }
2699 else
2700 {
2701 if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
2702 width != height)
2703 {
2704 context->validationError(GL_INVALID_VALUE, kCubemapIncomplete);
2705 return false;
2706 }
2707
2708 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
2709 {
2710 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
2711 return false;
2712 }
2713
2714 int maxLevelDimension = (maxDimension >> level);
2715 if (static_cast<int>(width) > maxLevelDimension ||
2716 static_cast<int>(height) > maxLevelDimension)
2717 {
2718 context->validationError(GL_INVALID_VALUE, kResourceMaxTextureSize);
2719 return false;
2720 }
2721 }
2722
2723 if (textureFormatOut)
2724 {
2725 *textureFormatOut = texture->getFormat(target, level);
2726 }
2727
2728 // Detect texture copying feedback loops for WebGL.
2729 if (context->getExtensions().webglCompatibility)
2730 {
2731 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
2732 {
2733 context->validationError(GL_INVALID_OPERATION, kFeedbackLoop);
2734 return false;
2735 }
2736 }
2737
2738 return true;
2739 }
2740
ValidateProgramDrawStates(const State & state,const Extensions & extensions,Program * program)2741 const char *ValidateProgramDrawStates(const State &state,
2742 const Extensions &extensions,
2743 Program *program)
2744 {
2745 if (extensions.multiview || extensions.multiview2)
2746 {
2747 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2748 Framebuffer *framebuffer = state.getDrawFramebuffer();
2749 const int framebufferNumViews = framebuffer->getNumViews();
2750
2751 if (framebufferNumViews != programNumViews)
2752 {
2753 return gl::err::kMultiviewMismatch;
2754 }
2755
2756 if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
2757 {
2758 return gl::err::kMultiviewTransformFeedback;
2759 }
2760
2761 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2762 state.isQueryActive(QueryType::TimeElapsed))
2763 {
2764 return gl::err::kMultiviewTimerQuery;
2765 }
2766 }
2767
2768 // Uniform buffer validation
2769 for (unsigned int uniformBlockIndex = 0;
2770 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2771 {
2772 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2773 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2774 const OffsetBindingPointer<Buffer> &uniformBuffer =
2775 state.getIndexedUniformBuffer(blockBinding);
2776
2777 if (uniformBuffer.get() == nullptr)
2778 {
2779 // undefined behaviour
2780 return gl::err::kUniformBufferUnbound;
2781 }
2782
2783 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2784 if (uniformBufferSize < uniformBlock.dataSize)
2785 {
2786 // undefined behaviour
2787 return gl::err::kUniformBufferTooSmall;
2788 }
2789
2790 if (extensions.webglCompatibility &&
2791 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2792 {
2793 return gl::err::kUniformBufferBoundForTransformFeedback;
2794 }
2795 }
2796
2797 return nullptr;
2798 }
2799
ValidateProgramPipelineDrawStates(const State & state,const Extensions & extensions,ProgramPipeline * programPipeline)2800 const char *ValidateProgramPipelineDrawStates(const State &state,
2801 const Extensions &extensions,
2802 ProgramPipeline *programPipeline)
2803 {
2804 for (const ShaderType shaderType : gl::AllShaderTypes())
2805 {
2806 Program *program = programPipeline->getShaderProgram(shaderType);
2807 if (program)
2808 {
2809 const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
2810 if (errorMsg)
2811 {
2812 return errorMsg;
2813 }
2814 }
2815 }
2816
2817 return nullptr;
2818 }
2819
ValidateProgramPipelineAttachedPrograms(ProgramPipeline * programPipeline)2820 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
2821 {
2822 // An INVALID_OPERATION error is generated by any command that transfers vertices to the
2823 // GL or launches compute work if the current set of active
2824 // program objects cannot be executed, for reasons including:
2825 // - A program object is active for at least one, but not all of the shader
2826 // stages that were present when the program was linked.
2827 for (const ShaderType shaderType : gl::AllShaderTypes())
2828 {
2829 Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
2830 if (shaderProgram)
2831 {
2832 ProgramExecutable &executable = shaderProgram->getExecutable();
2833 for (const ShaderType programShaderType : executable.getLinkedShaderStages())
2834 {
2835 if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
2836 {
2837 return gl::err::kNotAllStagesOfSeparableProgramUsed;
2838 }
2839 }
2840 }
2841 }
2842
2843 return nullptr;
2844 }
2845
2846 // Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2847 // completeness check.
ValidateDrawStates(const Context * context)2848 const char *ValidateDrawStates(const Context *context)
2849 {
2850 const Extensions &extensions = context->getExtensions();
2851 const State &state = context->getState();
2852
2853 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2854 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2855 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2856 VertexArray *vertexArray = state.getVertexArray();
2857 ASSERT(vertexArray);
2858
2859 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
2860 {
2861 return kBufferMapped;
2862 }
2863
2864 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2865 // Section 6.10 of the WebGL 1.0 spec.
2866 Framebuffer *framebuffer = state.getDrawFramebuffer();
2867 ASSERT(framebuffer);
2868
2869 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2870 {
2871 ASSERT(framebuffer);
2872 const FramebufferAttachment *dsAttachment =
2873 framebuffer->getStencilOrDepthStencilAttachment();
2874 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2875 ASSERT(stencilBits <= 8);
2876
2877 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2878 if (depthStencilState.stencilTest && stencilBits > 0)
2879 {
2880 GLuint maxStencilValue = (1 << stencilBits) - 1;
2881
2882 bool differentRefs =
2883 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2884 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2885 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2886 (depthStencilState.stencilBackWritemask & maxStencilValue);
2887 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2888 (depthStencilState.stencilBackMask & maxStencilValue);
2889
2890 if (differentRefs || differentWritemasks || differentMasks)
2891 {
2892 if (!extensions.webglCompatibility)
2893 {
2894 WARN() << "This ANGLE implementation does not support separate front/back "
2895 "stencil writemasks, reference values, or stencil mask values.";
2896 }
2897 return kStencilReferenceMaskOrMismatch;
2898 }
2899 }
2900 }
2901
2902 if (!extensions.floatBlend)
2903 {
2904 const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
2905 state.getBlendEnabledDrawBufferMask() &
2906 framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
2907 if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
2908 {
2909 return kUnsupportedFloatBlending;
2910 }
2911 }
2912
2913 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
2914 extensions.webglCompatibility)
2915 {
2916 if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
2917 {
2918 if (extensions.webglCompatibility)
2919 {
2920 return kInvalidConstantColor;
2921 }
2922
2923 WARN() << kConstantColorAlphaLimitation;
2924 return kConstantColorAlphaLimitation;
2925 }
2926 }
2927
2928 if (!framebuffer->isComplete(context))
2929 {
2930 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2931 return kDrawFramebufferIncomplete;
2932 }
2933
2934 if (context->getStateCache().hasAnyEnabledClientAttrib())
2935 {
2936 if (extensions.webglCompatibility || !state.areClientArraysEnabled())
2937 {
2938 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2939 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2940 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2941 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
2942 return kVertexArrayNoBuffer;
2943 }
2944
2945 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2946 {
2947 // This is an application error that would normally result in a crash, but we catch it
2948 // and return an error
2949 return kVertexArrayNoBufferPointer;
2950 }
2951 }
2952
2953 // If we are running GLES1, there is no current program.
2954 if (context->getClientVersion() >= Version(2, 0))
2955 {
2956 Program *program = state.getLinkedProgram(context);
2957 ProgramPipeline *programPipeline = state.getProgramPipeline();
2958
2959 if (program)
2960 {
2961 if (!program->validateSamplers(nullptr, context->getCaps()))
2962 {
2963 return kTextureTypeConflict;
2964 }
2965
2966 const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
2967 if (errorMsg)
2968 {
2969 return errorMsg;
2970 }
2971 }
2972 else if (programPipeline)
2973 {
2974 const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
2975 if (errorMsg)
2976 {
2977 return errorMsg;
2978 }
2979
2980 if (!programPipeline->validateSamplers(nullptr, context->getCaps()))
2981 {
2982 return kTextureTypeConflict;
2983 }
2984
2985 errorMsg = ValidateProgramPipelineDrawStates(state, extensions, programPipeline);
2986 if (errorMsg)
2987 {
2988 return errorMsg;
2989 }
2990 }
2991
2992 // Do some additional WebGL-specific validation
2993 if (extensions.webglCompatibility)
2994 {
2995 if (!state.validateSamplerFormats())
2996 {
2997 return kSamplerFormatMismatch;
2998 }
2999
3000 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
3001 if (state.isTransformFeedbackActive() &&
3002 transformFeedbackObject->buffersBoundForOtherUse())
3003 {
3004 return kTransformFeedbackBufferDoubleBound;
3005 }
3006
3007 // Detect rendering feedback loops for WebGL.
3008 if (framebuffer->hasRenderingFeedbackLoop())
3009 {
3010 return kFeedbackLoop;
3011 }
3012
3013 // Detect that the vertex shader input types match the attribute types
3014 if (!ValidateVertexShaderAttributeTypeMatch(context))
3015 {
3016 return kVertexShaderTypeMismatch;
3017 }
3018
3019 if (!context->getState().getRasterizerState().rasterizerDiscard &&
3020 !context->getState().allActiveDrawBufferChannelsMasked())
3021 {
3022 // Detect that if there's active color buffer without fragment shader output
3023 if (!ValidateFragmentShaderColorBufferMaskMatch(context))
3024 {
3025 return kDrawBufferMaskMismatch;
3026 }
3027
3028 // Detect that the color buffer types match the fragment shader output types
3029 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
3030 {
3031 return kDrawBufferTypeMismatch;
3032 }
3033 }
3034
3035 const VertexArray *vao = context->getState().getVertexArray();
3036 if (vao->hasTransformFeedbackBindingConflict(context))
3037 {
3038 return kVertexBufferBoundForTransformFeedback;
3039 }
3040 }
3041 }
3042
3043 return nullptr;
3044 }
3045
RecordDrawModeError(const Context * context,PrimitiveMode mode)3046 void RecordDrawModeError(const Context *context, PrimitiveMode mode)
3047 {
3048 const State &state = context->getState();
3049 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
3050 if (state.isTransformFeedbackActiveUnpaused())
3051 {
3052 if (!ValidateTransformFeedbackPrimitiveMode(context,
3053 curTransformFeedback->getPrimitiveMode(), mode))
3054 {
3055 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
3056 return;
3057 }
3058 }
3059
3060 const Extensions &extensions = context->getExtensions();
3061
3062 switch (mode)
3063 {
3064 case PrimitiveMode::Points:
3065 case PrimitiveMode::Lines:
3066 case PrimitiveMode::LineLoop:
3067 case PrimitiveMode::LineStrip:
3068 case PrimitiveMode::Triangles:
3069 case PrimitiveMode::TriangleStrip:
3070 case PrimitiveMode::TriangleFan:
3071 break;
3072
3073 case PrimitiveMode::LinesAdjacency:
3074 case PrimitiveMode::LineStripAdjacency:
3075 case PrimitiveMode::TrianglesAdjacency:
3076 case PrimitiveMode::TriangleStripAdjacency:
3077 if (!extensions.geometryShader)
3078 {
3079 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
3080 return;
3081 }
3082 break;
3083 default:
3084 context->validationError(GL_INVALID_ENUM, kInvalidDrawMode);
3085 return;
3086 }
3087
3088 // If we are running GLES1, there is no current program.
3089 if (context->getClientVersion() >= Version(2, 0))
3090 {
3091 Program *program = context->getActiveLinkedProgram();
3092 ASSERT(program);
3093
3094 // Do geometry shader specific validations
3095 if (program->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
3096 {
3097 if (!IsCompatibleDrawModeWithGeometryShader(
3098 mode, program->getGeometryShaderInputPrimitiveType()))
3099 {
3100 context->validationError(GL_INVALID_OPERATION,
3101 kIncompatibleDrawModeAgainstGeometryShader);
3102 return;
3103 }
3104 }
3105 }
3106
3107 // An error should be recorded.
3108 UNREACHABLE();
3109 }
3110
ValidateDrawArraysInstancedANGLE(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)3111 bool ValidateDrawArraysInstancedANGLE(const Context *context,
3112 PrimitiveMode mode,
3113 GLint first,
3114 GLsizei count,
3115 GLsizei primcount)
3116 {
3117 if (!context->getExtensions().instancedArraysANGLE)
3118 {
3119 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3120 return false;
3121 }
3122
3123 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
3124 {
3125 return false;
3126 }
3127
3128 return ValidateDrawInstancedANGLE(context);
3129 }
3130
ValidateDrawArraysInstancedEXT(const Context * context,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)3131 bool ValidateDrawArraysInstancedEXT(const Context *context,
3132 PrimitiveMode mode,
3133 GLint first,
3134 GLsizei count,
3135 GLsizei primcount)
3136 {
3137 if (!context->getExtensions().instancedArraysEXT)
3138 {
3139 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3140 return false;
3141 }
3142
3143 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
3144 {
3145 return false;
3146 }
3147
3148 return true;
3149 }
3150
ValidateDrawElementsStates(const Context * context)3151 const char *ValidateDrawElementsStates(const Context *context)
3152 {
3153 const State &state = context->getState();
3154
3155 if (context->getStateCache().isTransformFeedbackActiveUnpaused())
3156 {
3157 // EXT_geometry_shader allows transform feedback to work with all draw commands.
3158 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
3159 if (!context->getExtensions().geometryShader)
3160 {
3161 // It is an invalid operation to call DrawElements, DrawRangeElements or
3162 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3163 // 86)
3164 return kUnsupportedDrawModeForTransformFeedback;
3165 }
3166 }
3167
3168 const VertexArray *vao = state.getVertexArray();
3169 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
3170
3171 if (elementArrayBuffer)
3172 {
3173 if (context->getExtensions().webglCompatibility)
3174 {
3175 if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3176 {
3177 return kElementArrayBufferBoundForTransformFeedback;
3178 }
3179 }
3180 else if (elementArrayBuffer->isMapped())
3181 {
3182 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3183 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
3184 // WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3185 return kBufferMapped;
3186 }
3187 }
3188 else
3189 {
3190 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3191 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3192 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3193 if (!context->getState().areClientArraysEnabled() ||
3194 context->getExtensions().webglCompatibility)
3195 {
3196 return kMustHaveElementArrayBinding;
3197 }
3198 }
3199
3200 return nullptr;
3201 }
3202
ValidateDrawElementsInstancedANGLE(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)3203 bool ValidateDrawElementsInstancedANGLE(const Context *context,
3204 PrimitiveMode mode,
3205 GLsizei count,
3206 DrawElementsType type,
3207 const void *indices,
3208 GLsizei primcount)
3209 {
3210 if (!context->getExtensions().instancedArraysANGLE)
3211 {
3212 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3213 return false;
3214 }
3215
3216 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
3217 {
3218 return false;
3219 }
3220
3221 return ValidateDrawInstancedANGLE(context);
3222 }
3223
ValidateDrawElementsInstancedEXT(const Context * context,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)3224 bool ValidateDrawElementsInstancedEXT(const Context *context,
3225 PrimitiveMode mode,
3226 GLsizei count,
3227 DrawElementsType type,
3228 const void *indices,
3229 GLsizei primcount)
3230 {
3231 if (!context->getExtensions().instancedArraysEXT)
3232 {
3233 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3234 return false;
3235 }
3236
3237 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
3238 {
3239 return false;
3240 }
3241
3242 return true;
3243 }
3244
ValidateFramebufferTextureBase(const Context * context,GLenum target,GLenum attachment,TextureID texture,GLint level)3245 bool ValidateFramebufferTextureBase(const Context *context,
3246 GLenum target,
3247 GLenum attachment,
3248 TextureID texture,
3249 GLint level)
3250 {
3251 if (!ValidFramebufferTarget(context, target))
3252 {
3253 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
3254 return false;
3255 }
3256
3257 if (!ValidateAttachmentTarget(context, attachment))
3258 {
3259 return false;
3260 }
3261
3262 if (texture.value != 0)
3263 {
3264 Texture *tex = context->getTexture(texture);
3265
3266 if (tex == nullptr)
3267 {
3268 context->validationError(GL_INVALID_OPERATION, kMissingTexture);
3269 return false;
3270 }
3271
3272 if (level < 0)
3273 {
3274 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
3275 return false;
3276 }
3277 }
3278
3279 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
3280 ASSERT(framebuffer);
3281
3282 if (framebuffer->isDefault())
3283 {
3284 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
3285 return false;
3286 }
3287
3288 return true;
3289 }
3290
ValidateGetUniformBase(const Context * context,ShaderProgramID program,UniformLocation location)3291 bool ValidateGetUniformBase(const Context *context,
3292 ShaderProgramID program,
3293 UniformLocation location)
3294 {
3295 if (program.value == 0)
3296 {
3297 context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
3298 return false;
3299 }
3300
3301 Program *programObject = GetValidProgram(context, program);
3302 if (!programObject)
3303 {
3304 return false;
3305 }
3306
3307 if (!programObject || !programObject->isLinked())
3308 {
3309 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
3310 return false;
3311 }
3312
3313 if (!programObject->isValidUniformLocation(location))
3314 {
3315 context->validationError(GL_INVALID_OPERATION, kInvalidUniformLocation);
3316 return false;
3317 }
3318
3319 return true;
3320 }
3321
ValidateSizedGetUniform(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,GLsizei * length)3322 static bool ValidateSizedGetUniform(const Context *context,
3323 ShaderProgramID program,
3324 UniformLocation location,
3325 GLsizei bufSize,
3326 GLsizei *length)
3327 {
3328 if (length)
3329 {
3330 *length = 0;
3331 }
3332
3333 if (!ValidateGetUniformBase(context, program, location))
3334 {
3335 return false;
3336 }
3337
3338 if (bufSize < 0)
3339 {
3340 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
3341 return false;
3342 }
3343
3344 Program *programObject = context->getProgramResolveLink(program);
3345 ASSERT(programObject);
3346
3347 // sized queries -- ensure the provided buffer is large enough
3348 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3349 size_t requiredBytes = VariableExternalSize(uniform.type);
3350 if (static_cast<size_t>(bufSize) < requiredBytes)
3351 {
3352 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
3353 return false;
3354 }
3355
3356 if (length)
3357 {
3358 *length = VariableComponentCount(uniform.type);
3359 }
3360 return true;
3361 }
3362
ValidateGetnUniformfvEXT(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLfloat * params)3363 bool ValidateGetnUniformfvEXT(const Context *context,
3364 ShaderProgramID program,
3365 UniformLocation location,
3366 GLsizei bufSize,
3367 const GLfloat *params)
3368 {
3369 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3370 }
3371
ValidateGetnUniformfvRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3372 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
3373 ShaderProgramID program,
3374 UniformLocation location,
3375 GLsizei bufSize,
3376 const GLsizei *length,
3377 const GLfloat *params)
3378 {
3379 UNIMPLEMENTED();
3380 return false;
3381 }
3382
ValidateGetnUniformivEXT(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLint * params)3383 bool ValidateGetnUniformivEXT(const Context *context,
3384 ShaderProgramID program,
3385 UniformLocation location,
3386 GLsizei bufSize,
3387 const GLint *params)
3388 {
3389 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3390 }
3391
ValidateGetnUniformivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)3392 bool ValidateGetnUniformivRobustANGLE(const Context *context,
3393 ShaderProgramID program,
3394 UniformLocation location,
3395 GLsizei bufSize,
3396 const GLsizei *length,
3397 const GLint *params)
3398 {
3399 UNIMPLEMENTED();
3400 return false;
3401 }
3402
ValidateGetnUniformuivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)3403 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
3404 ShaderProgramID program,
3405 UniformLocation location,
3406 GLsizei bufSize,
3407 const GLsizei *length,
3408 const GLuint *params)
3409 {
3410 UNIMPLEMENTED();
3411 return false;
3412 }
3413
ValidateGetUniformfvRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3414 bool ValidateGetUniformfvRobustANGLE(const Context *context,
3415 ShaderProgramID program,
3416 UniformLocation location,
3417 GLsizei bufSize,
3418 const GLsizei *length,
3419 const GLfloat *params)
3420 {
3421 if (!ValidateRobustEntryPoint(context, bufSize))
3422 {
3423 return false;
3424 }
3425
3426 GLsizei writeLength = 0;
3427
3428 // bufSize is validated in ValidateSizedGetUniform
3429 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3430 {
3431 return false;
3432 }
3433
3434 SetRobustLengthParam(length, writeLength);
3435
3436 return true;
3437 }
3438
ValidateGetUniformivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)3439 bool ValidateGetUniformivRobustANGLE(const Context *context,
3440 ShaderProgramID program,
3441 UniformLocation location,
3442 GLsizei bufSize,
3443 const GLsizei *length,
3444 const GLint *params)
3445 {
3446 if (!ValidateRobustEntryPoint(context, bufSize))
3447 {
3448 return false;
3449 }
3450
3451 GLsizei writeLength = 0;
3452
3453 // bufSize is validated in ValidateSizedGetUniform
3454 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3455 {
3456 return false;
3457 }
3458
3459 SetRobustLengthParam(length, writeLength);
3460
3461 return true;
3462 }
3463
ValidateGetUniformuivRobustANGLE(const Context * context,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)3464 bool ValidateGetUniformuivRobustANGLE(const Context *context,
3465 ShaderProgramID program,
3466 UniformLocation location,
3467 GLsizei bufSize,
3468 const GLsizei *length,
3469 const GLuint *params)
3470 {
3471 if (!ValidateRobustEntryPoint(context, bufSize))
3472 {
3473 return false;
3474 }
3475
3476 if (context->getClientMajorVersion() < 3)
3477 {
3478 context->validationError(GL_INVALID_OPERATION, kES3Required);
3479 return false;
3480 }
3481
3482 GLsizei writeLength = 0;
3483
3484 // bufSize is validated in ValidateSizedGetUniform
3485 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3486 {
3487 return false;
3488 }
3489
3490 SetRobustLengthParam(length, writeLength);
3491
3492 return true;
3493 }
3494
ValidateDiscardFramebufferBase(const Context * context,GLenum target,GLsizei numAttachments,const GLenum * attachments,bool defaultFramebuffer)3495 bool ValidateDiscardFramebufferBase(const Context *context,
3496 GLenum target,
3497 GLsizei numAttachments,
3498 const GLenum *attachments,
3499 bool defaultFramebuffer)
3500 {
3501 if (numAttachments < 0)
3502 {
3503 context->validationError(GL_INVALID_VALUE, kNegativeAttachments);
3504 return false;
3505 }
3506
3507 for (GLsizei i = 0; i < numAttachments; ++i)
3508 {
3509 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
3510 {
3511 if (defaultFramebuffer)
3512 {
3513 context->validationError(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
3514 return false;
3515 }
3516
3517 if (attachments[i] >=
3518 GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
3519 {
3520 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
3521 return false;
3522 }
3523 }
3524 else
3525 {
3526 switch (attachments[i])
3527 {
3528 case GL_DEPTH_ATTACHMENT:
3529 case GL_STENCIL_ATTACHMENT:
3530 case GL_DEPTH_STENCIL_ATTACHMENT:
3531 if (defaultFramebuffer)
3532 {
3533 context->validationError(GL_INVALID_ENUM,
3534 kDefaultFramebufferInvalidAttachment);
3535 return false;
3536 }
3537 break;
3538 case GL_COLOR:
3539 case GL_DEPTH:
3540 case GL_STENCIL:
3541 if (!defaultFramebuffer)
3542 {
3543 context->validationError(GL_INVALID_ENUM,
3544 kDefaultFramebufferInvalidAttachment);
3545 return false;
3546 }
3547 break;
3548 default:
3549 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
3550 return false;
3551 }
3552 }
3553 }
3554
3555 return true;
3556 }
3557
ValidateInsertEventMarkerEXT(const Context * context,GLsizei length,const char * marker)3558 bool ValidateInsertEventMarkerEXT(const Context *context, GLsizei length, const char *marker)
3559 {
3560 if (!context->getExtensions().debugMarker)
3561 {
3562 // The debug marker calls should not set error state
3563 // However, it seems reasonable to set an error state if the extension is not enabled
3564 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3565 return false;
3566 }
3567
3568 // Note that debug marker calls must not set error state
3569 if (length < 0)
3570 {
3571 return false;
3572 }
3573
3574 if (marker == nullptr)
3575 {
3576 return false;
3577 }
3578
3579 return true;
3580 }
3581
ValidatePushGroupMarkerEXT(const Context * context,GLsizei length,const char * marker)3582 bool ValidatePushGroupMarkerEXT(const Context *context, GLsizei length, const char *marker)
3583 {
3584 if (!context->getExtensions().debugMarker)
3585 {
3586 // The debug marker calls should not set error state
3587 // However, it seems reasonable to set an error state if the extension is not enabled
3588 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3589 return false;
3590 }
3591
3592 // Note that debug marker calls must not set error state
3593 if (length < 0)
3594 {
3595 return false;
3596 }
3597
3598 if (length > 0 && marker == nullptr)
3599 {
3600 return false;
3601 }
3602
3603 return true;
3604 }
3605
ValidateEGLImageTargetTexture2DOES(const Context * context,TextureType type,GLeglImageOES image)3606 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
3607 TextureType type,
3608 GLeglImageOES image)
3609 {
3610 if (!context->getExtensions().eglImageOES && !context->getExtensions().eglImageExternalOES)
3611 {
3612 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3613 return false;
3614 }
3615
3616 switch (type)
3617 {
3618 case TextureType::_2D:
3619 if (!context->getExtensions().eglImageOES)
3620 {
3621 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3622 }
3623 break;
3624
3625 case TextureType::_2DArray:
3626 if (!context->getExtensions().eglImageArray)
3627 {
3628 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3629 }
3630 break;
3631
3632 case TextureType::External:
3633 if (!context->getExtensions().eglImageExternalOES)
3634 {
3635 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3636 }
3637 break;
3638
3639 default:
3640 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
3641 return false;
3642 }
3643
3644 egl::Image *imageObject = static_cast<egl::Image *>(image);
3645
3646 ASSERT(context->getDisplay());
3647 if (!context->getDisplay()->isValidImage(imageObject))
3648 {
3649 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
3650 return false;
3651 }
3652
3653 if (imageObject->getSamples() > 0)
3654 {
3655 context->validationError(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
3656 return false;
3657 }
3658
3659 if (!imageObject->isTexturable(context))
3660 {
3661 context->validationError(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
3662 return false;
3663 }
3664
3665 if (imageObject->isLayered() && type != TextureType::_2DArray)
3666 {
3667 context->validationError(GL_INVALID_OPERATION,
3668 "Image has more than 1 layer, target must be TEXTURE_2D_ARRAY");
3669 return false;
3670 }
3671
3672 return true;
3673 }
3674
ValidateEGLImageTargetRenderbufferStorageOES(const Context * context,GLenum target,GLeglImageOES image)3675 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
3676 GLenum target,
3677 GLeglImageOES image)
3678 {
3679 if (!context->getExtensions().eglImageOES)
3680 {
3681 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
3682 return false;
3683 }
3684
3685 switch (target)
3686 {
3687 case GL_RENDERBUFFER:
3688 break;
3689
3690 default:
3691 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
3692 return false;
3693 }
3694
3695 egl::Image *imageObject = static_cast<egl::Image *>(image);
3696
3697 ASSERT(context->getDisplay());
3698 if (!context->getDisplay()->isValidImage(imageObject))
3699 {
3700 context->validationError(GL_INVALID_VALUE, kInvalidEGLImage);
3701 return false;
3702 }
3703
3704 if (!imageObject->isRenderable(context))
3705 {
3706 context->validationError(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
3707 return false;
3708 }
3709
3710 return true;
3711 }
3712
ValidateBindVertexArrayBase(const Context * context,VertexArrayID array)3713 bool ValidateBindVertexArrayBase(const Context *context, VertexArrayID array)
3714 {
3715 if (!context->isVertexArrayGenerated(array))
3716 {
3717 // The default VAO should always exist
3718 ASSERT(array.value != 0);
3719 context->validationError(GL_INVALID_OPERATION, kInvalidVertexArray);
3720 return false;
3721 }
3722
3723 return true;
3724 }
3725
ValidateProgramBinaryBase(const Context * context,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)3726 bool ValidateProgramBinaryBase(const Context *context,
3727 ShaderProgramID program,
3728 GLenum binaryFormat,
3729 const void *binary,
3730 GLint length)
3731 {
3732 Program *programObject = GetValidProgram(context, program);
3733 if (programObject == nullptr)
3734 {
3735 return false;
3736 }
3737
3738 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3739 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3740 programBinaryFormats.end())
3741 {
3742 context->validationError(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
3743 return false;
3744 }
3745
3746 if (context->hasActiveTransformFeedback(program))
3747 {
3748 // ES 3.0.4 section 2.15 page 91
3749 context->validationError(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
3750 return false;
3751 }
3752
3753 return true;
3754 }
3755
ValidateGetProgramBinaryBase(const Context * context,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)3756 bool ValidateGetProgramBinaryBase(const Context *context,
3757 ShaderProgramID program,
3758 GLsizei bufSize,
3759 const GLsizei *length,
3760 const GLenum *binaryFormat,
3761 const void *binary)
3762 {
3763 Program *programObject = GetValidProgram(context, program);
3764 if (programObject == nullptr)
3765 {
3766 return false;
3767 }
3768
3769 if (!programObject->isLinked())
3770 {
3771 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
3772 return false;
3773 }
3774
3775 if (context->getCaps().programBinaryFormats.empty())
3776 {
3777 context->validationError(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
3778 return false;
3779 }
3780
3781 return true;
3782 }
3783
ValidateDrawBuffersBase(const Context * context,GLsizei n,const GLenum * bufs)3784 bool ValidateDrawBuffersBase(const Context *context, GLsizei n, const GLenum *bufs)
3785 {
3786 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3787 if (n < 0)
3788 {
3789 context->validationError(GL_INVALID_VALUE, kNegativeCount);
3790 return false;
3791 }
3792 if (n > context->getCaps().maxDrawBuffers)
3793 {
3794 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
3795 return false;
3796 }
3797
3798 ASSERT(context->getState().getDrawFramebuffer());
3799 FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
3800 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3801
3802 // This should come first before the check for the default frame buffer
3803 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3804 // rather than INVALID_OPERATION
3805 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3806 {
3807 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3808
3809 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
3810 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3811 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
3812 {
3813 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
3814 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3815 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3816 // 3.1 is still a bit ambiguous about the error, but future specs are
3817 // expected to clarify that GL_INVALID_ENUM is the correct error.
3818 context->validationError(GL_INVALID_ENUM, kInvalidDrawBuffer);
3819 return false;
3820 }
3821 else if (bufs[colorAttachment] >= maxColorAttachment)
3822 {
3823 context->validationError(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
3824 return false;
3825 }
3826 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3827 frameBufferId.value != 0)
3828 {
3829 // INVALID_OPERATION-GL is bound to buffer and ith argument
3830 // is not COLOR_ATTACHMENTi or NONE
3831 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
3832 return false;
3833 }
3834 }
3835
3836 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3837 // and n is not 1 or bufs is bound to value other than BACK and NONE
3838 if (frameBufferId.value == 0)
3839 {
3840 if (n != 1)
3841 {
3842 context->validationError(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
3843 return false;
3844 }
3845
3846 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3847 {
3848 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
3849 return false;
3850 }
3851 }
3852
3853 return true;
3854 }
3855
ValidateGetBufferPointervBase(const Context * context,BufferBinding target,GLenum pname,GLsizei * length,void * const * params)3856 bool ValidateGetBufferPointervBase(const Context *context,
3857 BufferBinding target,
3858 GLenum pname,
3859 GLsizei *length,
3860 void *const *params)
3861 {
3862 if (length)
3863 {
3864 *length = 0;
3865 }
3866
3867 if (!context->isValidBufferBinding(target))
3868 {
3869 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3870 return false;
3871 }
3872
3873 switch (pname)
3874 {
3875 case GL_BUFFER_MAP_POINTER:
3876 break;
3877
3878 default:
3879 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
3880 return false;
3881 }
3882
3883 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3884 // target bound to zero generate an INVALID_OPERATION error."
3885 // GLES 3.1 section 6.6 explicitly specifies this error.
3886 if (context->getState().getTargetBuffer(target) == nullptr)
3887 {
3888 context->validationError(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
3889 return false;
3890 }
3891
3892 if (length)
3893 {
3894 *length = 1;
3895 }
3896
3897 return true;
3898 }
3899
ValidateUnmapBufferBase(const Context * context,BufferBinding target)3900 bool ValidateUnmapBufferBase(const Context *context, BufferBinding target)
3901 {
3902 if (!context->isValidBufferBinding(target))
3903 {
3904 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3905 return false;
3906 }
3907
3908 Buffer *buffer = context->getState().getTargetBuffer(target);
3909
3910 if (buffer == nullptr || !buffer->isMapped())
3911 {
3912 context->validationError(GL_INVALID_OPERATION, kBufferNotMapped);
3913 return false;
3914 }
3915
3916 return true;
3917 }
3918
ValidateMapBufferRangeBase(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)3919 bool ValidateMapBufferRangeBase(const Context *context,
3920 BufferBinding target,
3921 GLintptr offset,
3922 GLsizeiptr length,
3923 GLbitfield access)
3924 {
3925 if (!context->isValidBufferBinding(target))
3926 {
3927 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
3928 return false;
3929 }
3930
3931 if (offset < 0)
3932 {
3933 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
3934 return false;
3935 }
3936
3937 if (length < 0)
3938 {
3939 context->validationError(GL_INVALID_VALUE, kNegativeLength);
3940 return false;
3941 }
3942
3943 Buffer *buffer = context->getState().getTargetBuffer(target);
3944
3945 if (!buffer)
3946 {
3947 context->validationError(GL_INVALID_OPERATION, kBufferNotMappable);
3948 return false;
3949 }
3950
3951 // Check for buffer overflow
3952 CheckedNumeric<size_t> checkedOffset(offset);
3953 auto checkedSize = checkedOffset + length;
3954
3955 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
3956 {
3957 context->validationError(GL_INVALID_VALUE, kMapOutOfRange);
3958 return false;
3959 }
3960
3961 // Check for invalid bits in the mask
3962 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3963 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3964 GL_MAP_UNSYNCHRONIZED_BIT;
3965
3966 if (access & ~(allAccessBits))
3967 {
3968 context->validationError(GL_INVALID_VALUE, kInvalidAccessBits);
3969 return false;
3970 }
3971
3972 if (length == 0)
3973 {
3974 context->validationError(GL_INVALID_OPERATION, kLengthZero);
3975 return false;
3976 }
3977
3978 if (buffer->isMapped())
3979 {
3980 context->validationError(GL_INVALID_OPERATION, kBufferAlreadyMapped);
3981 return false;
3982 }
3983
3984 // Check for invalid bit combinations
3985 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3986 {
3987 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
3988 return false;
3989 }
3990
3991 GLbitfield writeOnlyBits =
3992 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3993
3994 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3995 {
3996 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
3997 return false;
3998 }
3999
4000 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4001 {
4002 context->validationError(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
4003 return false;
4004 }
4005
4006 return ValidateMapBufferBase(context, target);
4007 }
4008
ValidateFlushMappedBufferRangeBase(const Context * context,BufferBinding target,GLintptr offset,GLsizeiptr length)4009 bool ValidateFlushMappedBufferRangeBase(const Context *context,
4010 BufferBinding target,
4011 GLintptr offset,
4012 GLsizeiptr length)
4013 {
4014 if (offset < 0)
4015 {
4016 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
4017 return false;
4018 }
4019
4020 if (length < 0)
4021 {
4022 context->validationError(GL_INVALID_VALUE, kNegativeLength);
4023 return false;
4024 }
4025
4026 if (!context->isValidBufferBinding(target))
4027 {
4028 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
4029 return false;
4030 }
4031
4032 Buffer *buffer = context->getState().getTargetBuffer(target);
4033
4034 if (buffer == nullptr)
4035 {
4036 context->validationError(GL_INVALID_OPERATION, kInvalidFlushZero);
4037 return false;
4038 }
4039
4040 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4041 {
4042 context->validationError(GL_INVALID_OPERATION, kInvalidFlushTarget);
4043 return false;
4044 }
4045
4046 // Check for buffer overflow
4047 CheckedNumeric<size_t> checkedOffset(offset);
4048 auto checkedSize = checkedOffset + length;
4049
4050 if (!checkedSize.IsValid() ||
4051 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
4052 {
4053 context->validationError(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
4054 return false;
4055 }
4056
4057 return true;
4058 }
4059
ValidateGenOrDelete(const Context * context,GLint n)4060 bool ValidateGenOrDelete(const Context *context, GLint n)
4061 {
4062 if (n < 0)
4063 {
4064 context->validationError(GL_INVALID_VALUE, kNegativeCount);
4065 return false;
4066 }
4067 return true;
4068 }
4069
ValidateRobustEntryPoint(const Context * context,GLsizei bufSize)4070 bool ValidateRobustEntryPoint(const Context *context, GLsizei bufSize)
4071 {
4072 if (!context->getExtensions().robustClientMemory)
4073 {
4074 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4075 return false;
4076 }
4077
4078 if (bufSize < 0)
4079 {
4080 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
4081 return false;
4082 }
4083
4084 return true;
4085 }
4086
ValidateRobustBufferSize(const Context * context,GLsizei bufSize,GLsizei numParams)4087 bool ValidateRobustBufferSize(const Context *context, GLsizei bufSize, GLsizei numParams)
4088 {
4089 if (bufSize < numParams)
4090 {
4091 context->validationError(GL_INVALID_OPERATION, kInsufficientParams);
4092 return false;
4093 }
4094
4095 return true;
4096 }
4097
ValidateGetFramebufferAttachmentParameterivBase(const Context * context,GLenum target,GLenum attachment,GLenum pname,GLsizei * numParams)4098 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
4099 GLenum target,
4100 GLenum attachment,
4101 GLenum pname,
4102 GLsizei *numParams)
4103 {
4104 if (!ValidFramebufferTarget(context, target))
4105 {
4106 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
4107 return false;
4108 }
4109
4110 int clientVersion = context->getClientMajorVersion();
4111
4112 switch (pname)
4113 {
4114 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4115 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4116 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4117 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4118 break;
4119
4120 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
4121 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
4122 if (clientVersion < 3 ||
4123 !(context->getExtensions().multiview || context->getExtensions().multiview2))
4124 {
4125 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4126 return false;
4127 }
4128 break;
4129
4130 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
4131 if (!context->getExtensions().multisampledRenderToTexture)
4132 {
4133 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4134 return false;
4135 }
4136 break;
4137
4138 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4139 if (clientVersion < 3 && !context->getExtensions().sRGB)
4140 {
4141 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4142 return false;
4143 }
4144 break;
4145
4146 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4147 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4148 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4149 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4150 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4151 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4152 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4153 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4154 if (clientVersion < 3)
4155 {
4156 context->validationError(GL_INVALID_ENUM, kES3Required);
4157 return false;
4158 }
4159 break;
4160
4161 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4162 if (!context->getExtensions().geometryShader)
4163 {
4164 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4165 return false;
4166 }
4167 break;
4168
4169 default:
4170 context->validationError(GL_INVALID_ENUM, kInvalidPname);
4171 return false;
4172 }
4173
4174 // Determine if the attachment is a valid enum
4175 switch (attachment)
4176 {
4177 case GL_BACK:
4178 case GL_DEPTH:
4179 case GL_STENCIL:
4180 if (clientVersion < 3)
4181 {
4182 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4183 return false;
4184 }
4185 break;
4186
4187 case GL_DEPTH_STENCIL_ATTACHMENT:
4188 if (clientVersion < 3 && !context->isWebGL1())
4189 {
4190 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4191 return false;
4192 }
4193 break;
4194
4195 case GL_COLOR_ATTACHMENT0:
4196 case GL_DEPTH_ATTACHMENT:
4197 case GL_STENCIL_ATTACHMENT:
4198 break;
4199
4200 default:
4201 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4202 attachment < GL_COLOR_ATTACHMENT0_EXT ||
4203 (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
4204 static_cast<GLuint>(context->getCaps().maxColorAttachments))
4205 {
4206 context->validationError(GL_INVALID_ENUM, kInvalidAttachment);
4207 return false;
4208 }
4209 break;
4210 }
4211
4212 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
4213 ASSERT(framebuffer);
4214
4215 if (framebuffer->isDefault())
4216 {
4217 if (clientVersion < 3)
4218 {
4219 context->validationError(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
4220 return false;
4221 }
4222
4223 switch (attachment)
4224 {
4225 case GL_BACK:
4226 case GL_DEPTH:
4227 case GL_STENCIL:
4228 break;
4229
4230 default:
4231 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4232 return false;
4233 }
4234 }
4235 else
4236 {
4237 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4238 {
4239 // Valid attachment query
4240 }
4241 else
4242 {
4243 switch (attachment)
4244 {
4245 case GL_DEPTH_ATTACHMENT:
4246 case GL_STENCIL_ATTACHMENT:
4247 break;
4248
4249 case GL_DEPTH_STENCIL_ATTACHMENT:
4250 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
4251 {
4252 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4253 return false;
4254 }
4255 break;
4256
4257 default:
4258 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4259 return false;
4260 }
4261 }
4262 }
4263
4264 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
4265 if (attachmentObject)
4266 {
4267 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4268 attachmentObject->type() == GL_TEXTURE ||
4269 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4270
4271 switch (pname)
4272 {
4273 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4274 if (attachmentObject->type() != GL_RENDERBUFFER &&
4275 attachmentObject->type() != GL_TEXTURE)
4276 {
4277 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4278 return false;
4279 }
4280 break;
4281
4282 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4283 if (attachmentObject->type() != GL_TEXTURE)
4284 {
4285 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4286 return false;
4287 }
4288 break;
4289
4290 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4291 if (attachmentObject->type() != GL_TEXTURE)
4292 {
4293 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4294 return false;
4295 }
4296 break;
4297
4298 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4299 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4300 {
4301 context->validationError(GL_INVALID_OPERATION, kInvalidAttachment);
4302 return false;
4303 }
4304 break;
4305
4306 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4307 if (attachmentObject->type() != GL_TEXTURE)
4308 {
4309 context->validationError(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
4310 return false;
4311 }
4312 break;
4313
4314 default:
4315 break;
4316 }
4317 }
4318 else
4319 {
4320 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4321 // is NONE, then querying any other pname will generate INVALID_ENUM.
4322
4323 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4324 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4325 // INVALID_OPERATION for all other pnames
4326
4327 switch (pname)
4328 {
4329 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4330 break;
4331
4332 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4333 if (clientVersion < 3)
4334 {
4335 context->validationError(GL_INVALID_ENUM,
4336 kInvalidFramebufferAttachmentParameter);
4337 return false;
4338 }
4339 break;
4340
4341 default:
4342 if (clientVersion < 3)
4343 {
4344 context->validationError(GL_INVALID_ENUM,
4345 kInvalidFramebufferAttachmentParameter);
4346 return false;
4347 }
4348 else
4349 {
4350 context->validationError(GL_INVALID_OPERATION,
4351 kInvalidFramebufferAttachmentParameter);
4352 return false;
4353 }
4354 }
4355 }
4356
4357 if (numParams)
4358 {
4359 *numParams = 1;
4360 }
4361
4362 return true;
4363 }
4364
ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context * context,GLenum target,GLenum attachment,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4365 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
4366 GLenum target,
4367 GLenum attachment,
4368 GLenum pname,
4369 GLsizei bufSize,
4370 const GLsizei *length,
4371 const GLint *params)
4372 {
4373 if (!ValidateRobustEntryPoint(context, bufSize))
4374 {
4375 return false;
4376 }
4377
4378 GLsizei numParams = 0;
4379 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4380 &numParams))
4381 {
4382 return false;
4383 }
4384
4385 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4386 {
4387 return false;
4388 }
4389
4390 SetRobustLengthParam(length, numParams);
4391
4392 return true;
4393 }
4394
ValidateGetBufferParameterivRobustANGLE(const Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4395 bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
4396 BufferBinding target,
4397 GLenum pname,
4398 GLsizei bufSize,
4399 const GLsizei *length,
4400 const GLint *params)
4401 {
4402 if (!ValidateRobustEntryPoint(context, bufSize))
4403 {
4404 return false;
4405 }
4406
4407 GLsizei numParams = 0;
4408
4409 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
4410 {
4411 return false;
4412 }
4413
4414 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4415 {
4416 return false;
4417 }
4418
4419 SetRobustLengthParam(length, numParams);
4420 return true;
4421 }
4422
ValidateGetBufferParameteri64vRobustANGLE(const Context * context,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint64 * params)4423 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
4424 BufferBinding target,
4425 GLenum pname,
4426 GLsizei bufSize,
4427 const GLsizei *length,
4428 const GLint64 *params)
4429 {
4430 GLsizei numParams = 0;
4431
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
4437 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
4438 {
4439 return false;
4440 }
4441
4442 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4443 {
4444 return false;
4445 }
4446
4447 SetRobustLengthParam(length, numParams);
4448
4449 return true;
4450 }
4451
ValidateGetProgramivBase(const Context * context,ShaderProgramID program,GLenum pname,GLsizei * numParams)4452 bool ValidateGetProgramivBase(const Context *context,
4453 ShaderProgramID program,
4454 GLenum pname,
4455 GLsizei *numParams)
4456 {
4457 // Currently, all GetProgramiv queries return 1 parameter
4458 if (numParams)
4459 {
4460 *numParams = 1;
4461 }
4462
4463 if (context->isContextLost())
4464 {
4465 context->validationError(GL_CONTEXT_LOST, kContextLost);
4466
4467 if (context->getExtensions().parallelShaderCompile && pname == GL_COMPLETION_STATUS_KHR)
4468 {
4469 // Generate an error but still return true, the context still needs to return a
4470 // value in this case.
4471 return true;
4472 }
4473 else
4474 {
4475 return false;
4476 }
4477 }
4478
4479 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4480 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4481 ? GetValidProgramNoResolve(context, program)
4482 : GetValidProgram(context, program);
4483 if (!programObject)
4484 {
4485 return false;
4486 }
4487
4488 switch (pname)
4489 {
4490 case GL_DELETE_STATUS:
4491 case GL_LINK_STATUS:
4492 case GL_VALIDATE_STATUS:
4493 case GL_INFO_LOG_LENGTH:
4494 case GL_ATTACHED_SHADERS:
4495 case GL_ACTIVE_ATTRIBUTES:
4496 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4497 case GL_ACTIVE_UNIFORMS:
4498 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4499 break;
4500
4501 case GL_PROGRAM_BINARY_LENGTH:
4502 if (context->getClientMajorVersion() < 3 &&
4503 !context->getExtensions().getProgramBinaryOES)
4504 {
4505 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4506 return false;
4507 }
4508 break;
4509
4510 case GL_ACTIVE_UNIFORM_BLOCKS:
4511 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4512 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4513 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4514 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4515 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4516 if (context->getClientMajorVersion() < 3)
4517 {
4518 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
4519 return false;
4520 }
4521 break;
4522
4523 case GL_PROGRAM_SEPARABLE:
4524 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
4525 if (context->getClientVersion() < Version(3, 1))
4526 {
4527 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
4528 return false;
4529 }
4530 break;
4531
4532 case GL_COMPUTE_WORK_GROUP_SIZE:
4533 if (context->getClientVersion() < Version(3, 1))
4534 {
4535 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
4536 return false;
4537 }
4538
4539 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4540 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4541 // program which has not been linked successfully, or which does not contain objects to
4542 // form a compute shader.
4543 if (!programObject->isLinked())
4544 {
4545 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4546 return false;
4547 }
4548 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
4549 {
4550 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
4551 return false;
4552 }
4553 break;
4554
4555 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4556 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4557 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4558 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4559 if (!context->getExtensions().geometryShader)
4560 {
4561 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4562 return false;
4563 }
4564
4565 // [EXT_geometry_shader] Chapter 7.12
4566 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4567 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4568 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4569 // successfully, or which does not contain objects to form a geometry shader.
4570 if (!programObject->isLinked())
4571 {
4572 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
4573 return false;
4574 }
4575 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
4576 {
4577 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
4578 return false;
4579 }
4580 break;
4581
4582 case GL_COMPLETION_STATUS_KHR:
4583 if (!context->getExtensions().parallelShaderCompile)
4584 {
4585 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
4586 return false;
4587 }
4588 break;
4589
4590 default:
4591 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
4592 return false;
4593 }
4594
4595 return true;
4596 }
4597
ValidateGetProgramivRobustANGLE(const Context * context,ShaderProgramID program,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4598 bool ValidateGetProgramivRobustANGLE(const Context *context,
4599 ShaderProgramID program,
4600 GLenum pname,
4601 GLsizei bufSize,
4602 const GLsizei *length,
4603 const GLint *params)
4604 {
4605 if (!ValidateRobustEntryPoint(context, bufSize))
4606 {
4607 return false;
4608 }
4609
4610 GLsizei numParams = 0;
4611
4612 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
4613 {
4614 return false;
4615 }
4616
4617 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4618 {
4619 return false;
4620 }
4621
4622 SetRobustLengthParam(length, numParams);
4623
4624 return true;
4625 }
4626
ValidateGetRenderbufferParameterivRobustANGLE(const Context * context,GLenum target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4627 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
4628 GLenum target,
4629 GLenum pname,
4630 GLsizei bufSize,
4631 const GLsizei *length,
4632 const GLint *params)
4633 {
4634 if (!ValidateRobustEntryPoint(context, bufSize))
4635 {
4636 return false;
4637 }
4638
4639 GLsizei numParams = 0;
4640
4641 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
4642 {
4643 return false;
4644 }
4645
4646 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4647 {
4648 return false;
4649 }
4650
4651 SetRobustLengthParam(length, numParams);
4652
4653 return true;
4654 }
4655
ValidateGetShaderivRobustANGLE(const Context * context,ShaderProgramID shader,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4656 bool ValidateGetShaderivRobustANGLE(const Context *context,
4657 ShaderProgramID shader,
4658 GLenum pname,
4659 GLsizei bufSize,
4660 const GLsizei *length,
4661 const GLint *params)
4662 {
4663 if (!ValidateRobustEntryPoint(context, bufSize))
4664 {
4665 return false;
4666 }
4667
4668 GLsizei numParams = 0;
4669
4670 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
4671 {
4672 return false;
4673 }
4674
4675 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4676 {
4677 return false;
4678 }
4679
4680 SetRobustLengthParam(length, numParams);
4681
4682 return true;
4683 }
4684
ValidateGetTexParameterfvRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4685 bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
4686 TextureType target,
4687 GLenum pname,
4688 GLsizei bufSize,
4689 const GLsizei *length,
4690 const GLfloat *params)
4691 {
4692 if (!ValidateRobustEntryPoint(context, bufSize))
4693 {
4694 return false;
4695 }
4696
4697 GLsizei numParams = 0;
4698
4699 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
4700 {
4701 return false;
4702 }
4703
4704 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4705 {
4706 return false;
4707 }
4708
4709 SetRobustLengthParam(length, numParams);
4710
4711 return true;
4712 }
4713
ValidateGetTexParameterivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4714 bool ValidateGetTexParameterivRobustANGLE(const Context *context,
4715 TextureType target,
4716 GLenum pname,
4717 GLsizei bufSize,
4718 const GLsizei *length,
4719 const GLint *params)
4720 {
4721
4722 if (!ValidateRobustEntryPoint(context, bufSize))
4723 {
4724 return false;
4725 }
4726 GLsizei numParams = 0;
4727 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
4728 {
4729 return false;
4730 }
4731
4732 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4733 {
4734 return false;
4735 }
4736
4737 SetRobustLengthParam(length, numParams);
4738 return true;
4739 }
4740
ValidateGetTexParameterIivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4741 bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
4742 TextureType target,
4743 GLenum pname,
4744 GLsizei bufSize,
4745 const GLsizei *length,
4746 const GLint *params)
4747 {
4748 UNIMPLEMENTED();
4749 return false;
4750 }
4751
ValidateGetTexParameterIuivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)4752 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
4753 TextureType target,
4754 GLenum pname,
4755 GLsizei bufSize,
4756 const GLsizei *length,
4757 const GLuint *params)
4758 {
4759 UNIMPLEMENTED();
4760 return false;
4761 }
4762
ValidateTexParameterfvRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLfloat * params)4763 bool ValidateTexParameterfvRobustANGLE(const Context *context,
4764 TextureType target,
4765 GLenum pname,
4766 GLsizei bufSize,
4767 const GLfloat *params)
4768 {
4769 if (!ValidateRobustEntryPoint(context, bufSize))
4770 {
4771 return false;
4772 }
4773
4774 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
4775 }
4776
ValidateTexParameterivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)4777 bool ValidateTexParameterivRobustANGLE(const Context *context,
4778 TextureType target,
4779 GLenum pname,
4780 GLsizei bufSize,
4781 const GLint *params)
4782 {
4783 if (!ValidateRobustEntryPoint(context, bufSize))
4784 {
4785 return false;
4786 }
4787
4788 return ValidateTexParameterBase(context, target, pname, bufSize, true, params);
4789 }
4790
ValidateTexParameterIivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)4791 bool ValidateTexParameterIivRobustANGLE(const Context *context,
4792 TextureType target,
4793 GLenum pname,
4794 GLsizei bufSize,
4795 const GLint *params)
4796 {
4797 UNIMPLEMENTED();
4798 return false;
4799 }
4800
ValidateTexParameterIuivRobustANGLE(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,const GLuint * params)4801 bool ValidateTexParameterIuivRobustANGLE(const Context *context,
4802 TextureType target,
4803 GLenum pname,
4804 GLsizei bufSize,
4805 const GLuint *params)
4806 {
4807 UNIMPLEMENTED();
4808 return false;
4809 }
4810
ValidateGetSamplerParameterfvRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4811 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
4812 SamplerID sampler,
4813 GLenum pname,
4814 GLsizei bufSize,
4815 const GLsizei *length,
4816 const GLfloat *params)
4817 {
4818 if (!ValidateRobustEntryPoint(context, bufSize))
4819 {
4820 return false;
4821 }
4822
4823 GLsizei numParams = 0;
4824
4825 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
4826 {
4827 return false;
4828 }
4829
4830 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4831 {
4832 return false;
4833 }
4834
4835 SetRobustLengthParam(length, numParams);
4836 return true;
4837 }
4838
ValidateGetSamplerParameterivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4839 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
4840 SamplerID sampler,
4841 GLenum pname,
4842 GLsizei bufSize,
4843 const GLsizei *length,
4844 const GLint *params)
4845 {
4846 if (!ValidateRobustEntryPoint(context, bufSize))
4847 {
4848 return false;
4849 }
4850
4851 GLsizei numParams = 0;
4852
4853 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
4854 {
4855 return false;
4856 }
4857
4858 if (!ValidateRobustBufferSize(context, bufSize, numParams))
4859 {
4860 return false;
4861 }
4862
4863 SetRobustLengthParam(length, numParams);
4864 return true;
4865 }
4866
ValidateGetSamplerParameterIivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4867 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
4868 SamplerID sampler,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 const GLsizei *length,
4872 const GLint *params)
4873 {
4874 UNIMPLEMENTED();
4875 return false;
4876 }
4877
ValidateGetSamplerParameterIuivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)4878 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
4879 SamplerID sampler,
4880 GLenum pname,
4881 GLsizei bufSize,
4882 const GLsizei *length,
4883 const GLuint *params)
4884 {
4885 UNIMPLEMENTED();
4886 return false;
4887 }
4888
ValidateSamplerParameterfvRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLfloat * params)4889 bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
4890 SamplerID sampler,
4891 GLenum pname,
4892 GLsizei bufSize,
4893 const GLfloat *params)
4894 {
4895 if (!ValidateRobustEntryPoint(context, bufSize))
4896 {
4897 return false;
4898 }
4899
4900 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
4901 }
4902
ValidateSamplerParameterivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * params)4903 bool ValidateSamplerParameterivRobustANGLE(const Context *context,
4904 SamplerID sampler,
4905 GLenum pname,
4906 GLsizei bufSize,
4907 const GLint *params)
4908 {
4909 if (!ValidateRobustEntryPoint(context, bufSize))
4910 {
4911 return false;
4912 }
4913
4914 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, true, params);
4915 }
4916
ValidateSamplerParameterIivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * param)4917 bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
4918 SamplerID sampler,
4919 GLenum pname,
4920 GLsizei bufSize,
4921 const GLint *param)
4922 {
4923 UNIMPLEMENTED();
4924 return false;
4925 }
4926
ValidateSamplerParameterIuivRobustANGLE(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLuint * param)4927 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
4928 SamplerID sampler,
4929 GLenum pname,
4930 GLsizei bufSize,
4931 const GLuint *param)
4932 {
4933 UNIMPLEMENTED();
4934 return false;
4935 }
4936
ValidateGetVertexAttribfvRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4937 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
4938 GLuint index,
4939 GLenum pname,
4940 GLsizei bufSize,
4941 const GLsizei *length,
4942 const GLfloat *params)
4943 {
4944 if (!ValidateRobustEntryPoint(context, bufSize))
4945 {
4946 return false;
4947 }
4948
4949 GLsizei writeLength = 0;
4950
4951 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
4952 {
4953 return false;
4954 }
4955
4956 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
4957 {
4958 return false;
4959 }
4960
4961 SetRobustLengthParam(length, writeLength);
4962 return true;
4963 }
4964
ValidateGetVertexAttribivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)4965 bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
4966 GLuint index,
4967 GLenum pname,
4968 GLsizei bufSize,
4969 const GLsizei *length,
4970 const GLint *params)
4971 {
4972 if (!ValidateRobustEntryPoint(context, bufSize))
4973 {
4974 return false;
4975 }
4976
4977 GLsizei writeLength = 0;
4978
4979 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
4980 {
4981 return false;
4982 }
4983
4984 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
4985 {
4986 return false;
4987 }
4988
4989 SetRobustLengthParam(length, writeLength);
4990
4991 return true;
4992 }
4993
ValidateGetVertexAttribPointervRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * pointer)4994 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
4995 GLuint index,
4996 GLenum pname,
4997 GLsizei bufSize,
4998 const GLsizei *length,
4999 void *const *pointer)
5000 {
5001 if (!ValidateRobustEntryPoint(context, bufSize))
5002 {
5003 return false;
5004 }
5005
5006 GLsizei writeLength = 0;
5007
5008 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
5009 {
5010 return false;
5011 }
5012
5013 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5014 {
5015 return false;
5016 }
5017
5018 SetRobustLengthParam(length, writeLength);
5019
5020 return true;
5021 }
5022
ValidateGetVertexAttribIivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5023 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
5024 GLuint index,
5025 GLenum pname,
5026 GLsizei bufSize,
5027 const GLsizei *length,
5028 const GLint *params)
5029 {
5030 if (!ValidateRobustEntryPoint(context, bufSize))
5031 {
5032 return false;
5033 }
5034
5035 GLsizei writeLength = 0;
5036
5037 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
5038 {
5039 return false;
5040 }
5041
5042 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5043 {
5044 return false;
5045 }
5046
5047 SetRobustLengthParam(length, writeLength);
5048
5049 return true;
5050 }
5051
ValidateGetVertexAttribIuivRobustANGLE(const Context * context,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)5052 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
5053 GLuint index,
5054 GLenum pname,
5055 GLsizei bufSize,
5056 const GLsizei *length,
5057 const GLuint *params)
5058 {
5059 if (!ValidateRobustEntryPoint(context, bufSize))
5060 {
5061 return false;
5062 }
5063
5064 GLsizei writeLength = 0;
5065
5066 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
5067 {
5068 return false;
5069 }
5070
5071 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5072 {
5073 return false;
5074 }
5075
5076 SetRobustLengthParam(length, writeLength);
5077
5078 return true;
5079 }
5080
ValidateGetActiveUniformBlockivRobustANGLE(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5081 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
5082 ShaderProgramID program,
5083 GLuint uniformBlockIndex,
5084 GLenum pname,
5085 GLsizei bufSize,
5086 const GLsizei *length,
5087 const GLint *params)
5088 {
5089 if (!ValidateRobustEntryPoint(context, bufSize))
5090 {
5091 return false;
5092 }
5093
5094 GLsizei writeLength = 0;
5095
5096 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5097 &writeLength))
5098 {
5099 return false;
5100 }
5101
5102 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
5103 {
5104 return false;
5105 }
5106
5107 SetRobustLengthParam(length, writeLength);
5108
5109 return true;
5110 }
5111
ValidateGetInternalformativRobustANGLE(const Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)5112 bool ValidateGetInternalformativRobustANGLE(const Context *context,
5113 GLenum target,
5114 GLenum internalformat,
5115 GLenum pname,
5116 GLsizei bufSize,
5117 const GLsizei *length,
5118 const GLint *params)
5119 {
5120 if (!ValidateRobustEntryPoint(context, bufSize))
5121 {
5122 return false;
5123 }
5124
5125 GLsizei numParams = 0;
5126
5127 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5128 &numParams))
5129 {
5130 return false;
5131 }
5132
5133 if (!ValidateRobustBufferSize(context, bufSize, numParams))
5134 {
5135 return false;
5136 }
5137
5138 SetRobustLengthParam(length, numParams);
5139
5140 return true;
5141 }
5142
5143 // Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5144 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5145 // specified clear value and the type of a buffer that is being cleared generates an
5146 // INVALID_OPERATION error instead of producing undefined results
ValidateWebGLFramebufferAttachmentClearType(const Context * context,GLint drawbuffer,const GLenum * validComponentTypes,size_t validComponentTypeCount)5147 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
5148 GLint drawbuffer,
5149 const GLenum *validComponentTypes,
5150 size_t validComponentTypeCount)
5151 {
5152 const FramebufferAttachment *attachment =
5153 context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5154 if (attachment)
5155 {
5156 GLenum componentType = attachment->getFormat().info->componentType;
5157 const GLenum *end = validComponentTypes + validComponentTypeCount;
5158 if (std::find(validComponentTypes, end, componentType) == end)
5159 {
5160 context->validationError(GL_INVALID_OPERATION, kNoDefinedClearConversion);
5161 return false;
5162 }
5163 }
5164
5165 return true;
5166 }
5167
ValidateRobustCompressedTexImageBase(const Context * context,GLsizei imageSize,GLsizei dataSize)5168 bool ValidateRobustCompressedTexImageBase(const Context *context,
5169 GLsizei imageSize,
5170 GLsizei dataSize)
5171 {
5172 if (!ValidateRobustEntryPoint(context, dataSize))
5173 {
5174 return false;
5175 }
5176
5177 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
5178 if (pixelUnpackBuffer == nullptr)
5179 {
5180 if (dataSize < imageSize)
5181 {
5182 context->validationError(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
5183 }
5184 }
5185 return true;
5186 }
5187
ValidateGetBufferParameterBase(const Context * context,BufferBinding target,GLenum pname,bool pointerVersion,GLsizei * numParams)5188 bool ValidateGetBufferParameterBase(const Context *context,
5189 BufferBinding target,
5190 GLenum pname,
5191 bool pointerVersion,
5192 GLsizei *numParams)
5193 {
5194 if (numParams)
5195 {
5196 *numParams = 0;
5197 }
5198
5199 if (!context->isValidBufferBinding(target))
5200 {
5201 context->validationError(GL_INVALID_ENUM, kInvalidBufferTypes);
5202 return false;
5203 }
5204
5205 const Buffer *buffer = context->getState().getTargetBuffer(target);
5206 if (!buffer)
5207 {
5208 // A null buffer means that "0" is bound to the requested buffer target
5209 context->validationError(GL_INVALID_OPERATION, kBufferNotBound);
5210 return false;
5211 }
5212
5213 const Extensions &extensions = context->getExtensions();
5214
5215 switch (pname)
5216 {
5217 case GL_BUFFER_USAGE:
5218 case GL_BUFFER_SIZE:
5219 break;
5220
5221 case GL_BUFFER_ACCESS_OES:
5222 if (!extensions.mapBufferOES)
5223 {
5224 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5225 return false;
5226 }
5227 break;
5228
5229 case GL_BUFFER_MAPPED:
5230 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5231 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferOES &&
5232 !extensions.mapBufferRange)
5233 {
5234 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5235 return false;
5236 }
5237 break;
5238
5239 case GL_BUFFER_MAP_POINTER:
5240 if (!pointerVersion)
5241 {
5242 context->validationError(GL_INVALID_ENUM, kInvalidMapPointerQuery);
5243 return false;
5244 }
5245 break;
5246
5247 case GL_BUFFER_ACCESS_FLAGS:
5248 case GL_BUFFER_MAP_OFFSET:
5249 case GL_BUFFER_MAP_LENGTH:
5250 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5251 {
5252 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5253 return false;
5254 }
5255 break;
5256
5257 case GL_MEMORY_SIZE_ANGLE:
5258 if (!context->getExtensions().memorySize)
5259 {
5260 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5261 return false;
5262 }
5263 break;
5264
5265 default:
5266 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5267 return false;
5268 }
5269
5270 // All buffer parameter queries return one value.
5271 if (numParams)
5272 {
5273 *numParams = 1;
5274 }
5275
5276 return true;
5277 }
5278
ValidateGetRenderbufferParameterivBase(const Context * context,GLenum target,GLenum pname,GLsizei * length)5279 bool ValidateGetRenderbufferParameterivBase(const Context *context,
5280 GLenum target,
5281 GLenum pname,
5282 GLsizei *length)
5283 {
5284 if (length)
5285 {
5286 *length = 0;
5287 }
5288
5289 if (target != GL_RENDERBUFFER)
5290 {
5291 context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
5292 return false;
5293 }
5294
5295 Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
5296 if (renderbuffer == nullptr)
5297 {
5298 context->validationError(GL_INVALID_OPERATION, kRenderbufferNotBound);
5299 return false;
5300 }
5301
5302 switch (pname)
5303 {
5304 case GL_RENDERBUFFER_WIDTH:
5305 case GL_RENDERBUFFER_HEIGHT:
5306 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5307 case GL_RENDERBUFFER_RED_SIZE:
5308 case GL_RENDERBUFFER_GREEN_SIZE:
5309 case GL_RENDERBUFFER_BLUE_SIZE:
5310 case GL_RENDERBUFFER_ALPHA_SIZE:
5311 case GL_RENDERBUFFER_DEPTH_SIZE:
5312 case GL_RENDERBUFFER_STENCIL_SIZE:
5313 break;
5314
5315 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5316 if (!context->getExtensions().framebufferMultisample)
5317 {
5318 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5319 return false;
5320 }
5321 break;
5322
5323 case GL_MEMORY_SIZE_ANGLE:
5324 if (!context->getExtensions().memorySize)
5325 {
5326 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5327 return false;
5328 }
5329 break;
5330
5331 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5332 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5333 if (!context->getExtensions().getImageANGLE)
5334 {
5335 context->validationError(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
5336 return false;
5337 }
5338 break;
5339
5340 default:
5341 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5342 return false;
5343 }
5344
5345 if (length)
5346 {
5347 *length = 1;
5348 }
5349 return true;
5350 }
5351
ValidateGetShaderivBase(const Context * context,ShaderProgramID shader,GLenum pname,GLsizei * length)5352 bool ValidateGetShaderivBase(const Context *context,
5353 ShaderProgramID shader,
5354 GLenum pname,
5355 GLsizei *length)
5356 {
5357 if (length)
5358 {
5359 *length = 0;
5360 }
5361
5362 if (context->isContextLost())
5363 {
5364 context->validationError(GL_CONTEXT_LOST, kContextLost);
5365
5366 if (context->getExtensions().parallelShaderCompile && pname == GL_COMPLETION_STATUS_KHR)
5367 {
5368 // Generate an error but still return true, the context still needs to return a
5369 // value in this case.
5370 return true;
5371 }
5372 else
5373 {
5374 return false;
5375 }
5376 }
5377
5378 if (GetValidShader(context, shader) == nullptr)
5379 {
5380 return false;
5381 }
5382
5383 switch (pname)
5384 {
5385 case GL_SHADER_TYPE:
5386 case GL_DELETE_STATUS:
5387 case GL_COMPILE_STATUS:
5388 case GL_INFO_LOG_LENGTH:
5389 case GL_SHADER_SOURCE_LENGTH:
5390 break;
5391
5392 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5393 if (!context->getExtensions().translatedShaderSource)
5394 {
5395 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5396 return false;
5397 }
5398 break;
5399
5400 case GL_COMPLETION_STATUS_KHR:
5401 if (!context->getExtensions().parallelShaderCompile)
5402 {
5403 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
5404 return false;
5405 }
5406 break;
5407
5408 default:
5409 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5410 return false;
5411 }
5412
5413 if (length)
5414 {
5415 *length = 1;
5416 }
5417 return true;
5418 }
5419
ValidateGetTexParameterBase(const Context * context,TextureType target,GLenum pname,GLsizei * length)5420 bool ValidateGetTexParameterBase(const Context *context,
5421 TextureType target,
5422 GLenum pname,
5423 GLsizei *length)
5424 {
5425 if (length)
5426 {
5427 *length = 0;
5428 }
5429
5430 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5431 {
5432 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5433 return false;
5434 }
5435
5436 if (context->getTextureByType(target) == nullptr)
5437 {
5438 // Should only be possible for external textures
5439 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
5440 return false;
5441 }
5442
5443 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5444 {
5445 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5446 return false;
5447 }
5448
5449 switch (pname)
5450 {
5451 case GL_TEXTURE_MAG_FILTER:
5452 case GL_TEXTURE_MIN_FILTER:
5453 case GL_TEXTURE_WRAP_S:
5454 case GL_TEXTURE_WRAP_T:
5455 break;
5456
5457 case GL_TEXTURE_USAGE_ANGLE:
5458 if (!context->getExtensions().textureUsage)
5459 {
5460 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5461 return false;
5462 }
5463 break;
5464
5465 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5466 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5467 {
5468 return false;
5469 }
5470 break;
5471
5472 case GL_TEXTURE_IMMUTABLE_FORMAT:
5473 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5474 {
5475 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5476 return false;
5477 }
5478 break;
5479
5480 case GL_TEXTURE_WRAP_R:
5481 case GL_TEXTURE_IMMUTABLE_LEVELS:
5482 case GL_TEXTURE_SWIZZLE_R:
5483 case GL_TEXTURE_SWIZZLE_G:
5484 case GL_TEXTURE_SWIZZLE_B:
5485 case GL_TEXTURE_SWIZZLE_A:
5486 case GL_TEXTURE_BASE_LEVEL:
5487 case GL_TEXTURE_MAX_LEVEL:
5488 case GL_TEXTURE_MIN_LOD:
5489 case GL_TEXTURE_MAX_LOD:
5490 case GL_TEXTURE_COMPARE_MODE:
5491 case GL_TEXTURE_COMPARE_FUNC:
5492 if (context->getClientMajorVersion() < 3)
5493 {
5494 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES30);
5495 return false;
5496 }
5497 break;
5498
5499 case GL_TEXTURE_SRGB_DECODE_EXT:
5500 if (!context->getExtensions().textureSRGBDecode)
5501 {
5502 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5503 return false;
5504 }
5505 break;
5506
5507 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5508 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
5509 if (context->getClientVersion() < Version(3, 1))
5510 {
5511 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
5512 return false;
5513 }
5514 break;
5515
5516 case GL_GENERATE_MIPMAP:
5517 case GL_TEXTURE_CROP_RECT_OES:
5518 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5519 // after GL_OES_draw_texture functionality implemented
5520 if (context->getClientMajorVersion() > 1)
5521 {
5522 context->validationError(GL_INVALID_ENUM, kGLES1Only);
5523 return false;
5524 }
5525 break;
5526
5527 case GL_MEMORY_SIZE_ANGLE:
5528 if (!context->getExtensions().memorySize)
5529 {
5530 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5531 return false;
5532 }
5533 break;
5534
5535 case GL_TEXTURE_BORDER_COLOR:
5536 if (!context->getExtensions().textureBorderClampOES)
5537 {
5538 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5539 return false;
5540 }
5541 break;
5542
5543 case GL_TEXTURE_NATIVE_ID_ANGLE:
5544 if (!context->getExtensions().textureExternalUpdateANGLE)
5545 {
5546 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
5547 return false;
5548 }
5549 break;
5550
5551 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
5552 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
5553 if (!context->getExtensions().getImageANGLE)
5554 {
5555 context->validationError(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
5556 return false;
5557 }
5558 break;
5559
5560 default:
5561 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5562 return false;
5563 }
5564
5565 if (length)
5566 {
5567 *length = GetTexParameterCount(pname);
5568 }
5569 return true;
5570 }
5571
ValidateGetVertexAttribBase(const Context * context,GLuint index,GLenum pname,GLsizei * length,bool pointer,bool pureIntegerEntryPoint)5572 bool ValidateGetVertexAttribBase(const Context *context,
5573 GLuint index,
5574 GLenum pname,
5575 GLsizei *length,
5576 bool pointer,
5577 bool pureIntegerEntryPoint)
5578 {
5579 if (length)
5580 {
5581 *length = 0;
5582 }
5583
5584 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5585 {
5586 context->validationError(GL_INVALID_OPERATION, kES3Required);
5587 return false;
5588 }
5589
5590 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
5591 {
5592 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
5593 return false;
5594 }
5595
5596 if (pointer)
5597 {
5598 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5599 {
5600 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5601 return false;
5602 }
5603 }
5604 else
5605 {
5606 switch (pname)
5607 {
5608 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5609 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5610 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5611 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5612 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5613 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5614 case GL_CURRENT_VERTEX_ATTRIB:
5615 break;
5616
5617 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5618 static_assert(
5619 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5620 "ANGLE extension enums not equal to GL enums.");
5621 if (context->getClientMajorVersion() < 3 &&
5622 !context->getExtensions().instancedArraysAny())
5623 {
5624 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5625 return false;
5626 }
5627 break;
5628
5629 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5630 if (context->getClientMajorVersion() < 3)
5631 {
5632 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5633 return false;
5634 }
5635 break;
5636
5637 case GL_VERTEX_ATTRIB_BINDING:
5638 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5639 if (context->getClientVersion() < ES_3_1)
5640 {
5641 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
5642 return false;
5643 }
5644 break;
5645
5646 default:
5647 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5648 return false;
5649 }
5650 }
5651
5652 if (length)
5653 {
5654 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5655 {
5656 *length = 4;
5657 }
5658 else
5659 {
5660 *length = 1;
5661 }
5662 }
5663
5664 return true;
5665 }
5666
ValidatePixelPack(const Context * context,GLenum format,GLenum type,GLint x,GLint y,GLsizei width,GLsizei height,GLsizei bufSize,GLsizei * length,const void * pixels)5667 bool ValidatePixelPack(const Context *context,
5668 GLenum format,
5669 GLenum type,
5670 GLint x,
5671 GLint y,
5672 GLsizei width,
5673 GLsizei height,
5674 GLsizei bufSize,
5675 GLsizei *length,
5676 const void *pixels)
5677 {
5678 // Check for pixel pack buffer related API errors
5679 Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
5680 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5681 {
5682 // ...the buffer object's data store is currently mapped.
5683 context->validationError(GL_INVALID_OPERATION, kBufferMapped);
5684 return false;
5685 }
5686 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5687 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5688 {
5689 context->validationError(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
5690 return false;
5691 }
5692
5693 // .. the data would be packed to the buffer object such that the memory writes required
5694 // would exceed the data store size.
5695 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5696 const Extents size(width, height, 1);
5697 const auto &pack = context->getState().getPackState();
5698
5699 GLuint endByte = 0;
5700 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
5701 {
5702 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5703 return false;
5704 }
5705
5706 if (bufSize >= 0)
5707 {
5708 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5709 {
5710 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
5711 return false;
5712 }
5713 }
5714
5715 if (pixelPackBuffer != nullptr)
5716 {
5717 CheckedNumeric<size_t> checkedEndByte(endByte);
5718 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5719 checkedEndByte += checkedOffset;
5720
5721 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5722 {
5723 // Overflow past the end of the buffer
5724 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
5725 return false;
5726 }
5727 }
5728
5729 if (pixelPackBuffer == nullptr && length != nullptr)
5730 {
5731 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5732 {
5733 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5734 return false;
5735 }
5736
5737 *length = static_cast<GLsizei>(endByte);
5738 }
5739
5740 return true;
5741 }
5742
ValidateReadPixelsBase(const Context * context,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,const void * pixels)5743 bool ValidateReadPixelsBase(const Context *context,
5744 GLint x,
5745 GLint y,
5746 GLsizei width,
5747 GLsizei height,
5748 GLenum format,
5749 GLenum type,
5750 GLsizei bufSize,
5751 GLsizei *length,
5752 GLsizei *columns,
5753 GLsizei *rows,
5754 const void *pixels)
5755 {
5756 if (length != nullptr)
5757 {
5758 *length = 0;
5759 }
5760 if (rows != nullptr)
5761 {
5762 *rows = 0;
5763 }
5764 if (columns != nullptr)
5765 {
5766 *columns = 0;
5767 }
5768
5769 if (width < 0 || height < 0)
5770 {
5771 context->validationError(GL_INVALID_VALUE, kNegativeSize);
5772 return false;
5773 }
5774
5775 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
5776 ASSERT(readFramebuffer);
5777
5778 if (!ValidateFramebufferComplete(context, readFramebuffer))
5779 {
5780 return false;
5781 }
5782
5783 // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
5784 // resolved before reading.
5785 if (!readFramebuffer->isDefault() &&
5786 !ValidateFramebufferNotMultisampled(context, readFramebuffer, true))
5787 {
5788 return false;
5789 }
5790
5791 if (readFramebuffer->getReadBufferState() == GL_NONE)
5792 {
5793 context->validationError(GL_INVALID_OPERATION, kReadBufferNone);
5794 return false;
5795 }
5796
5797 const FramebufferAttachment *readBuffer = nullptr;
5798 switch (format)
5799 {
5800 case GL_DEPTH_COMPONENT:
5801 readBuffer = readFramebuffer->getDepthAttachment();
5802 break;
5803 case GL_STENCIL_INDEX_OES:
5804 readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
5805 break;
5806 default:
5807 readBuffer = readFramebuffer->getReadColorAttachment();
5808 break;
5809 }
5810
5811 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5812 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5813 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5814 // situation is an application error that would lead to a crash in ANGLE.
5815 if (readBuffer == nullptr)
5816 {
5817 context->validationError(GL_INVALID_OPERATION, kMissingReadAttachment);
5818 return false;
5819 }
5820
5821 // OVR_multiview2, Revision 1:
5822 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
5823 // the number of views in the current read framebuffer is more than one.
5824 if (readFramebuffer->readDisallowedByMultiview())
5825 {
5826 context->validationError(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
5827 return false;
5828 }
5829
5830 if (context->getExtensions().webglCompatibility)
5831 {
5832 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5833 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5834 // and type before validating the combination of format and type. However, the
5835 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5836 // verifies that GL_INVALID_OPERATION is generated.
5837 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5838 // dEQP/WebGL.
5839 if (!ValidReadPixelsFormatEnum(context, format))
5840 {
5841 context->validationError(GL_INVALID_ENUM, kInvalidFormat);
5842 return false;
5843 }
5844
5845 if (!ValidReadPixelsTypeEnum(context, type))
5846 {
5847 context->validationError(GL_INVALID_ENUM, kInvalidType);
5848 return false;
5849 }
5850 }
5851
5852 GLenum currentFormat = GL_NONE;
5853 GLenum currentType = GL_NONE;
5854
5855 switch (format)
5856 {
5857 case GL_DEPTH_COMPONENT:
5858 case GL_STENCIL_INDEX_OES:
5859 // Only rely on ValidReadPixelsFormatType for depth/stencil formats
5860 break;
5861 default:
5862 currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
5863 currentType = readFramebuffer->getImplementationColorReadType(context);
5864 break;
5865 }
5866
5867 bool validFormatTypeCombination =
5868 ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
5869
5870 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5871 {
5872 context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
5873 return false;
5874 }
5875
5876 if (!ValidatePixelPack(context, format, type, x, y, width, height, bufSize, length, pixels))
5877 {
5878 return false;
5879 }
5880
5881 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
5882 angle::CheckedNumeric<int> clippedExtent(length);
5883 if (start < 0)
5884 {
5885 // "subtract" the area that is less than 0
5886 clippedExtent += start;
5887 }
5888
5889 angle::CheckedNumeric<int> readExtent = start;
5890 readExtent += length;
5891 if (!readExtent.IsValid())
5892 {
5893 return false;
5894 }
5895
5896 if (readExtent.ValueOrDie() > bufferSize)
5897 {
5898 // Subtract the region to the right of the read buffer
5899 clippedExtent -= (readExtent - bufferSize);
5900 }
5901
5902 if (!clippedExtent.IsValid())
5903 {
5904 return false;
5905 }
5906
5907 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5908 return true;
5909 };
5910
5911 GLsizei writtenColumns = 0;
5912 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5913 {
5914 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5915 return false;
5916 }
5917
5918 GLsizei writtenRows = 0;
5919 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5920 {
5921 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
5922 return false;
5923 }
5924
5925 if (columns != nullptr)
5926 {
5927 *columns = writtenColumns;
5928 }
5929
5930 if (rows != nullptr)
5931 {
5932 *rows = writtenRows;
5933 }
5934
5935 return true;
5936 }
5937
5938 template <typename ParamType>
ValidateTexParameterBase(const Context * context,TextureType target,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)5939 bool ValidateTexParameterBase(const Context *context,
5940 TextureType target,
5941 GLenum pname,
5942 GLsizei bufSize,
5943 bool vectorParams,
5944 const ParamType *params)
5945 {
5946 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5947 {
5948 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
5949 return false;
5950 }
5951
5952 if (context->getTextureByType(target) == nullptr)
5953 {
5954 // Should only be possible for external textures
5955 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
5956 return false;
5957 }
5958
5959 const GLsizei minBufSize = GetTexParameterCount(pname);
5960 if (bufSize >= 0 && bufSize < minBufSize)
5961 {
5962 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
5963 return false;
5964 }
5965
5966 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5967 {
5968 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5969 return false;
5970 }
5971
5972 switch (pname)
5973 {
5974 case GL_TEXTURE_WRAP_R:
5975 case GL_TEXTURE_SWIZZLE_R:
5976 case GL_TEXTURE_SWIZZLE_G:
5977 case GL_TEXTURE_SWIZZLE_B:
5978 case GL_TEXTURE_SWIZZLE_A:
5979 case GL_TEXTURE_BASE_LEVEL:
5980 case GL_TEXTURE_MAX_LEVEL:
5981 case GL_TEXTURE_COMPARE_MODE:
5982 case GL_TEXTURE_COMPARE_FUNC:
5983 case GL_TEXTURE_MIN_LOD:
5984 case GL_TEXTURE_MAX_LOD:
5985 if (context->getClientMajorVersion() < 3 &&
5986 !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
5987 {
5988 context->validationError(GL_INVALID_ENUM, kES3Required);
5989 return false;
5990 }
5991 if (target == TextureType::External &&
5992 !context->getExtensions().eglImageExternalEssl3OES)
5993 {
5994 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
5995 return false;
5996 }
5997 if (target == TextureType::VideoImage && !context->getExtensions().webglVideoTexture)
5998 {
5999 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6000 }
6001 break;
6002
6003 case GL_GENERATE_MIPMAP:
6004 case GL_TEXTURE_CROP_RECT_OES:
6005 if (context->getClientMajorVersion() > 1)
6006 {
6007 context->validationError(GL_INVALID_ENUM, kGLES1Only);
6008 return false;
6009 }
6010 break;
6011
6012 default:
6013 break;
6014 }
6015
6016 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
6017 {
6018 switch (pname)
6019 {
6020 case GL_TEXTURE_MIN_FILTER:
6021 case GL_TEXTURE_MAG_FILTER:
6022 case GL_TEXTURE_WRAP_S:
6023 case GL_TEXTURE_WRAP_T:
6024 case GL_TEXTURE_WRAP_R:
6025 case GL_TEXTURE_MIN_LOD:
6026 case GL_TEXTURE_MAX_LOD:
6027 case GL_TEXTURE_COMPARE_MODE:
6028 case GL_TEXTURE_COMPARE_FUNC:
6029 case GL_TEXTURE_BORDER_COLOR:
6030 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6031 return false;
6032 }
6033 }
6034
6035 switch (pname)
6036 {
6037 case GL_TEXTURE_WRAP_S:
6038 case GL_TEXTURE_WRAP_T:
6039 case GL_TEXTURE_WRAP_R:
6040 {
6041 bool restrictedWrapModes = ((target == TextureType::External &&
6042 !context->getExtensions().eglImageExternalWrapModesEXT) ||
6043 target == TextureType::Rectangle);
6044 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
6045 {
6046 return false;
6047 }
6048 }
6049 break;
6050
6051 case GL_TEXTURE_MIN_FILTER:
6052 {
6053 bool restrictedMinFilter =
6054 target == TextureType::External || target == TextureType::Rectangle;
6055 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
6056 {
6057 return false;
6058 }
6059 }
6060 break;
6061
6062 case GL_TEXTURE_MAG_FILTER:
6063 if (!ValidateTextureMagFilterValue(context, params))
6064 {
6065 return false;
6066 }
6067 break;
6068
6069 case GL_TEXTURE_USAGE_ANGLE:
6070 if (!context->getExtensions().textureUsage)
6071 {
6072 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6073 return false;
6074 }
6075
6076 switch (ConvertToGLenum(params[0]))
6077 {
6078 case GL_NONE:
6079 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6080 break;
6081
6082 default:
6083 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6084 return false;
6085 }
6086 break;
6087
6088 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6089 {
6090 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6091 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6092 {
6093 return false;
6094 }
6095 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6096 }
6097 break;
6098
6099 case GL_TEXTURE_MIN_LOD:
6100 case GL_TEXTURE_MAX_LOD:
6101 // any value is permissible
6102 break;
6103
6104 case GL_TEXTURE_COMPARE_MODE:
6105 if (!ValidateTextureCompareModeValue(context, params))
6106 {
6107 return false;
6108 }
6109 break;
6110
6111 case GL_TEXTURE_COMPARE_FUNC:
6112 if (!ValidateTextureCompareFuncValue(context, params))
6113 {
6114 return false;
6115 }
6116 break;
6117
6118 case GL_TEXTURE_SWIZZLE_R:
6119 case GL_TEXTURE_SWIZZLE_G:
6120 case GL_TEXTURE_SWIZZLE_B:
6121 case GL_TEXTURE_SWIZZLE_A:
6122 switch (ConvertToGLenum(params[0]))
6123 {
6124 case GL_RED:
6125 case GL_GREEN:
6126 case GL_BLUE:
6127 case GL_ALPHA:
6128 case GL_ZERO:
6129 case GL_ONE:
6130 break;
6131
6132 default:
6133 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6134 return false;
6135 }
6136 break;
6137
6138 case GL_TEXTURE_BASE_LEVEL:
6139 if (ConvertToGLint(params[0]) < 0)
6140 {
6141 context->validationError(GL_INVALID_VALUE, kBaseLevelNegative);
6142 return false;
6143 }
6144 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
6145 {
6146 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6147 return false;
6148 }
6149 if ((target == TextureType::_2DMultisample ||
6150 target == TextureType::_2DMultisampleArray) &&
6151 static_cast<GLuint>(params[0]) != 0)
6152 {
6153 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6154 return false;
6155 }
6156 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
6157 {
6158 context->validationError(GL_INVALID_OPERATION, kBaseLevelNonZero);
6159 return false;
6160 }
6161 break;
6162
6163 case GL_TEXTURE_MAX_LEVEL:
6164 if (ConvertToGLint(params[0]) < 0)
6165 {
6166 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
6167 return false;
6168 }
6169 break;
6170
6171 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6172 if (context->getClientVersion() < Version(3, 1))
6173 {
6174 context->validationError(GL_INVALID_ENUM, kEnumRequiresGLES31);
6175 return false;
6176 }
6177 switch (ConvertToGLenum(params[0]))
6178 {
6179 case GL_DEPTH_COMPONENT:
6180 case GL_STENCIL_INDEX:
6181 break;
6182
6183 default:
6184 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6185 return false;
6186 }
6187 break;
6188
6189 case GL_TEXTURE_SRGB_DECODE_EXT:
6190 if (!ValidateTextureSRGBDecodeValue(context, params))
6191 {
6192 return false;
6193 }
6194 break;
6195
6196 case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
6197 if (!ValidateTextureSRGBOverrideValue(context, params))
6198 {
6199 return false;
6200 }
6201 break;
6202
6203 case GL_GENERATE_MIPMAP:
6204 if (context->getClientMajorVersion() > 1)
6205 {
6206 context->validationError(GL_INVALID_ENUM, kGLES1Only);
6207 return false;
6208 }
6209 break;
6210
6211 case GL_TEXTURE_CROP_RECT_OES:
6212 if (context->getClientMajorVersion() > 1)
6213 {
6214 context->validationError(GL_INVALID_ENUM, kGLES1Only);
6215 return false;
6216 }
6217 if (!vectorParams)
6218 {
6219 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
6220 return false;
6221 }
6222 break;
6223
6224 case GL_TEXTURE_BORDER_COLOR:
6225 if (!context->getExtensions().textureBorderClampOES)
6226 {
6227 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6228 return false;
6229 }
6230 if (!vectorParams)
6231 {
6232 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
6233 return false;
6234 }
6235 break;
6236
6237 default:
6238 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6239 return false;
6240 }
6241
6242 return true;
6243 }
6244
6245 template bool ValidateTexParameterBase(const Context *,
6246 TextureType,
6247 GLenum,
6248 GLsizei,
6249 bool,
6250 const GLfloat *);
6251 template bool ValidateTexParameterBase(const Context *,
6252 TextureType,
6253 GLenum,
6254 GLsizei,
6255 bool,
6256 const GLint *);
6257 template bool ValidateTexParameterBase(const Context *,
6258 TextureType,
6259 GLenum,
6260 GLsizei,
6261 bool,
6262 const GLuint *);
6263
ValidateVertexAttribIndex(const Context * context,GLuint index)6264 bool ValidateVertexAttribIndex(const Context *context, GLuint index)
6265 {
6266 if (index >= MAX_VERTEX_ATTRIBS)
6267 {
6268 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
6269 return false;
6270 }
6271
6272 return true;
6273 }
6274
ValidateGetActiveUniformBlockivBase(const Context * context,ShaderProgramID program,GLuint uniformBlockIndex,GLenum pname,GLsizei * length)6275 bool ValidateGetActiveUniformBlockivBase(const Context *context,
6276 ShaderProgramID program,
6277 GLuint uniformBlockIndex,
6278 GLenum pname,
6279 GLsizei *length)
6280 {
6281 if (length)
6282 {
6283 *length = 0;
6284 }
6285
6286 if (context->getClientMajorVersion() < 3)
6287 {
6288 context->validationError(GL_INVALID_OPERATION, kES3Required);
6289 return false;
6290 }
6291
6292 Program *programObject = GetValidProgram(context, program);
6293 if (!programObject)
6294 {
6295 return false;
6296 }
6297
6298 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6299 {
6300 context->validationError(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
6301 return false;
6302 }
6303
6304 switch (pname)
6305 {
6306 case GL_UNIFORM_BLOCK_BINDING:
6307 case GL_UNIFORM_BLOCK_DATA_SIZE:
6308 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6309 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6310 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6311 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6312 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6313 break;
6314
6315 default:
6316 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6317 return false;
6318 }
6319
6320 if (length)
6321 {
6322 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6323 {
6324 const InterfaceBlock &uniformBlock =
6325 programObject->getUniformBlockByIndex(uniformBlockIndex);
6326 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6327 }
6328 else
6329 {
6330 *length = 1;
6331 }
6332 }
6333
6334 return true;
6335 }
6336
6337 template <typename ParamType>
ValidateSamplerParameterBase(const Context * context,SamplerID sampler,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)6338 bool ValidateSamplerParameterBase(const Context *context,
6339 SamplerID sampler,
6340 GLenum pname,
6341 GLsizei bufSize,
6342 bool vectorParams,
6343 const ParamType *params)
6344 {
6345 if (context->getClientMajorVersion() < 3)
6346 {
6347 context->validationError(GL_INVALID_OPERATION, kES3Required);
6348 return false;
6349 }
6350
6351 if (!context->isSampler(sampler))
6352 {
6353 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
6354 return false;
6355 }
6356
6357 const GLsizei minBufSize = GetSamplerParameterCount(pname);
6358 if (bufSize >= 0 && bufSize < minBufSize)
6359 {
6360 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
6361 return false;
6362 }
6363
6364 switch (pname)
6365 {
6366 case GL_TEXTURE_WRAP_S:
6367 case GL_TEXTURE_WRAP_T:
6368 case GL_TEXTURE_WRAP_R:
6369 if (!ValidateTextureWrapModeValue(context, params, false))
6370 {
6371 return false;
6372 }
6373 break;
6374
6375 case GL_TEXTURE_MIN_FILTER:
6376 if (!ValidateTextureMinFilterValue(context, params, false))
6377 {
6378 return false;
6379 }
6380 break;
6381
6382 case GL_TEXTURE_MAG_FILTER:
6383 if (!ValidateTextureMagFilterValue(context, params))
6384 {
6385 return false;
6386 }
6387 break;
6388
6389 case GL_TEXTURE_MIN_LOD:
6390 case GL_TEXTURE_MAX_LOD:
6391 // any value is permissible
6392 break;
6393
6394 case GL_TEXTURE_COMPARE_MODE:
6395 if (!ValidateTextureCompareModeValue(context, params))
6396 {
6397 return false;
6398 }
6399 break;
6400
6401 case GL_TEXTURE_COMPARE_FUNC:
6402 if (!ValidateTextureCompareFuncValue(context, params))
6403 {
6404 return false;
6405 }
6406 break;
6407
6408 case GL_TEXTURE_SRGB_DECODE_EXT:
6409 if (!ValidateTextureSRGBDecodeValue(context, params))
6410 {
6411 return false;
6412 }
6413 break;
6414
6415 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6416 {
6417 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6418 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6419 {
6420 return false;
6421 }
6422 }
6423 break;
6424
6425 case GL_TEXTURE_BORDER_COLOR:
6426 if (!context->getExtensions().textureBorderClampOES)
6427 {
6428 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6429 return false;
6430 }
6431 if (!vectorParams)
6432 {
6433 context->validationError(GL_INVALID_ENUM, kInsufficientBufferSize);
6434 return false;
6435 }
6436 break;
6437
6438 default:
6439 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6440 return false;
6441 }
6442
6443 return true;
6444 }
6445
6446 template bool ValidateSamplerParameterBase(const Context *,
6447 SamplerID,
6448 GLenum,
6449 GLsizei,
6450 bool,
6451 const GLfloat *);
6452 template bool ValidateSamplerParameterBase(const Context *,
6453 SamplerID,
6454 GLenum,
6455 GLsizei,
6456 bool,
6457 const GLint *);
6458 template bool ValidateSamplerParameterBase(const Context *,
6459 SamplerID,
6460 GLenum,
6461 GLsizei,
6462 bool,
6463 const GLuint *);
6464
ValidateGetSamplerParameterBase(const Context * context,SamplerID sampler,GLenum pname,GLsizei * length)6465 bool ValidateGetSamplerParameterBase(const Context *context,
6466 SamplerID sampler,
6467 GLenum pname,
6468 GLsizei *length)
6469 {
6470 if (length)
6471 {
6472 *length = 0;
6473 }
6474
6475 if (context->getClientMajorVersion() < 3)
6476 {
6477 context->validationError(GL_INVALID_OPERATION, kES3Required);
6478 return false;
6479 }
6480
6481 if (!context->isSampler(sampler))
6482 {
6483 context->validationError(GL_INVALID_OPERATION, kInvalidSampler);
6484 return false;
6485 }
6486
6487 switch (pname)
6488 {
6489 case GL_TEXTURE_WRAP_S:
6490 case GL_TEXTURE_WRAP_T:
6491 case GL_TEXTURE_WRAP_R:
6492 case GL_TEXTURE_MIN_FILTER:
6493 case GL_TEXTURE_MAG_FILTER:
6494 case GL_TEXTURE_MIN_LOD:
6495 case GL_TEXTURE_MAX_LOD:
6496 case GL_TEXTURE_COMPARE_MODE:
6497 case GL_TEXTURE_COMPARE_FUNC:
6498 break;
6499
6500 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6501 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6502 {
6503 return false;
6504 }
6505 break;
6506
6507 case GL_TEXTURE_SRGB_DECODE_EXT:
6508 if (!context->getExtensions().textureSRGBDecode)
6509 {
6510 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6511 return false;
6512 }
6513 break;
6514
6515 case GL_TEXTURE_BORDER_COLOR:
6516 if (!context->getExtensions().textureBorderClampOES)
6517 {
6518 context->validationError(GL_INVALID_ENUM, kExtensionNotEnabled);
6519 return false;
6520 }
6521 break;
6522
6523 default:
6524 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6525 return false;
6526 }
6527
6528 if (length)
6529 {
6530 *length = GetSamplerParameterCount(pname);
6531 }
6532 return true;
6533 }
6534
ValidateGetInternalFormativBase(const Context * context,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * numParams)6535 bool ValidateGetInternalFormativBase(const Context *context,
6536 GLenum target,
6537 GLenum internalformat,
6538 GLenum pname,
6539 GLsizei bufSize,
6540 GLsizei *numParams)
6541 {
6542 if (numParams)
6543 {
6544 *numParams = 0;
6545 }
6546
6547 if (context->getClientMajorVersion() < 3)
6548 {
6549 context->validationError(GL_INVALID_OPERATION, kES3Required);
6550 return false;
6551 }
6552
6553 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6554 if (!formatCaps.renderbuffer)
6555 {
6556 context->validationError(GL_INVALID_ENUM, kFormatNotRenderable);
6557 return false;
6558 }
6559
6560 switch (target)
6561 {
6562 case GL_RENDERBUFFER:
6563 break;
6564
6565 case GL_TEXTURE_2D_MULTISAMPLE:
6566 if (context->getClientVersion() < ES_3_1 &&
6567 !context->getExtensions().textureMultisample)
6568 {
6569 context->validationError(GL_INVALID_ENUM,
6570 kMultisampleTextureExtensionOrES31Required);
6571 return false;
6572 }
6573 break;
6574 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6575 if (!context->getExtensions().textureStorageMultisample2DArrayOES)
6576 {
6577 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
6578 return false;
6579 }
6580 break;
6581 default:
6582 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
6583 return false;
6584 }
6585
6586 if (bufSize < 0)
6587 {
6588 context->validationError(GL_INVALID_VALUE, kInsufficientBufferSize);
6589 return false;
6590 }
6591
6592 GLsizei maxWriteParams = 0;
6593 switch (pname)
6594 {
6595 case GL_NUM_SAMPLE_COUNTS:
6596 maxWriteParams = 1;
6597 break;
6598
6599 case GL_SAMPLES:
6600 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6601 break;
6602
6603 default:
6604 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
6605 return false;
6606 }
6607
6608 if (numParams)
6609 {
6610 // glGetInternalFormativ will not overflow bufSize
6611 *numParams = std::min(bufSize, maxWriteParams);
6612 }
6613
6614 return true;
6615 }
6616
ValidateFramebufferNotMultisampled(const Context * context,const Framebuffer * framebuffer,bool needResourceSamples)6617 bool ValidateFramebufferNotMultisampled(const Context *context,
6618 const Framebuffer *framebuffer,
6619 bool needResourceSamples)
6620 {
6621 int samples = needResourceSamples ? framebuffer->getResourceSamples(context)
6622 : framebuffer->getSamples(context);
6623 if (samples != 0)
6624 {
6625 context->validationError(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
6626 return false;
6627 }
6628 return true;
6629 }
6630
ValidateMultitextureUnit(const Context * context,GLenum texture)6631 bool ValidateMultitextureUnit(const Context *context, GLenum texture)
6632 {
6633 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6634 {
6635 context->validationError(GL_INVALID_ENUM, kInvalidMultitextureUnit);
6636 return false;
6637 }
6638 return true;
6639 }
6640
ValidateTexStorageMultisample(const Context * context,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)6641 bool ValidateTexStorageMultisample(const Context *context,
6642 TextureType target,
6643 GLsizei samples,
6644 GLint internalFormat,
6645 GLsizei width,
6646 GLsizei height)
6647 {
6648 const Caps &caps = context->getCaps();
6649 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
6650 {
6651 context->validationError(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
6652 return false;
6653 }
6654
6655 if (samples == 0)
6656 {
6657 context->validationError(GL_INVALID_VALUE, kSamplesZero);
6658 return false;
6659 }
6660
6661 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6662 if (!formatCaps.textureAttachment)
6663 {
6664 context->validationError(GL_INVALID_ENUM, kRenderableInternalFormat);
6665 return false;
6666 }
6667
6668 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6669 // is one of the unsized base internalformats listed in table 8.11.
6670 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6671 if (formatInfo.internalFormat == GL_NONE)
6672 {
6673 context->validationError(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
6674 return false;
6675 }
6676
6677 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6678 {
6679 context->validationError(GL_INVALID_OPERATION, kSamplesOutOfRange);
6680 return false;
6681 }
6682
6683 Texture *texture = context->getTextureByType(target);
6684 if (!texture || texture->id().value == 0)
6685 {
6686 context->validationError(GL_INVALID_OPERATION, kZeroBoundToTarget);
6687 return false;
6688 }
6689
6690 if (texture->getImmutableFormat())
6691 {
6692 context->validationError(GL_INVALID_OPERATION, kImmutableTextureBound);
6693 return false;
6694 }
6695 return true;
6696 }
6697
ValidateTexStorage2DMultisampleBase(const Context * context,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)6698 bool ValidateTexStorage2DMultisampleBase(const Context *context,
6699 TextureType target,
6700 GLsizei samples,
6701 GLint internalFormat,
6702 GLsizei width,
6703 GLsizei height)
6704 {
6705 if (target != TextureType::_2DMultisample)
6706 {
6707 context->validationError(GL_INVALID_ENUM, kInvalidTarget);
6708 return false;
6709 }
6710
6711 if (width < 1 || height < 1)
6712 {
6713 context->validationError(GL_INVALID_VALUE, kTextureSizeTooSmall);
6714 return false;
6715 }
6716
6717 return ValidateTexStorageMultisample(context, target, samples, internalFormat, width, height);
6718 }
6719
ValidateGetTexLevelParameterBase(const Context * context,TextureTarget target,GLint level,GLenum pname,GLsizei * length)6720 bool ValidateGetTexLevelParameterBase(const Context *context,
6721 TextureTarget target,
6722 GLint level,
6723 GLenum pname,
6724 GLsizei *length)
6725 {
6726
6727 if (length)
6728 {
6729 *length = 0;
6730 }
6731
6732 TextureType type = TextureTargetToType(target);
6733
6734 if (!ValidTexLevelDestinationTarget(context, type))
6735 {
6736 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6737 return false;
6738 }
6739
6740 if (context->getTextureByType(type) == nullptr)
6741 {
6742 context->validationError(GL_INVALID_ENUM, kTextureNotBound);
6743 return false;
6744 }
6745
6746 if (!ValidMipLevel(context, type, level))
6747 {
6748 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
6749 return false;
6750 }
6751
6752 switch (pname)
6753 {
6754 case GL_TEXTURE_RED_TYPE:
6755 case GL_TEXTURE_GREEN_TYPE:
6756 case GL_TEXTURE_BLUE_TYPE:
6757 case GL_TEXTURE_ALPHA_TYPE:
6758 case GL_TEXTURE_DEPTH_TYPE:
6759 break;
6760 case GL_TEXTURE_RED_SIZE:
6761 case GL_TEXTURE_GREEN_SIZE:
6762 case GL_TEXTURE_BLUE_SIZE:
6763 case GL_TEXTURE_ALPHA_SIZE:
6764 case GL_TEXTURE_DEPTH_SIZE:
6765 case GL_TEXTURE_STENCIL_SIZE:
6766 case GL_TEXTURE_SHARED_SIZE:
6767 break;
6768 case GL_TEXTURE_INTERNAL_FORMAT:
6769 case GL_TEXTURE_WIDTH:
6770 case GL_TEXTURE_HEIGHT:
6771 case GL_TEXTURE_DEPTH:
6772 break;
6773 case GL_TEXTURE_SAMPLES:
6774 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
6775 break;
6776 case GL_TEXTURE_COMPRESSED:
6777 break;
6778 default:
6779 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6780 return false;
6781 }
6782
6783 if (length)
6784 {
6785 *length = 1;
6786 }
6787 return true;
6788 }
6789
ValidateGetMultisamplefvBase(const Context * context,GLenum pname,GLuint index,const GLfloat * val)6790 bool ValidateGetMultisamplefvBase(const Context *context,
6791 GLenum pname,
6792 GLuint index,
6793 const GLfloat *val)
6794 {
6795 if (pname != GL_SAMPLE_POSITION)
6796 {
6797 context->validationError(GL_INVALID_ENUM, kInvalidPname);
6798 return false;
6799 }
6800
6801 Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
6802 GLint samples = framebuffer->getSamples(context);
6803
6804 if (index >= static_cast<GLuint>(samples))
6805 {
6806 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
6807 return false;
6808 }
6809
6810 return true;
6811 }
6812
ValidateSampleMaskiBase(const Context * context,GLuint maskNumber,GLbitfield mask)6813 bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask)
6814 {
6815 if (maskNumber >= static_cast<GLuint>(context->getCaps().maxSampleMaskWords))
6816 {
6817 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
6818 return false;
6819 }
6820
6821 return true;
6822 }
6823
RecordDrawAttribsError(const Context * context)6824 void RecordDrawAttribsError(const Context *context)
6825 {
6826 // An overflow can happen when adding the offset. Check against a special constant.
6827 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
6828 VertexAttribute::kIntegerOverflow ||
6829 context->getStateCache().getInstancedVertexElementLimit() ==
6830 VertexAttribute::kIntegerOverflow)
6831 {
6832 context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
6833 }
6834 else
6835 {
6836 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
6837 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
6838 context->validationError(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
6839 }
6840 }
6841
ValidateLoseContextCHROMIUM(const Context * context,GraphicsResetStatus current,GraphicsResetStatus other)6842 bool ValidateLoseContextCHROMIUM(const Context *context,
6843 GraphicsResetStatus current,
6844 GraphicsResetStatus other)
6845 {
6846 if (!context->getExtensions().loseContextCHROMIUM)
6847 {
6848 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6849 return false;
6850 }
6851
6852 switch (current)
6853 {
6854 case GraphicsResetStatus::GuiltyContextReset:
6855 case GraphicsResetStatus::InnocentContextReset:
6856 case GraphicsResetStatus::UnknownContextReset:
6857 break;
6858
6859 default:
6860 context->validationError(GL_INVALID_ENUM, kInvalidResetStatus);
6861 }
6862
6863 switch (other)
6864 {
6865 case GraphicsResetStatus::GuiltyContextReset:
6866 case GraphicsResetStatus::InnocentContextReset:
6867 case GraphicsResetStatus::UnknownContextReset:
6868 break;
6869
6870 default:
6871 context->validationError(GL_INVALID_ENUM, kInvalidResetStatus);
6872 }
6873
6874 return true;
6875 }
6876
6877 // GL_ANGLE_texture_storage_external
ValidateTexImage2DExternalANGLE(const Context * context,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type)6878 bool ValidateTexImage2DExternalANGLE(const Context *context,
6879 TextureTarget target,
6880 GLint level,
6881 GLint internalformat,
6882 GLsizei width,
6883 GLsizei height,
6884 GLint border,
6885 GLenum format,
6886 GLenum type)
6887 {
6888 if (!context->getExtensions().textureExternalUpdateANGLE)
6889 {
6890 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6891 return false;
6892 }
6893
6894 if (!ValidTexture2DDestinationTarget(context, target) &&
6895 !ValidTextureExternalTarget(context, target))
6896 {
6897 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6898 return false;
6899 }
6900
6901 if (context->getClientMajorVersion() <= 2)
6902 {
6903 if (!ValidateES2TexImageParametersBase(context, target, level, internalformat, false, false,
6904 0, 0, width, height, border, format, type, -1,
6905 nullptr))
6906 {
6907 return false;
6908 }
6909 }
6910 else
6911 {
6912 if (!ValidateES3TexImageParametersBase(context, target, level, internalformat, false, false,
6913 0, 0, 0, width, height, 1, border, format, type, -1,
6914 nullptr))
6915 {
6916 return false;
6917 }
6918 }
6919
6920 return true;
6921 }
6922
ValidateInvalidateTextureANGLE(const Context * context,TextureType target)6923 bool ValidateInvalidateTextureANGLE(const Context *context, TextureType target)
6924 {
6925 if (!context->getExtensions().textureExternalUpdateANGLE)
6926 {
6927 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
6928 return false;
6929 }
6930
6931 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
6932 {
6933 context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget);
6934 return false;
6935 }
6936
6937 return true;
6938 }
6939
6940 } // namespace gl
6941