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