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/PixelLocalStorage.h"
18 #include "libANGLE/Program.h"
19 #include "libANGLE/Query.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/TransformFeedback.h"
22 #include "libANGLE/angletypes.h"
23 #include "libANGLE/formatutils.h"
24 #include "libANGLE/queryconversions.h"
25 #include "libANGLE/queryutils.h"
26 #include "libANGLE/validationES2.h"
27 #include "libANGLE/validationES3.h"
28
29 #include "common/mathutil.h"
30 #include "common/utilities.h"
31
32 using namespace angle;
33
34 namespace gl
35 {
36 using namespace err;
37
38 namespace
39 {
CompressedTextureFormatRequiresExactSize(GLenum internalFormat)40 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
41 {
42 // List of compressed format that require that the texture size is smaller than or a multiple of
43 // the compressed block size.
44 switch (internalFormat)
45 {
46 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
49 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
50 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
52 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
53 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
54 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
55 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
58 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
59 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
60 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
61 case GL_COMPRESSED_RED_RGTC1_EXT:
62 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
63 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
64 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
65 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
66 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
67 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
68 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
69 return true;
70
71 default:
72 return false;
73 }
74 }
75
DifferenceCanOverflow(GLint a,GLint b)76 bool DifferenceCanOverflow(GLint a, GLint b)
77 {
78 CheckedNumeric<GLint> checkedA(a);
79 checkedA -= b;
80 // Use negation to make sure that the difference can't overflow regardless of the order.
81 checkedA = -checkedA;
82 return !checkedA.IsValid();
83 }
84
ValidReadPixelsTypeEnum(const Context * context,GLenum type)85 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
86 {
87 switch (type)
88 {
89 // Types referenced in Table 3.4 of the ES 2.0.25 spec
90 case GL_UNSIGNED_BYTE:
91 case GL_UNSIGNED_SHORT_4_4_4_4:
92 case GL_UNSIGNED_SHORT_5_5_5_1:
93 case GL_UNSIGNED_SHORT_5_6_5:
94 return context->getClientVersion() >= ES_2_0;
95
96 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
97 case GL_BYTE:
98 case GL_INT:
99 case GL_SHORT:
100 case GL_UNSIGNED_INT:
101 case GL_UNSIGNED_INT_10F_11F_11F_REV:
102 case GL_UNSIGNED_INT_2_10_10_10_REV:
103 case GL_UNSIGNED_INT_5_9_9_9_REV:
104 case GL_UNSIGNED_SHORT:
105 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
106 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
107 return context->getClientVersion() >= ES_3_0;
108
109 case GL_FLOAT:
110 return context->getClientVersion() >= ES_3_0 ||
111 context->getExtensions().textureFloatOES ||
112 context->getExtensions().colorBufferHalfFloatEXT;
113
114 case GL_HALF_FLOAT:
115 return context->getClientVersion() >= ES_3_0 ||
116 context->getExtensions().textureHalfFloatOES;
117
118 case GL_HALF_FLOAT_OES:
119 return context->getExtensions().colorBufferHalfFloatEXT;
120
121 default:
122 return false;
123 }
124 }
125
ValidReadPixelsFormatEnum(const Context * context,GLenum format)126 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
127 {
128 switch (format)
129 {
130 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
131 case GL_RGBA:
132 case GL_RGB:
133 case GL_ALPHA:
134 return context->getClientVersion() >= ES_2_0;
135
136 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
137 case GL_RG:
138 case GL_RED:
139 case GL_RGBA_INTEGER:
140 case GL_RGB_INTEGER:
141 case GL_RG_INTEGER:
142 case GL_RED_INTEGER:
143 return context->getClientVersion() >= ES_3_0;
144
145 case GL_SRGB_ALPHA_EXT:
146 case GL_SRGB_EXT:
147 return context->getExtensions().sRGBEXT;
148
149 case GL_BGRA_EXT:
150 return context->getExtensions().readFormatBgraEXT;
151
152 case GL_RGBX8_ANGLE:
153 return context->getExtensions().rgbxInternalFormatANGLE;
154
155 default:
156 return false;
157 }
158 }
159
ValidReadPixelsUnsignedNormalizedDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)160 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
161 const gl::InternalFormat *info,
162 GLenum type)
163 {
164 bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0);
165 switch (type)
166 {
167 case GL_UNSIGNED_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_24_8:
170 return supportsReadDepthNV;
171 default:
172 return false;
173 }
174 }
175
ValidReadPixelsFloatDepthType(const Context * context,const gl::InternalFormat * info,GLenum type)176 bool ValidReadPixelsFloatDepthType(const Context *context,
177 const gl::InternalFormat *info,
178 GLenum type)
179 {
180 return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
181 context->getExtensions().depthBufferFloat2NV;
182 }
183
ValidReadPixelsFormatType(const Context * context,const gl::InternalFormat * info,GLenum format,GLenum type)184 bool ValidReadPixelsFormatType(const Context *context,
185 const gl::InternalFormat *info,
186 GLenum format,
187 GLenum type)
188 {
189 switch (info->componentType)
190 {
191 case GL_UNSIGNED_NORMALIZED:
192 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
193 // ReadPixels with BGRA even if the extension is not present
194 switch (format)
195 {
196 case GL_RGBA:
197 return type == GL_UNSIGNED_BYTE ||
198 (context->getExtensions().textureNorm16EXT &&
199 type == GL_UNSIGNED_SHORT && info->type == GL_UNSIGNED_SHORT);
200 case GL_BGRA_EXT:
201 return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE);
202 case GL_STENCIL_INDEX_OES:
203 return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
204 case GL_DEPTH_COMPONENT:
205 return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
206 case GL_DEPTH_STENCIL_OES:
207 return context->getExtensions().readDepthStencilNV &&
208 (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0;
209 case GL_RGBX8_ANGLE:
210 return context->getExtensions().rgbxInternalFormatANGLE &&
211 (type == GL_UNSIGNED_BYTE);
212 default:
213 return false;
214 }
215 case GL_SIGNED_NORMALIZED:
216 ASSERT(context->getExtensions().renderSnormEXT);
217 ASSERT(info->type == GL_BYTE ||
218 (context->getExtensions().textureNorm16EXT && info->type == GL_SHORT));
219 // Type conversions are not allowed for signed normalized color buffers
220 return format == GL_RGBA && type == info->type;
221
222 case GL_INT:
223 return (format == GL_RGBA_INTEGER && type == GL_INT);
224
225 case GL_UNSIGNED_INT:
226 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
227
228 case GL_FLOAT:
229 switch (format)
230 {
231 case GL_RGBA:
232 return (type == GL_FLOAT);
233 case GL_DEPTH_COMPONENT:
234 return ValidReadPixelsFloatDepthType(context, info, type);
235 case GL_DEPTH_STENCIL_OES:
236 return context->getExtensions().readDepthStencilNV &&
237 type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0;
238 default:
239 return false;
240 }
241 default:
242 UNREACHABLE();
243 return false;
244 }
245 }
246
247 template <typename ParamType>
ValidateTextureWrapModeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params,bool restrictedWrapModes)248 bool ValidateTextureWrapModeValue(const Context *context,
249 angle::EntryPoint entryPoint,
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().textureBorderClampAny() &&
260 context->getClientVersion() < ES_3_2)
261 {
262 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
263 return false;
264 }
265 if (restrictedWrapModes)
266 {
267 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
268 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
269 return false;
270 }
271 break;
272
273 case GL_REPEAT:
274 case GL_MIRRORED_REPEAT:
275 if (restrictedWrapModes)
276 {
277 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
278 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
279 return false;
280 }
281 break;
282
283 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
284 if (!context->getExtensions().textureMirrorClampToEdgeEXT)
285 {
286 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
287 return false;
288 }
289 if (restrictedWrapModes)
290 {
291 // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
292 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
293 return false;
294 }
295 break;
296
297 default:
298 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureWrap);
299 return false;
300 }
301
302 return true;
303 }
304
305 template <typename ParamType>
ValidateTextureMinFilterValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params,bool restrictedMinFilter)306 bool ValidateTextureMinFilterValue(const Context *context,
307 angle::EntryPoint entryPoint,
308 const ParamType *params,
309 bool restrictedMinFilter)
310 {
311 switch (ConvertToGLenum(params[0]))
312 {
313 case GL_NEAREST:
314 case GL_LINEAR:
315 break;
316
317 case GL_NEAREST_MIPMAP_NEAREST:
318 case GL_LINEAR_MIPMAP_NEAREST:
319 case GL_NEAREST_MIPMAP_LINEAR:
320 case GL_LINEAR_MIPMAP_LINEAR:
321 if (restrictedMinFilter)
322 {
323 // OES_EGL_image_external specifies this error.
324 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFilterTexture);
325 return false;
326 }
327 break;
328
329 default:
330 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureFilterParam);
331 return false;
332 }
333
334 return true;
335 }
336
337 template <typename ParamType>
ValidateTextureMagFilterValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)338 bool ValidateTextureMagFilterValue(const Context *context,
339 angle::EntryPoint entryPoint,
340 const ParamType *params)
341 {
342 switch (ConvertToGLenum(params[0]))
343 {
344 case GL_NEAREST:
345 case GL_LINEAR:
346 break;
347
348 default:
349 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureFilterParam);
350 return false;
351 }
352
353 return true;
354 }
355
356 template <typename ParamType>
ValidateTextureCompareModeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)357 bool ValidateTextureCompareModeValue(const Context *context,
358 angle::EntryPoint entryPoint,
359 const ParamType *params)
360 {
361 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
362 switch (ConvertToGLenum(params[0]))
363 {
364 case GL_NONE:
365 case GL_COMPARE_REF_TO_TEXTURE:
366 break;
367
368 default:
369 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
370 return false;
371 }
372
373 return true;
374 }
375
376 template <typename ParamType>
ValidateTextureCompareFuncValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)377 bool ValidateTextureCompareFuncValue(const Context *context,
378 angle::EntryPoint entryPoint,
379 const ParamType *params)
380 {
381 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
382 switch (ConvertToGLenum(params[0]))
383 {
384 case GL_LEQUAL:
385 case GL_GEQUAL:
386 case GL_LESS:
387 case GL_GREATER:
388 case GL_EQUAL:
389 case GL_NOTEQUAL:
390 case GL_ALWAYS:
391 case GL_NEVER:
392 break;
393
394 default:
395 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
396 return false;
397 }
398
399 return true;
400 }
401
402 template <typename ParamType>
ValidateTextureSRGBDecodeValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)403 bool ValidateTextureSRGBDecodeValue(const Context *context,
404 angle::EntryPoint entryPoint,
405 const ParamType *params)
406 {
407 if (!context->getExtensions().textureSRGBDecodeEXT)
408 {
409 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
410 return false;
411 }
412
413 switch (ConvertToGLenum(params[0]))
414 {
415 case GL_DECODE_EXT:
416 case GL_SKIP_DECODE_EXT:
417 break;
418
419 default:
420 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
421 return false;
422 }
423
424 return true;
425 }
426
427 template <typename ParamType>
ValidateTextureSRGBOverrideValue(const Context * context,angle::EntryPoint entryPoint,const ParamType * params)428 bool ValidateTextureSRGBOverrideValue(const Context *context,
429 angle::EntryPoint entryPoint,
430 const ParamType *params)
431 {
432 if (!context->getExtensions().textureFormatSRGBOverrideEXT)
433 {
434 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
435 return false;
436 }
437
438 switch (ConvertToGLenum(params[0]))
439 {
440 case GL_SRGB:
441 case GL_NONE:
442 break;
443
444 default:
445 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnknownParameter);
446 return false;
447 }
448
449 return true;
450 }
451
ValidateTextureMaxAnisotropyExtensionEnabled(const Context * context,angle::EntryPoint entryPoint)452 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context,
453 angle::EntryPoint entryPoint)
454 {
455 if (!context->getExtensions().textureFilterAnisotropicEXT)
456 {
457 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
458 return false;
459 }
460
461 return true;
462 }
463
ValidateTextureMaxAnisotropyValue(const Context * context,angle::EntryPoint entryPoint,GLfloat paramValue)464 bool ValidateTextureMaxAnisotropyValue(const Context *context,
465 angle::EntryPoint entryPoint,
466 GLfloat paramValue)
467 {
468 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
469 {
470 return false;
471 }
472
473 GLfloat largest = context->getCaps().maxTextureAnisotropy;
474
475 if (paramValue < 1 || paramValue > largest)
476 {
477 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOutsideOfBounds);
478 return false;
479 }
480
481 return true;
482 }
483
ValidateFragmentShaderColorBufferMaskMatch(const Context * context)484 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
485 {
486 const auto &glState = context->getState();
487 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
488 const Framebuffer *framebuffer = glState.getDrawFramebuffer();
489
490 const auto &blendStateExt = glState.getBlendStateExt();
491 auto drawBufferMask = framebuffer->getDrawBufferMask() & blendStateExt.compareColorMask(0);
492 auto dualSourceBlendingMask = drawBufferMask & blendStateExt.getEnabledMask() &
493 blendStateExt.getUsesExtendedBlendFactorMask();
494 auto fragmentOutputMask = executable->getActiveOutputVariablesMask();
495 auto fragmentSecondaryOutputMask = executable->getActiveSecondaryOutputVariablesMask();
496
497 return drawBufferMask == (drawBufferMask & fragmentOutputMask) &&
498 dualSourceBlendingMask == (dualSourceBlendingMask & fragmentSecondaryOutputMask);
499 }
500
ValidateFragmentShaderColorBufferTypeMatch(const Context * context)501 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
502 {
503 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
504 const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
505
506 return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(),
507 framebuffer->getDrawBufferTypeMask().to_ulong(),
508 executable->getActiveOutputVariablesMask().to_ulong(),
509 framebuffer->getDrawBufferMask().to_ulong());
510 }
511
ValidateVertexShaderAttributeTypeMatch(const Context * context)512 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
513 {
514 const auto &glState = context->getState();
515 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
516 const VertexArray *vao = context->getState().getVertexArray();
517
518 if (executable == nullptr)
519 {
520 return false;
521 }
522
523 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
524 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
525 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
526
527 vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
528 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
529 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
530
531 return ValidateComponentTypeMasks(executable->getAttributesTypeMask().to_ulong(),
532 vaoAttribTypeBits, executable->getAttributesMask().to_ulong(),
533 0xFFFF);
534 }
535
IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,PrimitiveMode geometryShaderInputPrimitiveType)536 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
537 PrimitiveMode geometryShaderInputPrimitiveType)
538 {
539 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
540 switch (drawMode)
541 {
542 case PrimitiveMode::Points:
543 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
544 case PrimitiveMode::Lines:
545 case PrimitiveMode::LineStrip:
546 case PrimitiveMode::LineLoop:
547 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
548 case PrimitiveMode::LinesAdjacency:
549 case PrimitiveMode::LineStripAdjacency:
550 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
551 case PrimitiveMode::Triangles:
552 case PrimitiveMode::TriangleFan:
553 case PrimitiveMode::TriangleStrip:
554 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
555 case PrimitiveMode::TrianglesAdjacency:
556 case PrimitiveMode::TriangleStripAdjacency:
557 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
558 default:
559 UNREACHABLE();
560 return false;
561 }
562 }
563
564 // GLES1 texture parameters are a small subset of the others
IsValidGLES1TextureParameter(GLenum pname)565 bool IsValidGLES1TextureParameter(GLenum pname)
566 {
567 switch (pname)
568 {
569 case GL_TEXTURE_MAG_FILTER:
570 case GL_TEXTURE_MIN_FILTER:
571 case GL_TEXTURE_WRAP_S:
572 case GL_TEXTURE_WRAP_T:
573 case GL_TEXTURE_WRAP_R:
574 case GL_GENERATE_MIPMAP:
575 case GL_TEXTURE_CROP_RECT_OES:
576 return true;
577 default:
578 return false;
579 }
580 }
581
GetSamplerParameterCount(GLenum pname)582 unsigned int GetSamplerParameterCount(GLenum pname)
583 {
584 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
585 }
586
ValidateProgramDrawAdvancedBlendState(const Context * context,const ProgramExecutable & executable)587 const char *ValidateProgramDrawAdvancedBlendState(const Context *context,
588 const ProgramExecutable &executable)
589 {
590 const State &state = context->getState();
591 const BlendEquationBitSet &supportedBlendEquations = executable.getAdvancedBlendEquations();
592 const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask();
593
594 // Zero (default) means everything is BlendEquationType::Add, so check can be skipped
595 if (state.getBlendStateExt().getEquationColorBits() != 0)
596 {
597 for (size_t blendEnabledBufferIndex : enabledDrawBufferMask)
598 {
599 const gl::BlendEquationType enabledBlendEquation =
600 state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex);
601
602 if (enabledBlendEquation < gl::BlendEquationType::Multiply ||
603 enabledBlendEquation > gl::BlendEquationType::HslLuminosity)
604 {
605 continue;
606 }
607
608 if (!supportedBlendEquations.test(enabledBlendEquation))
609 {
610 return gl::err::kBlendEquationNotEnabled;
611 }
612 }
613 }
614
615 return nullptr;
616 }
617
ShPixelLocalStorageFormatToGLenum(ShPixelLocalStorageFormat format)618 ANGLE_INLINE GLenum ShPixelLocalStorageFormatToGLenum(ShPixelLocalStorageFormat format)
619 {
620 switch (format)
621 {
622 case ShPixelLocalStorageFormat::NotPLS:
623 return GL_NONE;
624 case ShPixelLocalStorageFormat::RGBA8:
625 return GL_RGBA8;
626 case ShPixelLocalStorageFormat::RGBA8I:
627 return GL_RGBA8I;
628 case ShPixelLocalStorageFormat::RGBA8UI:
629 return GL_RGBA8UI;
630 case ShPixelLocalStorageFormat::R32UI:
631 return GL_R32UI;
632 case ShPixelLocalStorageFormat::R32F:
633 return GL_R32F;
634 }
635 UNREACHABLE();
636 return GL_NONE;
637 }
638
ValidateProgramDrawStates(const Context * context,const Extensions & extensions,const ProgramExecutable & executable)639 ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context,
640 const Extensions &extensions,
641 const ProgramExecutable &executable)
642 {
643 const State &state = context->getState();
644 if (extensions.multiviewOVR || extensions.multiview2OVR)
645 {
646 const int programNumViews = executable.usesMultiview() ? executable.getNumViews() : 1;
647 Framebuffer *framebuffer = state.getDrawFramebuffer();
648 const int framebufferNumViews = framebuffer->getNumViews();
649
650 if (framebufferNumViews != programNumViews)
651 {
652 return gl::err::kMultiviewMismatch;
653 }
654
655 if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
656 {
657 return gl::err::kMultiviewTransformFeedback;
658 }
659
660 if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 &&
661 state.isQueryActive(QueryType::TimeElapsed))
662 {
663 return gl::err::kMultiviewTimerQuery;
664 }
665 }
666
667 // Uniform buffer validation
668 for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable.getUniformBlocks().size();
669 uniformBlockIndex++)
670 {
671 const InterfaceBlock &uniformBlock = executable.getUniformBlockByIndex(uniformBlockIndex);
672 GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex);
673 const OffsetBindingPointer<Buffer> &uniformBuffer =
674 state.getIndexedUniformBuffer(blockBinding);
675
676 if (uniformBuffer.get() == nullptr && context->isWebGL())
677 {
678 // undefined behaviour
679 return gl::err::kUniformBufferUnbound;
680 }
681
682 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
683 if (uniformBufferSize < uniformBlock.pod.dataSize &&
684 (context->isWebGL() || context->isBufferAccessValidationEnabled()))
685 {
686 // undefined behaviour
687 return gl::err::kUniformBufferTooSmall;
688 }
689
690 if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
691 {
692 return gl::err::kUniformBufferBoundForTransformFeedback;
693 }
694 }
695
696 // ANGLE_shader_pixel_local_storage validation.
697 if (extensions.shaderPixelLocalStorageANGLE)
698 {
699 const Framebuffer *framebuffer = state.getDrawFramebuffer();
700 const PixelLocalStorage *pls = framebuffer->peekPixelLocalStorage();
701 const auto &shaderPLSFormats = executable.getPixelLocalStorageFormats();
702 size_t activePLSCount = context->getState().getPixelLocalStorageActivePlanes();
703
704 if (shaderPLSFormats.size() > activePLSCount)
705 {
706 // INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a
707 // pixel local uniform bound to an inactive pixel local storage plane.
708 return gl::err::kPLSDrawProgramPlanesInactive;
709 }
710
711 if (shaderPLSFormats.size() < activePLSCount)
712 {
713 // INVALID_OPERATION is generated if a draw is issued with a fragment shader that does
714 // _not_ have a pixel local uniform bound to an _active_ pixel local storage plane
715 // (i.e., the fragment shader must declare uniforms bound to every single active pixel
716 // local storage plane).
717 return gl::err::kPLSDrawProgramActivePlanesUnused;
718 }
719
720 for (size_t i = 0; i < activePLSCount; ++i)
721 {
722 const auto &plsPlane = pls->getPlane(static_cast<GLint>(i));
723 ASSERT(plsPlane.isActive());
724 if (shaderPLSFormats[i] == ShPixelLocalStorageFormat::NotPLS)
725 {
726 // INVALID_OPERATION is generated if a draw is issued with a fragment shader that
727 // does _not_ have a pixel local uniform bound to an _active_ pixel local storage
728 // plane (i.e., the fragment shader must declare uniforms bound to every single
729 // active pixel local storage plane).
730 return gl::err::kPLSDrawProgramActivePlanesUnused;
731 }
732
733 if (ShPixelLocalStorageFormatToGLenum(shaderPLSFormats[i]) !=
734 plsPlane.getInternalformat())
735 {
736 // INVALID_OPERATION is generated if a draw is issued with a fragment shader that
737 // has a pixel local storage uniform whose format layout qualifier does not
738 // identically match the internalformat of its associated pixel local storage plane
739 // on the current draw framebuffer, as enumerated in Table X.3.
740 return gl::err::kPLSDrawProgramFormatMismatch;
741 }
742 }
743 }
744
745 // Enabled blend equation validation
746 const char *errorString = nullptr;
747
748 if (extensions.blendEquationAdvancedKHR)
749 {
750 errorString = ValidateProgramDrawAdvancedBlendState(context, executable);
751 }
752
753 return errorString;
754 }
755 } // anonymous namespace
756
SetRobustLengthParam(const GLsizei * length,GLsizei value)757 void SetRobustLengthParam(const GLsizei *length, GLsizei value)
758 {
759 if (length)
760 {
761 // Currently we modify robust length parameters in the validation layer. We should be only
762 // doing this in the Context instead.
763 // TODO(http://anglebug.com/42263032): Remove when possible.
764 *const_cast<GLsizei *>(length) = value;
765 }
766 }
767
ValidTextureTarget(const Context * context,TextureType type)768 bool ValidTextureTarget(const Context *context, TextureType type)
769 {
770 switch (type)
771 {
772 case TextureType::_2D:
773 case TextureType::CubeMap:
774 return true;
775
776 case TextureType::Rectangle:
777 return context->getExtensions().textureRectangleANGLE;
778
779 case TextureType::_3D:
780 return context->getClientVersion() >= ES_3_0 || context->getExtensions().texture3DOES;
781
782 case TextureType::_2DArray:
783 return context->getClientVersion() >= ES_3_0;
784
785 case TextureType::_2DMultisample:
786 return context->getClientVersion() >= ES_3_1 ||
787 context->getExtensions().textureMultisampleANGLE;
788
789 case TextureType::_2DMultisampleArray:
790 return context->getClientVersion() >= ES_3_2 ||
791 context->getExtensions().textureStorageMultisample2dArrayOES;
792
793 case TextureType::CubeMapArray:
794 return context->getClientVersion() >= ES_3_2 ||
795 context->getExtensions().textureCubeMapArrayAny();
796
797 case TextureType::VideoImage:
798 return context->getExtensions().videoTextureWEBGL;
799
800 case TextureType::Buffer:
801 return context->getClientVersion() >= ES_3_2 ||
802 context->getExtensions().textureBufferAny();
803
804 default:
805 return false;
806 }
807 }
808
ValidTexture2DTarget(const Context * context,TextureType type)809 bool ValidTexture2DTarget(const Context *context, TextureType type)
810 {
811 switch (type)
812 {
813 case TextureType::_2D:
814 case TextureType::CubeMap:
815 return true;
816
817 case TextureType::Rectangle:
818 return context->getExtensions().textureRectangleANGLE;
819
820 default:
821 return false;
822 }
823 }
824
ValidTexture3DTarget(const Context * context,TextureType target)825 bool ValidTexture3DTarget(const Context *context, TextureType target)
826 {
827 switch (target)
828 {
829 case TextureType::_3D:
830 case TextureType::_2DArray:
831 return (context->getClientMajorVersion() >= 3);
832
833 case TextureType::CubeMapArray:
834 return (context->getClientVersion() >= Version(3, 2) ||
835 context->getExtensions().textureCubeMapArrayAny());
836
837 default:
838 return false;
839 }
840 }
841
842 // Most texture GL calls are not compatible with external textures, so we have a separate validation
843 // function for use in the GL calls that do
ValidTextureExternalTarget(const Context * context,TextureType target)844 bool ValidTextureExternalTarget(const Context *context, TextureType target)
845 {
846 return (target == TextureType::External) &&
847 (context->getExtensions().EGLImageExternalOES ||
848 context->getExtensions().EGLStreamConsumerExternalNV);
849 }
850
ValidTextureExternalTarget(const Context * context,TextureTarget target)851 bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
852 {
853 return (target == TextureTarget::External) &&
854 ValidTextureExternalTarget(context, TextureType::External);
855 }
856
857 // This function differs from ValidTextureTarget in that the target must be
858 // usable as the destination of a 2D operation-- so a cube face is valid, but
859 // GL_TEXTURE_CUBE_MAP is not.
860 // Note: duplicate of IsInternalTextureTarget
ValidTexture2DDestinationTarget(const Context * context,TextureTarget target)861 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
862 {
863 switch (target)
864 {
865 case TextureTarget::_2D:
866 case TextureTarget::CubeMapNegativeX:
867 case TextureTarget::CubeMapNegativeY:
868 case TextureTarget::CubeMapNegativeZ:
869 case TextureTarget::CubeMapPositiveX:
870 case TextureTarget::CubeMapPositiveY:
871 case TextureTarget::CubeMapPositiveZ:
872 return true;
873 case TextureTarget::Rectangle:
874 return context->getExtensions().textureRectangleANGLE;
875 case TextureTarget::VideoImage:
876 return context->getExtensions().videoTextureWEBGL;
877 default:
878 return false;
879 }
880 }
881
ValidateTransformFeedbackPrimitiveMode(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode transformFeedbackPrimitiveMode,PrimitiveMode renderPrimitiveMode)882 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
883 angle::EntryPoint entryPoint,
884 PrimitiveMode transformFeedbackPrimitiveMode,
885 PrimitiveMode renderPrimitiveMode)
886 {
887 ASSERT(context);
888
889 if ((!context->getExtensions().geometryShaderAny() ||
890 !context->getExtensions().tessellationShaderAny()) &&
891 context->getClientVersion() < ES_3_2)
892 {
893 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
894 // that does not match the current transform feedback object's draw mode (if transform
895 // feedback is active), (3.0.2, section 2.14, pg 86)
896 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
897 }
898
899 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
900 ASSERT(executable);
901 if (executable->hasLinkedShaderStage(ShaderType::Geometry))
902 {
903 // If geometry shader is active, transform feedback mode must match what is output from this
904 // stage.
905 renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType();
906 }
907 else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
908 {
909 // Similarly with tessellation shaders, but only if no geometry shader is present. With
910 // tessellation shaders, only triangles are possibly output.
911 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles &&
912 executable->getTessGenMode() == GL_TRIANGLES;
913 }
914
915 // [GL_EXT_geometry_shader] Table 12.1gs
916 switch (renderPrimitiveMode)
917 {
918 case PrimitiveMode::Points:
919 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
920 case PrimitiveMode::Lines:
921 case PrimitiveMode::LineStrip:
922 case PrimitiveMode::LineLoop:
923 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
924 case PrimitiveMode::Triangles:
925 case PrimitiveMode::TriangleFan:
926 case PrimitiveMode::TriangleStrip:
927 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
928 case PrimitiveMode::Patches:
929 return transformFeedbackPrimitiveMode == PrimitiveMode::Patches;
930 default:
931 UNREACHABLE();
932 return false;
933 }
934 }
935
ValidateDrawElementsInstancedBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount,GLuint baseinstance)936 bool ValidateDrawElementsInstancedBase(const Context *context,
937 angle::EntryPoint entryPoint,
938 PrimitiveMode mode,
939 GLsizei count,
940 DrawElementsType type,
941 const void *indices,
942 GLsizei primcount,
943 GLuint baseinstance)
944 {
945 if (primcount <= 0)
946 {
947 if (primcount < 0)
948 {
949 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
950 return false;
951 }
952
953 // Early exit.
954 return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices,
955 primcount);
956 }
957
958 if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount))
959 {
960 return false;
961 }
962
963 if (count == 0)
964 {
965 // Early exit.
966 return true;
967 }
968
969 return ValidateDrawInstancedAttribs(context, entryPoint, primcount, baseinstance);
970 }
971
ValidateDrawArraysInstancedBase(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount,GLuint baseinstance)972 bool ValidateDrawArraysInstancedBase(const Context *context,
973 angle::EntryPoint entryPoint,
974 PrimitiveMode mode,
975 GLint first,
976 GLsizei count,
977 GLsizei primcount,
978 GLuint baseinstance)
979 {
980 if (primcount <= 0)
981 {
982 if (primcount < 0)
983 {
984 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
985 return false;
986 }
987
988 // Early exit.
989 return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount);
990 }
991
992 if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount))
993 {
994 return false;
995 }
996
997 if (count == 0)
998 {
999 // Early exit.
1000 return true;
1001 }
1002
1003 return ValidateDrawInstancedAttribs(context, entryPoint, primcount, baseinstance);
1004 }
1005
ValidateDrawInstancedANGLE(const Context * context,angle::EntryPoint entryPoint)1006 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint)
1007 {
1008 // Verify there is at least one active attribute with a divisor of zero
1009 const State &state = context->getState();
1010 const ProgramExecutable *executable = state.getLinkedProgramExecutable(context);
1011
1012 if (!executable)
1013 {
1014 // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
1015 // an error.
1016 context->getState().getDebug().insertMessage(
1017 GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
1018 std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint);
1019 return true;
1020 }
1021
1022 const auto &attribs = state.getVertexArray()->getVertexAttributes();
1023 const auto &bindings = state.getVertexArray()->getVertexBindings();
1024 for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++)
1025 {
1026 const VertexAttribute &attrib = attribs[attributeIndex];
1027 const VertexBinding &binding = bindings[attrib.bindingIndex];
1028 if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
1029 {
1030 return true;
1031 }
1032 }
1033
1034 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoZeroDivisor);
1035 return false;
1036 }
1037
ValidTexture3DDestinationTarget(const Context * context,TextureTarget target)1038 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
1039 {
1040 switch (target)
1041 {
1042 case TextureTarget::_3D:
1043 return true;
1044 case TextureTarget::_2DArray:
1045 return context->getClientVersion() >= Version(3, 0);
1046 case TextureTarget::CubeMapArray:
1047 return (context->getClientVersion() >= Version(3, 2) ||
1048 context->getExtensions().textureCubeMapArrayAny());
1049 default:
1050 return false;
1051 }
1052 }
1053
ValidTexLevelDestinationTarget(const Context * context,TextureType type)1054 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
1055 {
1056 switch (type)
1057 {
1058 case TextureType::_2D:
1059 case TextureType::CubeMap:
1060 return true;
1061 case TextureType::_2DArray:
1062 return context->getClientVersion() >= ES_3_0;
1063 case TextureType::_2DMultisample:
1064 return context->getClientVersion() >= ES_3_1 ||
1065 context->getExtensions().textureMultisampleANGLE;
1066 case TextureType::_2DMultisampleArray:
1067 return context->getClientVersion() >= ES_3_2 ||
1068 context->getExtensions().textureStorageMultisample2dArrayOES;
1069 case TextureType::_3D:
1070 return context->getClientVersion() >= ES_3_0 || context->getExtensions().texture3DOES;
1071 case TextureType::CubeMapArray:
1072 return context->getClientVersion() >= ES_3_2 ||
1073 context->getExtensions().textureCubeMapArrayAny();
1074 case TextureType::Rectangle:
1075 return context->getExtensions().textureRectangleANGLE;
1076 case TextureType::Buffer:
1077 return context->getClientVersion() >= ES_3_2 ||
1078 context->getExtensions().textureBufferAny();
1079 default:
1080 return false;
1081 }
1082 }
1083
ValidFramebufferTarget(const Context * context,GLenum target)1084 bool ValidFramebufferTarget(const Context *context, GLenum target)
1085 {
1086 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1087 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1088 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
1089
1090 switch (target)
1091 {
1092 case GL_FRAMEBUFFER:
1093 return true;
1094
1095 case GL_READ_FRAMEBUFFER:
1096 case GL_DRAW_FRAMEBUFFER:
1097 return (context->getExtensions().framebufferBlitAny() ||
1098 context->getClientMajorVersion() >= 3);
1099
1100 default:
1101 return false;
1102 }
1103 }
1104
ValidMipLevel(const Context * context,TextureType type,GLint level)1105 bool ValidMipLevel(const Context *context, TextureType type, GLint level)
1106 {
1107 const auto &caps = context->getCaps();
1108 int maxDimension = 0;
1109 switch (type)
1110 {
1111 case TextureType::_2D:
1112 case TextureType::_2DArray:
1113 maxDimension = caps.max2DTextureSize;
1114 break;
1115
1116 case TextureType::CubeMap:
1117 case TextureType::CubeMapArray:
1118 maxDimension = caps.maxCubeMapTextureSize;
1119 break;
1120
1121 case TextureType::External:
1122 case TextureType::Rectangle:
1123 case TextureType::VideoImage:
1124 case TextureType::Buffer:
1125 case TextureType::_2DMultisample:
1126 case TextureType::_2DMultisampleArray:
1127 return level == 0;
1128
1129 case TextureType::_3D:
1130 maxDimension = caps.max3DTextureSize;
1131 break;
1132
1133 default:
1134 UNREACHABLE();
1135 }
1136
1137 return level <= log2(maxDimension) && level >= 0;
1138 }
1139
ValidImageSizeParameters(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLint level,GLsizei width,GLsizei height,GLsizei depth,bool isSubImage)1140 bool ValidImageSizeParameters(const Context *context,
1141 angle::EntryPoint entryPoint,
1142 TextureType target,
1143 GLint level,
1144 GLsizei width,
1145 GLsizei height,
1146 GLsizei depth,
1147 bool isSubImage)
1148 {
1149 if (width < 0 || height < 0 || depth < 0)
1150 {
1151 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
1152 return false;
1153 }
1154 // TexSubImage parameters can be NPOT without textureNPOT extension,
1155 // as long as the destination texture is POT.
1156 bool hasNPOTSupport =
1157 context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0);
1158 if (!isSubImage && !hasNPOTSupport &&
1159 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
1160 {
1161 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureNotPow2);
1162 return false;
1163 }
1164
1165 if (!ValidMipLevel(context, target, level))
1166 {
1167 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
1168 return false;
1169 }
1170
1171 return true;
1172 }
1173
ValidCompressedBaseLevel(GLsizei size,GLuint blockSize,GLint level)1174 bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level)
1175 {
1176 // Already checked in ValidMipLevel.
1177 ASSERT(level < 32);
1178 // This function is used only for 4x4 BC formats.
1179 ASSERT(blockSize == 4);
1180 // Use the constant value to avoid division.
1181 return ((size << level) % 4) == 0;
1182 }
1183
ValidCompressedImageSize(const Context * context,GLenum internalFormat,GLint level,GLsizei width,GLsizei height,GLsizei depth)1184 bool ValidCompressedImageSize(const Context *context,
1185 GLenum internalFormat,
1186 GLint level,
1187 GLsizei width,
1188 GLsizei height,
1189 GLsizei depth)
1190 {
1191 if (width < 0 || height < 0)
1192 {
1193 return false;
1194 }
1195
1196 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1197
1198 if (!formatInfo.compressed && !formatInfo.paletted)
1199 {
1200 return false;
1201 }
1202
1203 // A texture format can not be both block-compressed and paletted
1204 ASSERT(!(formatInfo.compressed && formatInfo.paletted));
1205
1206 if (formatInfo.compressed)
1207 {
1208 // Only PVRTC1 requires dimensions to be powers of two
1209 if (IsPVRTC1Format(internalFormat))
1210 {
1211 if (!isPow2(width) || !isPow2(height))
1212 {
1213 return false;
1214 }
1215
1216 if (context->getLimitations().squarePvrtc1)
1217 {
1218 if (width != height)
1219 {
1220 return false;
1221 }
1222 }
1223 }
1224
1225 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1226 {
1227 // In WebGL compatibility mode and D3D, enforce that the base level implied
1228 // by the compressed texture's mip level would conform to the block
1229 // size.
1230 if (context->isWebGL() ||
1231 context->getLimitations().compressedBaseMipLevelMultipleOfFour)
1232 {
1233 // This check is performed only for BC formats.
1234 ASSERT(formatInfo.compressedBlockDepth == 1);
1235 if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) ||
1236 !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level))
1237 {
1238 return false;
1239 }
1240 }
1241 // non-WebGL and non-D3D check is not necessary for the following formats
1242 // From EXT_texture_compression_s3tc specification:
1243 // If the width or height is not a multiple of four, there will be 4x4 blocks at the
1244 // edge of the image that contain "extra" texels that are not part of the image. From
1245 // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an
1246 // RGTC/BPTC image has a width or height that is not a multiple of four, the data
1247 // corresponding to texels outside the image are irrelevant and undefined.
1248 }
1249 }
1250
1251 if (formatInfo.paletted)
1252 {
1253 // TODO(http://anglebug.com/42266155): multi-level paletted images
1254 if (level != 0)
1255 {
1256 return false;
1257 }
1258
1259 if (!isPow2(width) || !isPow2(height))
1260 {
1261 return false;
1262 }
1263 }
1264
1265 return true;
1266 }
1267
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)1268 bool ValidCompressedSubImageSize(const Context *context,
1269 GLenum internalFormat,
1270 GLint xoffset,
1271 GLint yoffset,
1272 GLint zoffset,
1273 GLsizei width,
1274 GLsizei height,
1275 GLsizei depth,
1276 size_t textureWidth,
1277 size_t textureHeight,
1278 size_t textureDepth)
1279 {
1280 // Passing non-compressed internal format to sub-image compressed entry points generates
1281 // INVALID_OPERATION, so check it here.
1282 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1283 if (!formatInfo.compressed)
1284 {
1285 return false;
1286 }
1287
1288 // Negative dimensions already checked in ValidImageSizeParameters called by
1289 // ValidateES2TexImageParametersBase or ValidateES3TexImageParametersBase.
1290 ASSERT(width >= 0 && height >= 0 && depth >= 0);
1291
1292 // Negative and overflowed offsets already checked in ValidateES2TexImageParametersBase or
1293 // ValidateES3TexImageParametersBase.
1294 ASSERT(xoffset >= 0 && yoffset >= 0 && zoffset >= 0);
1295 ASSERT(std::numeric_limits<GLsizei>::max() - xoffset >= width &&
1296 std::numeric_limits<GLsizei>::max() - yoffset >= height &&
1297 std::numeric_limits<GLsizei>::max() - zoffset >= depth);
1298
1299 // Ensure that format's block dimensions are set.
1300 ASSERT(formatInfo.compressedBlockWidth > 0 && formatInfo.compressedBlockHeight > 0 &&
1301 formatInfo.compressedBlockDepth > 0);
1302
1303 // Check if the whole image is being replaced. For 2D texture blocks, zoffset and depth do not
1304 // affect whether the replaced region fills the entire image.
1305 if ((xoffset == 0 && static_cast<size_t>(width) == textureWidth) &&
1306 (yoffset == 0 && static_cast<size_t>(height) == textureHeight) &&
1307 ((zoffset == 0 && static_cast<size_t>(depth) == textureDepth) ||
1308 formatInfo.compressedBlockDepth == 1))
1309 {
1310 // All compressed formats support whole image replacement, early pass.
1311 return true;
1312 }
1313
1314 // The replaced region does not match the image size. Fail if the format does not support
1315 // partial updates.
1316 if (CompressedFormatRequiresWholeImage(internalFormat))
1317 {
1318 return false;
1319 }
1320
1321 // The format supports partial updates. Check that the origin of the replaced region is aligned
1322 // to block boundaries.
1323 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1324 yoffset % formatInfo.compressedBlockHeight != 0 ||
1325 zoffset % formatInfo.compressedBlockDepth != 0)
1326 {
1327 return false;
1328 }
1329
1330 // The replaced region dimensions must either be multiples of the block dimensions or exactly
1331 // reach the image boundaries.
1332 return (static_cast<size_t>(xoffset + width) == textureWidth ||
1333 width % formatInfo.compressedBlockWidth == 0) &&
1334 (static_cast<size_t>(yoffset + height) == textureHeight ||
1335 height % formatInfo.compressedBlockHeight == 0) &&
1336 (static_cast<size_t>(zoffset + depth) == textureDepth ||
1337 depth % formatInfo.compressedBlockDepth == 0);
1338 }
1339
ValidImageDataSize(const Context * context,angle::EntryPoint entryPoint,TextureType texType,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * pixels,GLsizei imageSize)1340 bool ValidImageDataSize(const Context *context,
1341 angle::EntryPoint entryPoint,
1342 TextureType texType,
1343 GLsizei width,
1344 GLsizei height,
1345 GLsizei depth,
1346 GLenum format,
1347 GLenum type,
1348 const void *pixels,
1349 GLsizei imageSize)
1350 {
1351 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
1352 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1353 {
1354 // Checks are not required
1355 return true;
1356 }
1357
1358 // ...the data would be unpacked from the buffer object such that the memory reads required
1359 // would exceed the data store size.
1360 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
1361 if (formatInfo.internalFormat == GL_NONE)
1362 {
1363 UNREACHABLE();
1364 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalErrorFormatNotFound);
1365 return false;
1366 }
1367 const Extents size(width, height, depth);
1368 const auto &unpack = context->getState().getUnpackState();
1369
1370 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
1371 GLuint endByte = 0;
1372 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
1373 {
1374 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
1375 return false;
1376 }
1377
1378 if (pixelUnpackBuffer)
1379 {
1380 CheckedNumeric<size_t> checkedEndByte(endByte);
1381 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1382 checkedEndByte += checkedOffset;
1383
1384 if (!checkedEndByte.IsValid() ||
1385 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1386 {
1387 // Overflow past the end of the buffer
1388 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
1389 return false;
1390 }
1391 if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
1392 {
1393 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1394 kPixelUnpackBufferBoundForTransformFeedback);
1395 return false;
1396 }
1397 }
1398 else
1399 {
1400 ASSERT(imageSize >= 0);
1401 if (pixels == nullptr && imageSize != 0)
1402 {
1403 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeMustBeZero);
1404 return false;
1405 }
1406
1407 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
1408 {
1409 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeTooSmall);
1410 return false;
1411 }
1412 }
1413
1414 return true;
1415 }
1416
ValidQueryType(const Context * context,QueryType queryType)1417 bool ValidQueryType(const Context *context, QueryType queryType)
1418 {
1419 switch (queryType)
1420 {
1421 case QueryType::AnySamples:
1422 case QueryType::AnySamplesConservative:
1423 return context->getClientMajorVersion() >= 3 ||
1424 context->getExtensions().occlusionQueryBooleanEXT;
1425 case QueryType::TransformFeedbackPrimitivesWritten:
1426 return (context->getClientMajorVersion() >= 3);
1427 case QueryType::TimeElapsed:
1428 return context->getExtensions().disjointTimerQueryEXT;
1429 case QueryType::CommandsCompleted:
1430 return context->getExtensions().syncQueryCHROMIUM;
1431 case QueryType::PrimitivesGenerated:
1432 return context->getClientVersion() >= ES_3_2 ||
1433 context->getExtensions().geometryShaderAny();
1434 default:
1435 return false;
1436 }
1437 }
1438
ValidateWebGLVertexAttribPointer(const Context * context,angle::EntryPoint entryPoint,VertexAttribType type,GLboolean normalized,GLsizei stride,const void * ptr,bool pureInteger)1439 bool ValidateWebGLVertexAttribPointer(const Context *context,
1440 angle::EntryPoint entryPoint,
1441 VertexAttribType type,
1442 GLboolean normalized,
1443 GLsizei stride,
1444 const void *ptr,
1445 bool pureInteger)
1446 {
1447 ASSERT(context->isWebGL());
1448 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1449 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1450 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1451 // parameter exceeds 255.
1452 constexpr GLsizei kMaxWebGLStride = 255;
1453 if (stride > kMaxWebGLStride)
1454 {
1455 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
1456 return false;
1457 }
1458
1459 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1460 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1461 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1462 // or an INVALID_OPERATION error is generated.
1463 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
1464 size_t typeSize = GetVertexFormatSize(internalType);
1465
1466 ASSERT(isPow2(typeSize) && typeSize > 0);
1467 size_t sizeMask = (typeSize - 1);
1468 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1469 {
1470 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
1471 return false;
1472 }
1473
1474 if ((stride & sizeMask) != 0)
1475 {
1476 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
1477 return false;
1478 }
1479
1480 return true;
1481 }
1482
GetValidProgramNoResolve(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1483 Program *GetValidProgramNoResolve(const Context *context,
1484 angle::EntryPoint entryPoint,
1485 ShaderProgramID id)
1486 {
1487 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1488 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1489 // or program object and INVALID_OPERATION if the provided name identifies an object
1490 // that is not the expected type."
1491
1492 Program *validProgram = context->getProgramNoResolveLink(id);
1493
1494 if (!validProgram)
1495 {
1496 if (context->getShaderNoResolveCompile(id))
1497 {
1498 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedProgramName);
1499 }
1500 else
1501 {
1502 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
1503 }
1504 }
1505
1506 return validProgram;
1507 }
1508
GetValidProgram(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1509 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
1510 {
1511 Program *program = GetValidProgramNoResolve(context, entryPoint, id);
1512 if (program)
1513 {
1514 program->resolveLink(context);
1515 }
1516 return program;
1517 }
1518
GetValidShader(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID id)1519 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
1520 {
1521 // See ValidProgram for spec details.
1522
1523 Shader *validShader = context->getShaderNoResolveCompile(id);
1524
1525 if (!validShader)
1526 {
1527 if (context->getProgramNoResolveLink(id))
1528 {
1529 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedShaderName);
1530 }
1531 else
1532 {
1533 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderName);
1534 }
1535 }
1536
1537 return validShader;
1538 }
1539
ValidateAttachmentTarget(const Context * context,angle::EntryPoint entryPoint,GLenum attachment)1540 bool ValidateAttachmentTarget(const Context *context,
1541 angle::EntryPoint entryPoint,
1542 GLenum attachment)
1543 {
1544 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1545 {
1546 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT)
1547 {
1548 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1549 return false;
1550 }
1551
1552 // Color attachment 0 is validated below because it is always valid
1553 const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1554 if (colorAttachment >= context->getCaps().maxColorAttachments)
1555 {
1556 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
1557 return false;
1558 }
1559 }
1560 else
1561 {
1562 switch (attachment)
1563 {
1564 case GL_COLOR_ATTACHMENT0:
1565 case GL_DEPTH_ATTACHMENT:
1566 case GL_STENCIL_ATTACHMENT:
1567 break;
1568
1569 case GL_DEPTH_STENCIL_ATTACHMENT:
1570 if (!context->isWebGL() && context->getClientMajorVersion() < 3)
1571 {
1572 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1573 return false;
1574 }
1575 break;
1576
1577 default:
1578 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
1579 return false;
1580 }
1581 }
1582
1583 return true;
1584 }
1585
ValidateRenderbufferStorageParametersBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)1586 bool ValidateRenderbufferStorageParametersBase(const Context *context,
1587 angle::EntryPoint entryPoint,
1588 GLenum target,
1589 GLsizei samples,
1590 GLenum internalformat,
1591 GLsizei width,
1592 GLsizei height)
1593 {
1594 switch (target)
1595 {
1596 case GL_RENDERBUFFER:
1597 break;
1598 default:
1599 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1600 return false;
1601 }
1602
1603 if (width < 0 || height < 0 || samples < 0)
1604 {
1605 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
1606 return false;
1607 }
1608
1609 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1610 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1611
1612 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
1613 if (!formatCaps.renderbuffer)
1614 {
1615 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1616 return false;
1617 }
1618
1619 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1620 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
1621 // only sized internal formats.
1622 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
1623 if (formatInfo.internalFormat == GL_NONE)
1624 {
1625 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
1626 return false;
1627 }
1628
1629 if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
1630 {
1631 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
1632 return false;
1633 }
1634
1635 RenderbufferID id = context->getState().getRenderbufferId();
1636 if (id.value == 0)
1637 {
1638 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
1639 return false;
1640 }
1641
1642 return true;
1643 }
1644
ValidateBlitFramebufferParameters(const Context * context,angle::EntryPoint entryPoint,GLint srcX0,GLint srcY0,GLint srcX1,GLint srcY1,GLint dstX0,GLint dstY0,GLint dstX1,GLint dstY1,GLbitfield mask,GLenum filter)1645 bool ValidateBlitFramebufferParameters(const Context *context,
1646 angle::EntryPoint entryPoint,
1647 GLint srcX0,
1648 GLint srcY0,
1649 GLint srcX1,
1650 GLint srcY1,
1651 GLint dstX0,
1652 GLint dstY0,
1653 GLint dstX1,
1654 GLint dstY1,
1655 GLbitfield mask,
1656 GLenum filter)
1657 {
1658 switch (filter)
1659 {
1660 case GL_NEAREST:
1661 break;
1662 case GL_LINEAR:
1663 break;
1664 default:
1665 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kBlitInvalidFilter);
1666 return false;
1667 }
1668
1669 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1670 {
1671 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBlitInvalidMask);
1672 return false;
1673 }
1674
1675 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1676 // color buffer, leaving only nearest being unfiltered from above
1677 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1678 {
1679 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
1680 return false;
1681 }
1682
1683 const auto &glState = context->getState();
1684 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1685 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
1686
1687 if (!readFramebuffer || !drawFramebuffer)
1688 {
1689 ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
1690 return false;
1691 }
1692
1693 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
1694 {
1695 return false;
1696 }
1697
1698 if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer))
1699 {
1700 return false;
1701 }
1702
1703 // The QCOM_framebuffer_foveated spec:
1704 if (drawFramebuffer->isFoveationEnabled())
1705 {
1706 // INVALID_OPERATION is generated by any API call which causes a framebuffer
1707 // attachment to be written to if the framebuffer attachments have changed for
1708 // a foveated fbo.
1709 if (drawFramebuffer->hasAnyAttachmentChanged())
1710 {
1711 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFramebufferFoveationAttachmentChanged);
1712 return false;
1713 }
1714 }
1715
1716 // EXT_YUV_target disallows blitting to or from a YUV framebuffer
1717 if ((mask & GL_COLOR_BUFFER_BIT) != 0 &&
1718 (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment()))
1719 {
1720 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitYUVFramebuffer);
1721 return false;
1722 }
1723
1724 // The draw and read framebuffers can only match if:
1725 // - They are the default framebuffer AND
1726 // - The read/draw surfaces are different
1727 if ((readFramebuffer->id() == drawFramebuffer->id()) &&
1728 ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
1729 (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
1730 {
1731 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitFeedbackLoop);
1732 return false;
1733 }
1734
1735 // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
1736 // consider it MS. checkReadBufferResourceSamples = false
1737 if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false))
1738 {
1739 return false;
1740 }
1741
1742 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1743 // always run it in order to avoid triggering driver bugs.
1744 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1745 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1746 {
1747 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
1748 return false;
1749 }
1750
1751 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1752
1753 if (mask & GL_COLOR_BUFFER_BIT)
1754 {
1755 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
1756 const Extensions &extensions = context->getExtensions();
1757
1758 if (readColorBuffer)
1759 {
1760 const Format &readFormat = readColorBuffer->getFormat();
1761
1762 for (size_t drawbufferIdx = 0;
1763 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
1764 {
1765 const FramebufferAttachment *attachment =
1766 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1767 if (attachment)
1768 {
1769 const Format &drawFormat = attachment->getFormat();
1770
1771 // The GL ES 3.0.2 spec (pg 193) states that:
1772 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1773 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1774 // as well
1775 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1776 // well
1777 // Changes with EXT_color_buffer_float:
1778 // Case 1) is changed to fixed point OR floating point
1779 GLenum readComponentType = readFormat.info->componentType;
1780 GLenum drawComponentType = drawFormat.info->componentType;
1781 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1782 readComponentType == GL_SIGNED_NORMALIZED);
1783 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1784 drawComponentType == GL_SIGNED_NORMALIZED);
1785
1786 if (extensions.colorBufferFloatEXT)
1787 {
1788 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1789 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1790
1791 if (readFixedOrFloat != drawFixedOrFloat)
1792 {
1793 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1794 kBlitTypeMismatchFixedOrFloat);
1795 return false;
1796 }
1797 }
1798 else if (readFixedPoint != drawFixedPoint)
1799 {
1800 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
1801 return false;
1802 }
1803
1804 if (readComponentType == GL_UNSIGNED_INT &&
1805 drawComponentType != GL_UNSIGNED_INT)
1806 {
1807 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1808 kBlitTypeMismatchUnsignedInteger);
1809 return false;
1810 }
1811
1812 if (readComponentType == GL_INT && drawComponentType != GL_INT)
1813 {
1814 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1815 kBlitTypeMismatchSignedInteger);
1816 return false;
1817 }
1818
1819 if (readColorBuffer->getResourceSamples() > 0 &&
1820 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
1821 {
1822 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
1823 kBlitMultisampledFormatOrBoundsMismatch);
1824 return false;
1825 }
1826
1827 if (context->isWebGL() && *readColorBuffer == *attachment)
1828 {
1829 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageColor);
1830 return false;
1831 }
1832 }
1833 }
1834
1835 if (readFormat.info->isInt() && filter == GL_LINEAR)
1836 {
1837 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
1838 return false;
1839 }
1840 }
1841 // In OpenGL ES, blits to/from missing attachments are silently ignored. In WebGL 2.0, this
1842 // is defined to be an error.
1843 else if (context->isWebGL() && drawFramebuffer->hasEnabledDrawBuffer())
1844 {
1845 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingColor);
1846 return false;
1847 }
1848 }
1849
1850 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1851 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1852 for (size_t i = 0; i < 2; i++)
1853 {
1854 if (mask & masks[i])
1855 {
1856 const FramebufferAttachment *readBuffer =
1857 readFramebuffer->getAttachment(context, attachments[i]);
1858 const FramebufferAttachment *drawBuffer =
1859 drawFramebuffer->getAttachment(context, attachments[i]);
1860
1861 if (readBuffer && drawBuffer)
1862 {
1863 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
1864 {
1865 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitDepthOrStencilFormatMismatch);
1866 return false;
1867 }
1868
1869 if (readBuffer->getResourceSamples() > 0 && !sameBounds)
1870 {
1871 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
1872 return false;
1873 }
1874
1875 if (context->isWebGL() && *readBuffer == *drawBuffer)
1876 {
1877 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
1878 return false;
1879 }
1880 }
1881 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1882 else if (context->isWebGL() && drawBuffer)
1883 {
1884 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
1885 return false;
1886 }
1887 }
1888 }
1889
1890 // OVR_multiview2:
1891 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1892 // current draw framebuffer isMultiview() or the number of
1893 // views in the current read framebuffer is more than one.
1894 if (readFramebuffer->readDisallowedByMultiview())
1895 {
1896 ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
1897 return false;
1898 }
1899 if (drawFramebuffer->isMultiview())
1900 {
1901 ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
1902 return false;
1903 }
1904
1905 return true;
1906 }
1907
ValidateBindFramebufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,FramebufferID framebuffer)1908 bool ValidateBindFramebufferBase(const Context *context,
1909 angle::EntryPoint entryPoint,
1910 GLenum target,
1911 FramebufferID framebuffer)
1912 {
1913 if (!ValidFramebufferTarget(context, target))
1914 {
1915 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1916 return false;
1917 }
1918
1919 if (!context->getState().isBindGeneratesResourceEnabled() &&
1920 !context->isFramebufferGenerated(framebuffer))
1921 {
1922 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
1923 return false;
1924 }
1925
1926 return true;
1927 }
1928
ValidateBindRenderbufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,RenderbufferID renderbuffer)1929 bool ValidateBindRenderbufferBase(const Context *context,
1930 angle::EntryPoint entryPoint,
1931 GLenum target,
1932 RenderbufferID renderbuffer)
1933 {
1934 if (target != GL_RENDERBUFFER)
1935 {
1936 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
1937 return false;
1938 }
1939
1940 if (!context->getState().isBindGeneratesResourceEnabled() &&
1941 !context->isRenderbufferGenerated(renderbuffer))
1942 {
1943 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
1944 return false;
1945 }
1946
1947 return true;
1948 }
1949
ValidateFramebufferParameteriBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLint param)1950 bool ValidateFramebufferParameteriBase(const Context *context,
1951 angle::EntryPoint entryPoint,
1952 GLenum target,
1953 GLenum pname,
1954 GLint param)
1955 {
1956 if (!ValidFramebufferTarget(context, target))
1957 {
1958 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
1959 return false;
1960 }
1961
1962 switch (pname)
1963 {
1964 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1965 {
1966 GLint maxWidth = context->getCaps().maxFramebufferWidth;
1967 if (param < 0 || param > maxWidth)
1968 {
1969 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferWidth);
1970 return false;
1971 }
1972 break;
1973 }
1974 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1975 {
1976 GLint maxHeight = context->getCaps().maxFramebufferHeight;
1977 if (param < 0 || param > maxHeight)
1978 {
1979 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferHeight);
1980 return false;
1981 }
1982 break;
1983 }
1984 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1985 {
1986 GLint maxSamples = context->getCaps().maxFramebufferSamples;
1987 if (param < 0 || param > maxSamples)
1988 {
1989 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferSamples);
1990 return false;
1991 }
1992 break;
1993 }
1994 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1995 {
1996 break;
1997 }
1998 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1999 {
2000 if (!context->getExtensions().geometryShaderAny() &&
2001 context->getClientVersion() < ES_3_2)
2002 {
2003 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
2004 return false;
2005 }
2006 GLint maxLayers = context->getCaps().maxFramebufferLayers;
2007 if (param < 0 || param > maxLayers)
2008 {
2009 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferLayer);
2010 return false;
2011 }
2012 break;
2013 }
2014 case GL_FRAMEBUFFER_FLIP_Y_MESA:
2015 {
2016 if (!context->getExtensions().framebufferFlipYMESA)
2017 {
2018 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2019 return false;
2020 }
2021 break;
2022 }
2023 default:
2024 {
2025 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2026 return false;
2027 }
2028 }
2029
2030 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
2031 ASSERT(framebuffer);
2032 if (framebuffer->isDefault())
2033 {
2034 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
2035 return false;
2036 }
2037 return true;
2038 }
2039
ValidateFramebufferRenderbufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum renderbuffertarget,RenderbufferID renderbuffer)2040 bool ValidateFramebufferRenderbufferBase(const Context *context,
2041 angle::EntryPoint entryPoint,
2042 GLenum target,
2043 GLenum attachment,
2044 GLenum renderbuffertarget,
2045 RenderbufferID renderbuffer)
2046 {
2047 if (!ValidFramebufferTarget(context, target))
2048 {
2049 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
2050 return false;
2051 }
2052
2053 if (renderbuffertarget != GL_RENDERBUFFER)
2054 {
2055 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
2056 return false;
2057 }
2058
2059 Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
2060
2061 ASSERT(framebuffer);
2062 if (framebuffer->isDefault())
2063 {
2064 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
2065 return false;
2066 }
2067
2068 if (!ValidateAttachmentTarget(context, entryPoint, attachment))
2069 {
2070 return false;
2071 }
2072
2073 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2074 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2075 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2076 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2077 if (renderbuffer.value != 0)
2078 {
2079 if (!context->getRenderbuffer(renderbuffer))
2080 {
2081 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
2082 return false;
2083 }
2084 }
2085
2086 return true;
2087 }
2088
ValidateFramebufferTextureBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,TextureID texture,GLint level)2089 bool ValidateFramebufferTextureBase(const Context *context,
2090 angle::EntryPoint entryPoint,
2091 GLenum target,
2092 GLenum attachment,
2093 TextureID texture,
2094 GLint level)
2095 {
2096 if (!ValidFramebufferTarget(context, target))
2097 {
2098 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
2099 return false;
2100 }
2101
2102 if (!ValidateAttachmentTarget(context, entryPoint, attachment))
2103 {
2104 return false;
2105 }
2106
2107 if (texture.value != 0)
2108 {
2109 Texture *tex = context->getTexture(texture);
2110
2111 if (tex == nullptr)
2112 {
2113 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
2114 return false;
2115 }
2116
2117 if (level < 0)
2118 {
2119 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
2120 return false;
2121 }
2122
2123 // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
2124 // An INVALID_VALUE error is generated if texture is not zero and level is
2125 // not a supported texture level for textarget
2126
2127 // Common criteria for not supported texture levels(other criteria are handled case by case
2128 // in non base functions): If texture refers to an immutable-format texture, level must be
2129 // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for
2130 // texture.
2131 if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1)
2132 {
2133 if (level >= static_cast<GLint>(tex->getImmutableLevels()))
2134 {
2135 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
2136 return false;
2137 }
2138 }
2139
2140 // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
2141 // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture.
2142 if ((context->getClientVersion() >= ES_3_2 ||
2143 context->getExtensions().textureBufferAny()) &&
2144 tex->getType() == TextureType::Buffer)
2145 {
2146 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
2147 return false;
2148 }
2149
2150 if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent())
2151 {
2152 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
2153 "Mismatch between Texture and Context Protected Content state");
2154 return false;
2155 }
2156 }
2157
2158 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
2159 ASSERT(framebuffer);
2160
2161 if (framebuffer->isDefault())
2162 {
2163 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
2164 return false;
2165 }
2166
2167 return true;
2168 }
2169
ValidateGenerateMipmapBase(const Context * context,angle::EntryPoint entryPoint,TextureType target)2170 bool ValidateGenerateMipmapBase(const Context *context,
2171 angle::EntryPoint entryPoint,
2172 TextureType target)
2173 {
2174 if (!ValidTextureTarget(context, target))
2175 {
2176 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
2177 return false;
2178 }
2179
2180 Texture *texture = context->getTextureByType(target);
2181
2182 if (texture == nullptr)
2183 {
2184 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
2185 return false;
2186 }
2187
2188 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
2189
2190 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
2191 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
2192 if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
2193 {
2194 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelOutOfRange);
2195 return false;
2196 }
2197
2198 TextureTarget baseTarget = (target == TextureType::CubeMap)
2199 ? TextureTarget::CubeMapPositiveX
2200 : NonCubeTextureTypeToTarget(target);
2201 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
2202 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
2203 format.stencilBits > 0)
2204 {
2205 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2206 return false;
2207 }
2208
2209 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
2210 bool formatUnsized = !format.sized;
2211 bool formatColorRenderableAndFilterable =
2212 format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
2213 format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
2214 if (!formatUnsized && !formatColorRenderableAndFilterable)
2215 {
2216 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2217 return false;
2218 }
2219
2220 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
2221 // generation
2222 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
2223 {
2224 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2225 return false;
2226 }
2227
2228 // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
2229 // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
2230 if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
2231 {
2232 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
2233 return false;
2234 }
2235
2236 // Non-power of 2 ES2 check
2237 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES &&
2238 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
2239 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
2240 {
2241 ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
2242 target == TextureType::CubeMap);
2243 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotPow2);
2244 return false;
2245 }
2246
2247 // Cube completeness check
2248 if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
2249 {
2250 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCubemapIncomplete);
2251 return false;
2252 }
2253
2254 if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
2255 texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
2256 {
2257 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
2258 return false;
2259 }
2260
2261 return true;
2262 }
2263
ValidateReadPixelsRobustANGLE(const Context * context,angle::EntryPoint entryPoint,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)2264 bool ValidateReadPixelsRobustANGLE(const Context *context,
2265 angle::EntryPoint entryPoint,
2266 GLint x,
2267 GLint y,
2268 GLsizei width,
2269 GLsizei height,
2270 GLenum format,
2271 GLenum type,
2272 GLsizei bufSize,
2273 const GLsizei *length,
2274 const GLsizei *columns,
2275 const GLsizei *rows,
2276 const void *pixels)
2277 {
2278 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2279 {
2280 return false;
2281 }
2282
2283 GLsizei writeLength = 0;
2284 GLsizei writeColumns = 0;
2285 GLsizei writeRows = 0;
2286
2287 if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2288 &writeLength, &writeColumns, &writeRows, pixels))
2289 {
2290 return false;
2291 }
2292
2293 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
2294 {
2295 return false;
2296 }
2297
2298 SetRobustLengthParam(length, writeLength);
2299 SetRobustLengthParam(columns, writeColumns);
2300 SetRobustLengthParam(rows, writeRows);
2301
2302 return true;
2303 }
2304
ValidateReadnPixelsEXT(const Context * context,angle::EntryPoint entryPoint,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,const void * pixels)2305 bool ValidateReadnPixelsEXT(const Context *context,
2306 angle::EntryPoint entryPoint,
2307 GLint x,
2308 GLint y,
2309 GLsizei width,
2310 GLsizei height,
2311 GLenum format,
2312 GLenum type,
2313 GLsizei bufSize,
2314 const void *pixels)
2315 {
2316 if (bufSize < 0)
2317 {
2318 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
2319 return false;
2320 }
2321
2322 return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2323 nullptr, nullptr, nullptr, pixels);
2324 }
2325
ValidateReadnPixelsRobustANGLE(const Context * context,angle::EntryPoint entryPoint,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)2326 bool ValidateReadnPixelsRobustANGLE(const Context *context,
2327 angle::EntryPoint entryPoint,
2328 GLint x,
2329 GLint y,
2330 GLsizei width,
2331 GLsizei height,
2332 GLenum format,
2333 GLenum type,
2334 GLsizei bufSize,
2335 const GLsizei *length,
2336 const GLsizei *columns,
2337 const GLsizei *rows,
2338 const void *data)
2339 {
2340 GLsizei writeLength = 0;
2341 GLsizei writeColumns = 0;
2342 GLsizei writeRows = 0;
2343
2344 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2345 {
2346 return false;
2347 }
2348
2349 if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
2350 &writeLength, &writeColumns, &writeRows, data))
2351 {
2352 return false;
2353 }
2354
2355 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
2356 {
2357 return false;
2358 }
2359
2360 SetRobustLengthParam(length, writeLength);
2361 SetRobustLengthParam(columns, writeColumns);
2362 SetRobustLengthParam(rows, writeRows);
2363
2364 return true;
2365 }
2366
ValidateGenQueriesEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * ids)2367 bool ValidateGenQueriesEXT(const Context *context,
2368 angle::EntryPoint entryPoint,
2369 GLsizei n,
2370 const QueryID *ids)
2371 {
2372 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2373 !context->getExtensions().disjointTimerQueryEXT)
2374 {
2375 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2376 return false;
2377 }
2378
2379 return ValidateGenOrDelete(context, entryPoint, n);
2380 }
2381
ValidateDeleteQueriesEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const QueryID * ids)2382 bool ValidateDeleteQueriesEXT(const Context *context,
2383 angle::EntryPoint entryPoint,
2384 GLsizei n,
2385 const QueryID *ids)
2386 {
2387 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2388 !context->getExtensions().disjointTimerQueryEXT)
2389 {
2390 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2391 return false;
2392 }
2393
2394 return ValidateGenOrDelete(context, entryPoint, n);
2395 }
2396
ValidateIsQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id)2397 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id)
2398 {
2399 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2400 !context->getExtensions().disjointTimerQueryEXT)
2401 {
2402 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2403 return false;
2404 }
2405
2406 return true;
2407 }
2408
ValidateBeginQueryBase(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)2409 bool ValidateBeginQueryBase(const Context *context,
2410 angle::EntryPoint entryPoint,
2411 QueryType target,
2412 QueryID id)
2413 {
2414 if (!ValidQueryType(context, target))
2415 {
2416 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2417 return false;
2418 }
2419
2420 if (id.value == 0)
2421 {
2422 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2423 return false;
2424 }
2425
2426 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2427 // of zero, if the active query object name for <target> is non-zero (for the
2428 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2429 // the active query for either target is non-zero), if <id> is the name of an
2430 // existing query object whose type does not match <target>, or if <id> is the
2431 // active query object name for any query type, the error INVALID_OPERATION is
2432 // generated.
2433
2434 // Ensure no other queries are active
2435 // NOTE: If other queries than occlusion are supported, we will need to check
2436 // separately that:
2437 // a) The query ID passed is not the current active query for any target/type
2438 // b) There are no active queries for the requested target (and in the case
2439 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2440 // no query may be active for either if glBeginQuery targets either.
2441
2442 if (context->getState().isQueryActive(target))
2443 {
2444 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOtherQueryActive);
2445 return false;
2446 }
2447
2448 // check that name was obtained with glGenQueries
2449 if (!context->isQueryGenerated(id))
2450 {
2451 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2452 return false;
2453 }
2454
2455 // Check for type mismatch. If query is not yet started we're good to go.
2456 Query *queryObject = context->getQuery(id);
2457 if (queryObject && queryObject->getType() != target)
2458 {
2459 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryTargetMismatch);
2460 return false;
2461 }
2462
2463 return true;
2464 }
2465
ValidateBeginQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target,QueryID id)2466 bool ValidateBeginQueryEXT(const Context *context,
2467 angle::EntryPoint entryPoint,
2468 QueryType target,
2469 QueryID id)
2470 {
2471 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2472 !context->getExtensions().disjointTimerQueryEXT &&
2473 !context->getExtensions().syncQueryCHROMIUM)
2474 {
2475 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2476 return false;
2477 }
2478
2479 return ValidateBeginQueryBase(context, entryPoint, target, id);
2480 }
2481
ValidateEndQueryBase(const Context * context,angle::EntryPoint entryPoint,QueryType target)2482 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target)
2483 {
2484 if (!ValidQueryType(context, target))
2485 {
2486 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2487 return false;
2488 }
2489
2490 const Query *queryObject = context->getState().getActiveQuery(target);
2491
2492 if (queryObject == nullptr)
2493 {
2494 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryInactive);
2495 return false;
2496 }
2497
2498 return true;
2499 }
2500
ValidateEndQueryEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target)2501 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target)
2502 {
2503 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2504 !context->getExtensions().disjointTimerQueryEXT &&
2505 !context->getExtensions().syncQueryCHROMIUM)
2506 {
2507 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
2508 return false;
2509 }
2510
2511 return ValidateEndQueryBase(context, entryPoint, target);
2512 }
2513
ValidateQueryCounterEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,QueryType target)2514 bool ValidateQueryCounterEXT(const Context *context,
2515 angle::EntryPoint entryPoint,
2516 QueryID id,
2517 QueryType target)
2518 {
2519 if (!context->getExtensions().disjointTimerQueryEXT)
2520 {
2521 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2522 return false;
2523 }
2524
2525 if (target != QueryType::Timestamp)
2526 {
2527 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
2528 return false;
2529 }
2530
2531 if (!context->isQueryGenerated(id))
2532 {
2533 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2534 return false;
2535 }
2536
2537 // If query object is not started, that's fine.
2538 Query *queryObject = context->getQuery(id);
2539 if (queryObject && context->getState().isQueryActive(queryObject))
2540 {
2541 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
2542 return false;
2543 }
2544
2545 return true;
2546 }
2547
ValidateGetQueryivBase(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,GLsizei * numParams)2548 bool ValidateGetQueryivBase(const Context *context,
2549 angle::EntryPoint entryPoint,
2550 QueryType target,
2551 GLenum pname,
2552 GLsizei *numParams)
2553 {
2554 if (numParams)
2555 {
2556 *numParams = 0;
2557 }
2558
2559 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
2560 {
2561 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
2562 return false;
2563 }
2564
2565 switch (pname)
2566 {
2567 case GL_CURRENT_QUERY_EXT:
2568 if (target == QueryType::Timestamp)
2569 {
2570 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
2571 return false;
2572 }
2573 break;
2574 case GL_QUERY_COUNTER_BITS_EXT:
2575 if (!context->getExtensions().disjointTimerQueryEXT ||
2576 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
2577 {
2578 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2579 return false;
2580 }
2581 break;
2582 default:
2583 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
2584 return false;
2585 }
2586
2587 if (numParams)
2588 {
2589 // All queries return only one value
2590 *numParams = 1;
2591 }
2592
2593 return true;
2594 }
2595
ValidateGetQueryivEXT(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,const GLint * params)2596 bool ValidateGetQueryivEXT(const Context *context,
2597 angle::EntryPoint entryPoint,
2598 QueryType target,
2599 GLenum pname,
2600 const GLint *params)
2601 {
2602 if (!context->getExtensions().occlusionQueryBooleanEXT &&
2603 !context->getExtensions().disjointTimerQueryEXT &&
2604 !context->getExtensions().syncQueryCHROMIUM)
2605 {
2606 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2607 return false;
2608 }
2609
2610 return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
2611 }
2612
ValidateGetQueryivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)2613 bool ValidateGetQueryivRobustANGLE(const Context *context,
2614 angle::EntryPoint entryPoint,
2615 QueryType target,
2616 GLenum pname,
2617 GLsizei bufSize,
2618 const GLsizei *length,
2619 const GLint *params)
2620 {
2621 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2622 {
2623 return false;
2624 }
2625
2626 GLsizei numParams = 0;
2627
2628 if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams))
2629 {
2630 return false;
2631 }
2632
2633 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2634 {
2635 return false;
2636 }
2637
2638 SetRobustLengthParam(length, numParams);
2639
2640 return true;
2641 }
2642
ValidateGetQueryObjectValueBase(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei * numParams)2643 bool ValidateGetQueryObjectValueBase(const Context *context,
2644 angle::EntryPoint entryPoint,
2645 QueryID id,
2646 GLenum pname,
2647 GLsizei *numParams)
2648 {
2649 if (numParams)
2650 {
2651 *numParams = 1;
2652 }
2653
2654 if (context->isContextLost())
2655 {
2656 ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
2657
2658 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
2659 {
2660 // Generate an error but still return true, the context still needs to return a
2661 // value in this case.
2662 return true;
2663 }
2664 else
2665 {
2666 return false;
2667 }
2668 }
2669
2670 Query *queryObject = context->getQuery(id);
2671
2672 if (!queryObject)
2673 {
2674 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
2675 return false;
2676 }
2677
2678 if (context->getState().isQueryActive(queryObject))
2679 {
2680 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
2681 return false;
2682 }
2683
2684 switch (pname)
2685 {
2686 case GL_QUERY_RESULT_EXT:
2687 case GL_QUERY_RESULT_AVAILABLE_EXT:
2688 break;
2689
2690 default:
2691 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
2692 return false;
2693 }
2694
2695 return true;
2696 }
2697
ValidateGetQueryObjectivEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLint * params)2698 bool ValidateGetQueryObjectivEXT(const Context *context,
2699 angle::EntryPoint entryPoint,
2700 QueryID id,
2701 GLenum pname,
2702 const GLint *params)
2703 {
2704 if (!context->getExtensions().disjointTimerQueryEXT)
2705 {
2706 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2707 return false;
2708 }
2709 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2710 }
2711
ValidateGetQueryObjectivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)2712 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
2713 angle::EntryPoint entryPoint,
2714 QueryID id,
2715 GLenum pname,
2716 GLsizei bufSize,
2717 const GLsizei *length,
2718 const GLint *params)
2719 {
2720 if (!context->getExtensions().disjointTimerQueryEXT)
2721 {
2722 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2723 return false;
2724 }
2725
2726 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2727 {
2728 return false;
2729 }
2730
2731 GLsizei numParams = 0;
2732
2733 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2734 {
2735 return false;
2736 }
2737
2738 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2739 {
2740 return false;
2741 }
2742
2743 SetRobustLengthParam(length, numParams);
2744
2745 return true;
2746 }
2747
ValidateGetQueryObjectuivEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,const GLuint * params)2748 bool ValidateGetQueryObjectuivEXT(const Context *context,
2749 angle::EntryPoint entryPoint,
2750 QueryID id,
2751 GLenum pname,
2752 const GLuint *params)
2753 {
2754 if (!context->getExtensions().disjointTimerQueryEXT &&
2755 !context->getExtensions().occlusionQueryBooleanEXT &&
2756 !context->getExtensions().syncQueryCHROMIUM)
2757 {
2758 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2759 return false;
2760 }
2761 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2762 }
2763
ValidateGetQueryObjectuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)2764 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
2765 angle::EntryPoint entryPoint,
2766 QueryID id,
2767 GLenum pname,
2768 GLsizei bufSize,
2769 const GLsizei *length,
2770 const GLuint *params)
2771 {
2772 if (!context->getExtensions().disjointTimerQueryEXT &&
2773 !context->getExtensions().occlusionQueryBooleanEXT &&
2774 !context->getExtensions().syncQueryCHROMIUM)
2775 {
2776 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2777 return false;
2778 }
2779
2780 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2781 {
2782 return false;
2783 }
2784
2785 GLsizei numParams = 0;
2786
2787 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2788 {
2789 return false;
2790 }
2791
2792 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2793 {
2794 return false;
2795 }
2796
2797 SetRobustLengthParam(length, numParams);
2798
2799 return true;
2800 }
2801
ValidateGetQueryObjecti64vEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLint64 * params)2802 bool ValidateGetQueryObjecti64vEXT(const Context *context,
2803 angle::EntryPoint entryPoint,
2804 QueryID id,
2805 GLenum pname,
2806 GLint64 *params)
2807 {
2808 if (!context->getExtensions().disjointTimerQueryEXT)
2809 {
2810 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2811 return false;
2812 }
2813 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2814 }
2815
ValidateGetQueryObjecti64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * params)2816 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
2817 angle::EntryPoint entryPoint,
2818 QueryID id,
2819 GLenum pname,
2820 GLsizei bufSize,
2821 const GLsizei *length,
2822 GLint64 *params)
2823 {
2824 if (!context->getExtensions().disjointTimerQueryEXT)
2825 {
2826 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2827 return false;
2828 }
2829
2830 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2831 {
2832 return false;
2833 }
2834
2835 GLsizei numParams = 0;
2836
2837 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2838 {
2839 return false;
2840 }
2841
2842 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2843 {
2844 return false;
2845 }
2846
2847 SetRobustLengthParam(length, numParams);
2848
2849 return true;
2850 }
2851
ValidateGetQueryObjectui64vEXT(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLuint64 * params)2852 bool ValidateGetQueryObjectui64vEXT(const Context *context,
2853 angle::EntryPoint entryPoint,
2854 QueryID id,
2855 GLenum pname,
2856 GLuint64 *params)
2857 {
2858 if (!context->getExtensions().disjointTimerQueryEXT)
2859 {
2860 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2861 return false;
2862 }
2863 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
2864 }
2865
ValidateGetQueryObjectui64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,QueryID id,GLenum pname,GLsizei bufSize,const GLsizei * length,GLuint64 * params)2866 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
2867 angle::EntryPoint entryPoint,
2868 QueryID id,
2869 GLenum pname,
2870 GLsizei bufSize,
2871 const GLsizei *length,
2872 GLuint64 *params)
2873 {
2874 if (!context->getExtensions().disjointTimerQueryEXT)
2875 {
2876 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
2877 return false;
2878 }
2879
2880 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
2881 {
2882 return false;
2883 }
2884
2885 GLsizei numParams = 0;
2886
2887 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
2888 {
2889 return false;
2890 }
2891
2892 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
2893 {
2894 return false;
2895 }
2896
2897 SetRobustLengthParam(length, numParams);
2898
2899 return true;
2900 }
2901
ValidateUniformCommonBase(const Context * context,angle::EntryPoint entryPoint,const Program * program,UniformLocation location,GLsizei count,const LinkedUniform ** uniformOut)2902 bool ValidateUniformCommonBase(const Context *context,
2903 angle::EntryPoint entryPoint,
2904 const Program *program,
2905 UniformLocation location,
2906 GLsizei count,
2907 const LinkedUniform **uniformOut)
2908 {
2909 // TODO(Jiajia): Add image uniform check in future.
2910 if (count < 0)
2911 {
2912 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
2913 return false;
2914 }
2915
2916 if (!program)
2917 {
2918 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidProgramName);
2919 return false;
2920 }
2921
2922 if (!program->isLinked())
2923 {
2924 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
2925 return false;
2926 }
2927
2928 if (location.value == -1)
2929 {
2930 // Silently ignore the uniform command
2931 return false;
2932 }
2933
2934 const ProgramExecutable &executable = program->getExecutable();
2935 const auto &uniformLocations = executable.getUniformLocations();
2936 size_t castedLocation = static_cast<size_t>(location.value);
2937 if (castedLocation >= uniformLocations.size())
2938 {
2939 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
2940 return false;
2941 }
2942
2943 const auto &uniformLocation = uniformLocations[castedLocation];
2944 if (uniformLocation.ignored)
2945 {
2946 // Silently ignore the uniform command
2947 return false;
2948 }
2949
2950 if (!uniformLocation.used())
2951 {
2952 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
2953 return false;
2954 }
2955
2956 const LinkedUniform &uniform = executable.getUniformByIndex(uniformLocation.index);
2957
2958 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2959 if (count > 1 && !uniform.isArray())
2960 {
2961 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformCount);
2962 return false;
2963 }
2964
2965 *uniformOut = &uniform;
2966 return true;
2967 }
2968
ValidateUniform1ivValue(const Context * context,angle::EntryPoint entryPoint,GLenum uniformType,GLsizei count,const GLint * value)2969 bool ValidateUniform1ivValue(const Context *context,
2970 angle::EntryPoint entryPoint,
2971 GLenum uniformType,
2972 GLsizei count,
2973 const GLint *value)
2974 {
2975 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2976 // It is compatible with INT or BOOL.
2977 // Do these cheap tests first, for a little extra speed.
2978 if (GL_INT == uniformType || GL_BOOL == uniformType)
2979 {
2980 return true;
2981 }
2982
2983 if (IsSamplerType(uniformType))
2984 {
2985 // Check that the values are in range.
2986 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2987 for (GLsizei i = 0; i < count; ++i)
2988 {
2989 if (value[i] < 0 || value[i] >= max)
2990 {
2991 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
2992 return false;
2993 }
2994 }
2995 return true;
2996 }
2997
2998 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
2999 return false;
3000 }
3001
ValidateUniformMatrixValue(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,GLenum uniformType)3002 bool ValidateUniformMatrixValue(const Context *context,
3003 angle::EntryPoint entryPoint,
3004 GLenum valueType,
3005 GLenum uniformType)
3006 {
3007 // Check that the value type is compatible with uniform type.
3008 if (valueType == uniformType)
3009 {
3010 return true;
3011 }
3012
3013 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
3014 return false;
3015 }
3016
ValidateUniform(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count)3017 bool ValidateUniform(const Context *context,
3018 angle::EntryPoint entryPoint,
3019 GLenum valueType,
3020 UniformLocation location,
3021 GLsizei count)
3022 {
3023 const LinkedUniform *uniform = nullptr;
3024 Program *programObject = context->getActiveLinkedProgram();
3025 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
3026 &uniform) &&
3027 ValidateUniformValue(context, entryPoint, valueType, uniform->getType());
3028 }
3029
ValidateUniform1iv(const Context * context,angle::EntryPoint entryPoint,UniformLocation location,GLsizei count,const GLint * value)3030 bool ValidateUniform1iv(const Context *context,
3031 angle::EntryPoint entryPoint,
3032 UniformLocation location,
3033 GLsizei count,
3034 const GLint *value)
3035 {
3036 const LinkedUniform *uniform = nullptr;
3037 Program *programObject = context->getActiveLinkedProgram();
3038 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
3039 &uniform) &&
3040 ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value);
3041 }
3042
ValidateUniformMatrix(const Context * context,angle::EntryPoint entryPoint,GLenum valueType,UniformLocation location,GLsizei count,GLboolean transpose)3043 bool ValidateUniformMatrix(const Context *context,
3044 angle::EntryPoint entryPoint,
3045 GLenum valueType,
3046 UniformLocation location,
3047 GLsizei count,
3048 GLboolean transpose)
3049 {
3050 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
3051 {
3052 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kES3Required);
3053 return false;
3054 }
3055
3056 const LinkedUniform *uniform = nullptr;
3057 Program *programObject = context->getActiveLinkedProgram();
3058 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
3059 &uniform) &&
3060 ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType());
3061 }
3062
ValidateStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLenum * nativeType,unsigned int * numParams)3063 bool ValidateStateQuery(const Context *context,
3064 angle::EntryPoint entryPoint,
3065 GLenum pname,
3066 GLenum *nativeType,
3067 unsigned int *numParams)
3068 {
3069 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
3070 {
3071 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
3072 return false;
3073 }
3074
3075 const Caps &caps = context->getCaps();
3076
3077 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
3078 {
3079 int colorAttachment = (pname - GL_DRAW_BUFFER0);
3080
3081 if (colorAttachment >= caps.maxDrawBuffers)
3082 {
3083 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
3084 return false;
3085 }
3086 }
3087
3088 switch (pname)
3089 {
3090 case GL_TEXTURE_BINDING_2D:
3091 case GL_TEXTURE_BINDING_CUBE_MAP:
3092 case GL_TEXTURE_BINDING_3D:
3093 case GL_TEXTURE_BINDING_2D_ARRAY:
3094 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
3095 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
3096 break;
3097
3098 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
3099 if (!context->getExtensions().textureRectangleANGLE)
3100 {
3101 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3102 return false;
3103 }
3104 break;
3105
3106 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3107 if (!context->getExtensions().EGLStreamConsumerExternalNV &&
3108 !context->getExtensions().EGLImageExternalOES)
3109 {
3110 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3111 return false;
3112 }
3113 break;
3114
3115 case GL_TEXTURE_BUFFER_BINDING:
3116 case GL_TEXTURE_BINDING_BUFFER:
3117 case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
3118 case GL_MAX_TEXTURE_BUFFER_SIZE:
3119 if (context->getClientVersion() < Version(3, 2) &&
3120 !context->getExtensions().textureBufferAny())
3121 {
3122 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
3123 return false;
3124 }
3125 break;
3126
3127 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3128 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
3129 {
3130 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
3131 ASSERT(readFramebuffer);
3132
3133 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint,
3134 readFramebuffer))
3135 {
3136 return false;
3137 }
3138
3139 if (readFramebuffer->getReadBufferState() == GL_NONE)
3140 {
3141 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
3142 return false;
3143 }
3144
3145 const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
3146 if (!attachment)
3147 {
3148 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNotAttached);
3149 return false;
3150 }
3151 break;
3152 }
3153
3154 case GL_PRIMITIVE_BOUNDING_BOX:
3155 if (!context->getExtensions().primitiveBoundingBoxAny())
3156 {
3157 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
3158 return false;
3159 }
3160 break;
3161
3162 case GL_SHADING_RATE_QCOM:
3163 if (!context->getExtensions().shadingRateQCOM)
3164 {
3165 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
3166 return false;
3167 }
3168 break;
3169
3170 case GL_MULTISAMPLE_LINE_WIDTH_RANGE:
3171 if (context->getClientVersion() < Version(3, 2))
3172 {
3173 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3174 return false;
3175 }
3176 break;
3177
3178 case GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY:
3179 if (context->getClientVersion() < Version(3, 2))
3180 {
3181 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3182 return false;
3183 }
3184 break;
3185
3186 case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
3187 if (context->getClientVersion() < Version(3, 2) &&
3188 !context->getExtensions().tessellationShaderAny())
3189 {
3190 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
3191 return false;
3192 }
3193 break;
3194
3195 default:
3196 break;
3197 }
3198
3199 // pname is valid, but there are no parameters to return
3200 if (*numParams == 0)
3201 {
3202 return false;
3203 }
3204
3205 return true;
3206 }
3207
ValidateGetBooleanvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLboolean * params)3208 bool ValidateGetBooleanvRobustANGLE(const Context *context,
3209 angle::EntryPoint entryPoint,
3210 GLenum pname,
3211 GLsizei bufSize,
3212 const GLsizei *length,
3213 const GLboolean *params)
3214 {
3215 GLenum nativeType;
3216 unsigned int numParams = 0;
3217
3218 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3219 {
3220 return false;
3221 }
3222
3223 SetRobustLengthParam(length, numParams);
3224
3225 return true;
3226 }
3227
ValidateGetFloatvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)3228 bool ValidateGetFloatvRobustANGLE(const Context *context,
3229 angle::EntryPoint entryPoint,
3230 GLenum pname,
3231 GLsizei bufSize,
3232 const GLsizei *length,
3233 const GLfloat *params)
3234 {
3235 GLenum nativeType;
3236 unsigned int numParams = 0;
3237
3238 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3239 {
3240 return false;
3241 }
3242
3243 SetRobustLengthParam(length, numParams);
3244
3245 return true;
3246 }
3247
ValidateGetIntegervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * data)3248 bool ValidateGetIntegervRobustANGLE(const Context *context,
3249 angle::EntryPoint entryPoint,
3250 GLenum pname,
3251 GLsizei bufSize,
3252 const GLsizei *length,
3253 const GLint *data)
3254 {
3255 GLenum nativeType;
3256 unsigned int numParams = 0;
3257
3258 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3259 {
3260 return false;
3261 }
3262
3263 SetRobustLengthParam(length, numParams);
3264
3265 return true;
3266 }
3267
ValidateGetInteger64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,const GLsizei * length,GLint64 * data)3268 bool ValidateGetInteger64vRobustANGLE(const Context *context,
3269 angle::EntryPoint entryPoint,
3270 GLenum pname,
3271 GLsizei bufSize,
3272 const GLsizei *length,
3273 GLint64 *data)
3274 {
3275 GLenum nativeType;
3276 unsigned int numParams = 0;
3277
3278 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
3279 {
3280 return false;
3281 }
3282
3283 if (nativeType == GL_INT_64_ANGLEX)
3284 {
3285 CastStateValues(context, nativeType, pname, numParams, data);
3286 return false;
3287 }
3288
3289 SetRobustLengthParam(length, numParams);
3290 return true;
3291 }
3292
ValidateRobustStateQuery(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLsizei bufSize,GLenum * nativeType,unsigned int * numParams)3293 bool ValidateRobustStateQuery(const Context *context,
3294 angle::EntryPoint entryPoint,
3295 GLenum pname,
3296 GLsizei bufSize,
3297 GLenum *nativeType,
3298 unsigned int *numParams)
3299 {
3300 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
3301 {
3302 return false;
3303 }
3304
3305 if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams))
3306 {
3307 return false;
3308 }
3309
3310 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams))
3311 {
3312 return false;
3313 }
3314
3315 return true;
3316 }
3317
ValidateCopyImageSubDataTarget(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target)3318 bool ValidateCopyImageSubDataTarget(const Context *context,
3319 angle::EntryPoint entryPoint,
3320 GLuint name,
3321 GLenum target)
3322 {
3323 // From EXT_copy_image: INVALID_ENUM is generated if either <srcTarget> or <dstTarget> is not
3324 // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the
3325 // cubemap face selectors described in table 3.17, or if the target does not match the type of
3326 // the object. INVALID_VALUE is generated if either <srcName> or <dstName> does not correspond
3327 // to a valid renderbuffer or texture object according to the corresponding target parameter.
3328 switch (target)
3329 {
3330 case GL_RENDERBUFFER:
3331 {
3332 RenderbufferID renderbuffer = PackParam<RenderbufferID>(name);
3333 if (!context->isRenderbuffer(renderbuffer))
3334 {
3335 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName);
3336 return false;
3337 }
3338 break;
3339 }
3340 case GL_TEXTURE_2D:
3341 case GL_TEXTURE_3D:
3342 case GL_TEXTURE_2D_ARRAY:
3343 case GL_TEXTURE_CUBE_MAP:
3344 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3345 case GL_TEXTURE_EXTERNAL_OES:
3346 {
3347 TextureID texture = PackParam<TextureID>(name);
3348 if (!context->isTexture(texture))
3349 {
3350 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName);
3351 return false;
3352 }
3353
3354 Texture *textureObject = context->getTexture(texture);
3355 if (textureObject && textureObject->getType() != PackParam<TextureType>(target))
3356 {
3357 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, err::kTextureTypeMismatch);
3358 return false;
3359 }
3360 break;
3361 }
3362 default:
3363 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3364 return false;
3365 }
3366
3367 return true;
3368 }
3369
ValidateCopyImageSubDataLevel(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLint level)3370 bool ValidateCopyImageSubDataLevel(const Context *context,
3371 angle::EntryPoint entryPoint,
3372 GLenum target,
3373 GLint level)
3374 {
3375 switch (target)
3376 {
3377 case GL_RENDERBUFFER:
3378 {
3379 if (level != 0)
3380 {
3381 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3382 return false;
3383 }
3384 break;
3385 }
3386 case GL_TEXTURE_2D:
3387 case GL_TEXTURE_3D:
3388 case GL_TEXTURE_2D_ARRAY:
3389 case GL_TEXTURE_CUBE_MAP:
3390 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3391 case GL_TEXTURE_EXTERNAL_OES:
3392 {
3393 if (!ValidMipLevel(context, PackParam<TextureType>(target), level))
3394 {
3395 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3396 return false;
3397 }
3398 break;
3399 }
3400 default:
3401 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3402 return false;
3403 }
3404
3405 return true;
3406 }
3407
ValidateCopyImageSubDataTargetRegion(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target,GLint level,GLint offsetX,GLint offsetY,GLint offsetZ,GLsizei width,GLsizei height,GLsizei * samples)3408 bool ValidateCopyImageSubDataTargetRegion(const Context *context,
3409 angle::EntryPoint entryPoint,
3410 GLuint name,
3411 GLenum target,
3412 GLint level,
3413 GLint offsetX,
3414 GLint offsetY,
3415 GLint offsetZ,
3416 GLsizei width,
3417 GLsizei height,
3418 GLsizei *samples)
3419 {
3420 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
3421 // of the corresponding image object.
3422 if (offsetX < 0 || offsetY < 0 || offsetZ < 0)
3423 {
3424 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3425 return false;
3426 }
3427
3428 if (target == GL_RENDERBUFFER)
3429 {
3430 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
3431 // boundaries of the corresponding image object
3432 Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
3433 if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height))
3434 {
3435 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
3436 return false;
3437 }
3438 }
3439 else
3440 {
3441 Texture *texture = context->getTexture(PackParam<TextureID>(name));
3442
3443 // INVALID_OPERATION is generated if either object is a texture and the texture is not
3444 // complete
3445 // This will handle the texture completeness check. Note that this ignores format-based
3446 // compleness rules.
3447 if (!texture->isSamplerCompleteForCopyImage(context, nullptr))
3448 {
3449 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNotTextureComplete);
3450 return false;
3451 }
3452
3453 GLenum textureTargetToUse = target;
3454 if (target == GL_TEXTURE_CUBE_MAP)
3455 {
3456 // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
3457 textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3458 }
3459
3460 const GLsizei textureWidth = static_cast<GLsizei>(
3461 texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level));
3462 const GLsizei textureHeight = static_cast<GLsizei>(
3463 texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level));
3464
3465 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
3466 // boundaries of the corresponding image object
3467 if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height))
3468 {
3469 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
3470 return false;
3471 }
3472
3473 *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level);
3474 *samples = (*samples == 0) ? 1 : *samples;
3475 }
3476
3477 return true;
3478 }
3479
ValidateCompressedRegion(const Context * context,angle::EntryPoint entryPoint,const InternalFormat & formatInfo,GLsizei width,GLsizei height)3480 bool ValidateCompressedRegion(const Context *context,
3481 angle::EntryPoint entryPoint,
3482 const InternalFormat &formatInfo,
3483 GLsizei width,
3484 GLsizei height)
3485 {
3486 ASSERT(formatInfo.compressed);
3487
3488 // INVALID_VALUE is generated if the image format is compressed and the dimensions of the
3489 // subregion fail to meet the alignment constraints of the format.
3490 if ((width % formatInfo.compressedBlockWidth != 0) ||
3491 (height % formatInfo.compressedBlockHeight != 0))
3492 {
3493 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedRegionSize);
3494 return false;
3495 }
3496
3497 return true;
3498 }
3499
GetTargetFormatInfo(const Context * context,angle::EntryPoint entryPoint,GLuint name,GLenum target,GLint level)3500 const InternalFormat &GetTargetFormatInfo(const Context *context,
3501 angle::EntryPoint entryPoint,
3502 GLuint name,
3503 GLenum target,
3504 GLint level)
3505 {
3506 static const InternalFormat defaultInternalFormat;
3507
3508 switch (target)
3509 {
3510 case GL_RENDERBUFFER:
3511 {
3512 Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
3513 return *buffer->getFormat().info;
3514 }
3515 case GL_TEXTURE_2D:
3516 case GL_TEXTURE_3D:
3517 case GL_TEXTURE_2D_ARRAY:
3518 case GL_TEXTURE_CUBE_MAP:
3519 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
3520 case GL_TEXTURE_EXTERNAL_OES:
3521 {
3522 Texture *texture = context->getTexture(PackParam<TextureID>(name));
3523 GLenum textureTargetToUse = target;
3524
3525 if (target == GL_TEXTURE_CUBE_MAP)
3526 {
3527 // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the
3528 // textureWidth/textureHeight
3529 textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
3530 }
3531 return *texture->getFormat(PackParam<TextureTarget>(textureTargetToUse), level).info;
3532 }
3533 default:
3534 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
3535 return defaultInternalFormat;
3536 }
3537 }
3538
ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat,GLenum compressedFormat)3539 bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat)
3540 {
3541 // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the
3542 // EXT_copy_image spec.
3543 switch (compressedFormat)
3544 {
3545 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
3546 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
3547 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
3548 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
3549 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
3550 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
3551 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
3552 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
3553 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
3554 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
3555 case GL_COMPRESSED_RGBA8_ETC2_EAC:
3556 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
3557 case GL_COMPRESSED_RG11_EAC:
3558 case GL_COMPRESSED_SIGNED_RG11_EAC:
3559 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
3560 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
3561 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
3562 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
3563 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
3564 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
3565 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
3566 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
3567 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
3568 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
3569 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
3570 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
3571 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
3572 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
3573 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
3574 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
3575 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
3576 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
3577 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
3578 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
3579 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
3580 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
3581 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
3582 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
3583 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
3584 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
3585 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
3586 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
3587 case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
3588 case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
3589 case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
3590 case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
3591 case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
3592 case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
3593 case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
3594 case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
3595 case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
3596 case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
3597 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
3598 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
3599 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
3600 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
3601 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
3602 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
3603 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
3604 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
3605 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
3606 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
3607 {
3608 switch (uncompressedFormat)
3609 {
3610 case GL_RGBA32UI:
3611 case GL_RGBA32I:
3612 case GL_RGBA32F:
3613 return true;
3614 default:
3615 return false;
3616 }
3617 }
3618 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
3619 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
3620 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
3621 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
3622 case GL_COMPRESSED_RED_RGTC1_EXT:
3623 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
3624 case GL_COMPRESSED_RGB8_ETC2:
3625 case GL_COMPRESSED_SRGB8_ETC2:
3626 case GL_COMPRESSED_R11_EAC:
3627 case GL_COMPRESSED_SIGNED_R11_EAC:
3628 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3629 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3630 {
3631 switch (uncompressedFormat)
3632 {
3633 case GL_RGBA16UI:
3634 case GL_RGBA16I:
3635 case GL_RGBA16F:
3636 case GL_RG32UI:
3637 case GL_RG32I:
3638 case GL_RG32F:
3639 return true;
3640 default:
3641 return false;
3642 }
3643 }
3644 default:
3645 break;
3646 }
3647
3648 return false;
3649 }
3650
ValidateCopyCompressedFormatCompatible(const InternalFormat & srcFormatInfo,const InternalFormat & dstFormatInfo)3651 bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo,
3652 const InternalFormat &dstFormatInfo)
3653 {
3654 // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec.
3655
3656 ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat);
3657
3658 const GLenum srcFormat = srcFormatInfo.internalFormat;
3659 const GLenum dstFormat = dstFormatInfo.internalFormat;
3660
3661 switch (srcFormat)
3662 {
3663 case GL_COMPRESSED_RED_RGTC1_EXT:
3664 return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT);
3665 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
3666 return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT);
3667 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
3668 return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
3669 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
3670 return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT);
3671 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
3672 return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
3673 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
3674 return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
3675 case GL_COMPRESSED_R11_EAC:
3676 return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC);
3677 case GL_COMPRESSED_SIGNED_R11_EAC:
3678 return (dstFormat == GL_COMPRESSED_R11_EAC);
3679 case GL_COMPRESSED_RG11_EAC:
3680 return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC);
3681 case GL_COMPRESSED_SIGNED_RG11_EAC:
3682 return (dstFormat == GL_COMPRESSED_RG11_EAC);
3683 default:
3684 break;
3685 }
3686
3687 // Since they can't be the same format and are both compressed formats, one must be linear and
3688 // the other nonlinear.
3689 if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding)
3690 {
3691 return false;
3692 }
3693
3694 const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat;
3695 const GLenum nonLinearFormat =
3696 (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat;
3697
3698 switch (linearFormat)
3699 {
3700 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
3701 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
3702 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
3703 return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
3704 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
3705 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
3706 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
3707 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
3708 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
3709 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
3710 case GL_COMPRESSED_RGB8_ETC2:
3711 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2);
3712 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
3713 return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
3714 case GL_COMPRESSED_RGBA8_ETC2_EAC:
3715 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
3716 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
3717 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
3718 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
3719 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
3720 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
3721 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
3722 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
3723 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
3724 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
3725 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
3726 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
3727 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
3728 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
3729 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
3730 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
3731 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
3732 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
3733 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
3734 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
3735 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
3736 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
3737 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
3738 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
3739 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
3740 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
3741 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
3742 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
3743 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
3744 case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
3745 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES);
3746 case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
3747 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES);
3748 case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
3749 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES);
3750 case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
3751 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES);
3752 case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
3753 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES);
3754 case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
3755 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES);
3756 case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
3757 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES);
3758 case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
3759 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES);
3760 case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
3761 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES);
3762 case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
3763 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES);
3764 default:
3765 break;
3766 }
3767
3768 return false;
3769 }
3770
ValidateCopyFormatCompatible(const InternalFormat & srcFormatInfo,const InternalFormat & dstFormatInfo)3771 bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo,
3772 const InternalFormat &dstFormatInfo)
3773 {
3774 // Matching source and destination formats are compatible.
3775 if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat)
3776 {
3777 return true;
3778 }
3779
3780 if (srcFormatInfo.compressed != dstFormatInfo.compressed)
3781 {
3782 GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
3783 : dstFormatInfo.internalFormat;
3784 GLenum compressedFormat = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
3785 : dstFormatInfo.internalFormat;
3786
3787 return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat);
3788 }
3789
3790 if (!srcFormatInfo.compressed)
3791 {
3792 // Source and destination are uncompressed formats.
3793 return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes);
3794 }
3795
3796 return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo);
3797 }
3798
ValidateCopyImageSubDataBase(const Context * context,angle::EntryPoint entryPoint,GLuint srcName,GLenum srcTarget,GLint srcLevel,GLint srcX,GLint srcY,GLint srcZ,GLuint dstName,GLenum dstTarget,GLint dstLevel,GLint dstX,GLint dstY,GLint dstZ,GLsizei srcWidth,GLsizei srcHeight,GLsizei srcDepth)3799 bool ValidateCopyImageSubDataBase(const Context *context,
3800 angle::EntryPoint entryPoint,
3801 GLuint srcName,
3802 GLenum srcTarget,
3803 GLint srcLevel,
3804 GLint srcX,
3805 GLint srcY,
3806 GLint srcZ,
3807 GLuint dstName,
3808 GLenum dstTarget,
3809 GLint dstLevel,
3810 GLint dstX,
3811 GLint dstY,
3812 GLint dstZ,
3813 GLsizei srcWidth,
3814 GLsizei srcHeight,
3815 GLsizei srcDepth)
3816 {
3817 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
3818 // of the corresponding image object
3819 if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0))
3820 {
3821 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3822 return false;
3823 }
3824
3825 if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget))
3826 {
3827 return false;
3828 }
3829 if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget))
3830 {
3831 return false;
3832 }
3833
3834 if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel))
3835 {
3836 return false;
3837 }
3838 if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel))
3839 {
3840 return false;
3841 }
3842
3843 const InternalFormat &srcFormatInfo =
3844 GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel);
3845 const InternalFormat &dstFormatInfo =
3846 GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel);
3847 GLsizei dstWidth = srcWidth;
3848 GLsizei dstHeight = srcHeight;
3849 GLsizei srcSamples = 1;
3850 GLsizei dstSamples = 1;
3851
3852 if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE)
3853 {
3854 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureLevel);
3855 return false;
3856 }
3857
3858 if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel,
3859 srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples))
3860 {
3861 return false;
3862 }
3863
3864 // When copying from a compressed image to an uncompressed image the image texel dimensions
3865 // written to the uncompressed image will be source extent divided by the compressed texel block
3866 // dimensions.
3867 if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed))
3868 {
3869 ASSERT(srcFormatInfo.compressedBlockWidth != 0);
3870 ASSERT(srcFormatInfo.compressedBlockHeight != 0);
3871
3872 dstWidth /= srcFormatInfo.compressedBlockWidth;
3873 dstHeight /= srcFormatInfo.compressedBlockHeight;
3874 }
3875 // When copying from an uncompressed image to a compressed image the image texel dimensions
3876 // written to the compressed image will be the source extent multiplied by the compressed texel
3877 // block dimensions.
3878 else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed))
3879 {
3880 dstWidth *= dstFormatInfo.compressedBlockWidth;
3881 dstHeight *= dstFormatInfo.compressedBlockHeight;
3882 }
3883
3884 if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel,
3885 dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples))
3886 {
3887 return false;
3888 }
3889
3890 bool fillsEntireMip = false;
3891 gl::Texture *dstTexture = context->getTexture({dstName});
3892 gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget);
3893 // TODO(http://anglebug.com/42264179): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER)
3894 // are unsupported when used with compressed formats due to gl::PackParam() returning
3895 // TextureTarget::InvalidEnum.
3896 if (dstTargetPacked != gl::TextureTarget::InvalidEnum)
3897 {
3898 const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel);
3899 fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width &&
3900 srcHeight == dstExtents.height && srcDepth == dstExtents.depth;
3901 }
3902
3903 if (srcFormatInfo.compressed && !fillsEntireMip &&
3904 !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight))
3905 {
3906 return false;
3907 }
3908
3909 if (dstFormatInfo.compressed && !fillsEntireMip &&
3910 !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight))
3911 {
3912 return false;
3913 }
3914
3915 // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats
3916 // are not compatible, if one image is compressed and the other is uncompressed and the block
3917 // size of compressed image is not equal to the texel size of the compressed image.
3918 if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo))
3919 {
3920 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIncompatibleTextures);
3921 return false;
3922 }
3923
3924 // INVALID_OPERATION is generated if the source and destination number of samples do not match
3925 if (srcSamples != dstSamples)
3926 {
3927 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
3928 return false;
3929 }
3930
3931 return true;
3932 }
3933
ValidateCopyTexImageParametersBase(const Context * context,angle::EntryPoint entryPoint,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)3934 bool ValidateCopyTexImageParametersBase(const Context *context,
3935 angle::EntryPoint entryPoint,
3936 TextureTarget target,
3937 GLint level,
3938 GLenum internalformat,
3939 bool isSubImage,
3940 GLint xoffset,
3941 GLint yoffset,
3942 GLint zoffset,
3943 GLint x,
3944 GLint y,
3945 GLsizei width,
3946 GLsizei height,
3947 GLint border,
3948 Format *textureFormatOut)
3949 {
3950 TextureType texType = TextureTargetToType(target);
3951
3952 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
3953 {
3954 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
3955 return false;
3956 }
3957
3958 if (width < 0 || height < 0)
3959 {
3960 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
3961 return false;
3962 }
3963
3964 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3965 std::numeric_limits<GLsizei>::max() - yoffset < height)
3966 {
3967 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
3968 return false;
3969 }
3970
3971 if (std::numeric_limits<GLint>::max() - width < x ||
3972 std::numeric_limits<GLint>::max() - height < y)
3973 {
3974 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
3975 return false;
3976 }
3977
3978 if (border != 0)
3979 {
3980 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
3981 return false;
3982 }
3983
3984 if (!ValidMipLevel(context, texType, level))
3985 {
3986 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
3987 return false;
3988 }
3989
3990 const State &state = context->getState();
3991 Framebuffer *readFramebuffer = state.getReadFramebuffer();
3992 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
3993 {
3994 return false;
3995 }
3996
3997 // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since
3998 // they will be resolved before copying.
3999 if (!readFramebuffer->isDefault() &&
4000 !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
4001 {
4002 return false;
4003 }
4004
4005 if (readFramebuffer->getReadBufferState() == GL_NONE)
4006 {
4007 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
4008 return false;
4009 }
4010
4011 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
4012 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
4013 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
4014 // situation is an application error that would lead to a crash in ANGLE.
4015 const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
4016 if (source == nullptr)
4017 {
4018 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
4019 return false;
4020 }
4021
4022 if (source->isYUV())
4023 {
4024 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCopyFromYUVFramebuffer);
4025 return false;
4026 }
4027
4028 // OVR_multiview spec:
4029 // INVALID_FRAMEBUFFER_OPERATION is generated by commands that read from the
4030 // framebuffer such as BlitFramebuffer, ReadPixels, CopyTexImage*, and
4031 // CopyTexSubImage*, if the number of views in the current read framebuffer
4032 // is greater than 1.
4033 if (readFramebuffer->readDisallowedByMultiview())
4034 {
4035 ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
4036 return false;
4037 }
4038
4039 const Caps &caps = context->getCaps();
4040
4041 GLint maxDimension = 0;
4042 switch (texType)
4043 {
4044 case TextureType::_2D:
4045 maxDimension = caps.max2DTextureSize;
4046 break;
4047
4048 case TextureType::CubeMap:
4049 case TextureType::CubeMapArray:
4050 maxDimension = caps.maxCubeMapTextureSize;
4051 break;
4052
4053 case TextureType::Rectangle:
4054 maxDimension = caps.maxRectangleTextureSize;
4055 break;
4056
4057 case TextureType::_2DArray:
4058 maxDimension = caps.max2DTextureSize;
4059 break;
4060
4061 case TextureType::_3D:
4062 maxDimension = caps.max3DTextureSize;
4063 break;
4064
4065 default:
4066 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
4067 return false;
4068 }
4069
4070 Texture *texture = state.getTargetTexture(texType);
4071 if (!texture)
4072 {
4073 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
4074 return false;
4075 }
4076
4077 if (texture->getImmutableFormat() && !isSubImage)
4078 {
4079 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
4080 return false;
4081 }
4082
4083 const InternalFormat &formatInfo =
4084 isSubImage ? *texture->getFormat(target, level).info
4085 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
4086
4087 if (formatInfo.depthBits > 0 || formatInfo.compressed)
4088 {
4089 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
4090 return false;
4091 }
4092
4093 if (isSubImage)
4094 {
4095 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
4096 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
4097 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
4098 {
4099 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
4100 return false;
4101 }
4102 }
4103 else
4104 {
4105 if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
4106 width != height)
4107 {
4108 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapIncomplete);
4109 return false;
4110 }
4111
4112 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
4113 {
4114 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
4115 return false;
4116 }
4117
4118 int maxLevelDimension = (maxDimension >> level);
4119 if (static_cast<int>(width) > maxLevelDimension ||
4120 static_cast<int>(height) > maxLevelDimension)
4121 {
4122 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
4123 return false;
4124 }
4125 }
4126
4127 // Do not leak the previous texture format for non-subImage case.
4128 if (textureFormatOut && isSubImage)
4129 {
4130 *textureFormatOut = texture->getFormat(target, level);
4131 }
4132
4133 // Detect texture copying feedback loops for WebGL.
4134 if (context->isWebGL())
4135 {
4136 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
4137 {
4138 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFeedbackLoop);
4139 return false;
4140 }
4141 }
4142
4143 return true;
4144 }
4145
ValidateProgramPipelineDrawStates(const Context * context,const Extensions & extensions,ProgramPipeline * programPipeline)4146 const char *ValidateProgramPipelineDrawStates(const Context *context,
4147 const Extensions &extensions,
4148 ProgramPipeline *programPipeline)
4149 {
4150 for (const ShaderType shaderType : gl::AllShaderTypes())
4151 {
4152 const SharedProgramExecutable &executable =
4153 programPipeline->getShaderProgramExecutable(shaderType);
4154 if (executable)
4155 {
4156 const char *errorMsg = ValidateProgramDrawStates(context, extensions, *executable);
4157 if (errorMsg)
4158 {
4159 return errorMsg;
4160 }
4161 }
4162 }
4163
4164 return nullptr;
4165 }
4166
ValidateProgramPipelineAttachedPrograms(ProgramPipeline * programPipeline)4167 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
4168 {
4169 // An INVALID_OPERATION error is generated by any command that transfers vertices to the
4170 // GL or launches compute work if the current set of active
4171 // program objects cannot be executed, for reasons including:
4172 // - There is no current program object specified by UseProgram, there is a current program
4173 // pipeline object, and that object is empty (no executable code is installed for any stage).
4174 // - A program object is active for at least one, but not all of the shader
4175 // stages that were present when the program was linked.
4176 if (!programPipeline->getExecutable().getLinkedShaderStages().any())
4177 {
4178 return gl::err::kNoExecutableCodeInstalled;
4179 }
4180 for (const ShaderType shaderType : gl::AllShaderTypes())
4181 {
4182 const Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
4183 if (shaderProgram)
4184 {
4185 const ProgramExecutable &executable = shaderProgram->getExecutable();
4186 for (const ShaderType programShaderType : executable.getLinkedShaderStages())
4187 {
4188 if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
4189 {
4190 return gl::err::kNotAllStagesOfSeparableProgramUsed;
4191 }
4192 }
4193 }
4194 }
4195
4196 // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders
4197 // A non-separable program object or program pipeline object that includes
4198 // a geometry shader must also include a vertex shader.
4199 // An INVALID_OPERATION error is generated by any command that transfers
4200 // vertices to the GL if the current program state has a geometry shader
4201 // but no vertex shader.
4202 if (!programPipeline->getShaderProgram(ShaderType::Vertex) &&
4203 programPipeline->getShaderProgram(ShaderType::Geometry))
4204 {
4205 return gl::err::kNoActiveGraphicsShaderStage;
4206 }
4207
4208 return nullptr;
4209 }
4210
ValidateDrawStates(const Context * context,GLenum * outErrorCode)4211 const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode)
4212 {
4213 // Note all errors returned from this function are INVALID_OPERATION except for the draw
4214 // framebuffer completeness check.
4215 *outErrorCode = GL_INVALID_OPERATION;
4216
4217 const Extensions &extensions = context->getExtensions();
4218 const State &state = context->getState();
4219
4220 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
4221 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
4222 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
4223 VertexArray *vertexArray = state.getVertexArray();
4224 ASSERT(vertexArray);
4225
4226 if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer())
4227 {
4228 return kBufferMapped;
4229 }
4230
4231 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
4232 // Section 6.10 of the WebGL 1.0 spec.
4233 Framebuffer *framebuffer = state.getDrawFramebuffer();
4234 ASSERT(framebuffer);
4235
4236 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
4237 extensions.webglCompatibilityANGLE)
4238 {
4239 ASSERT(framebuffer);
4240 const FramebufferAttachment *dsAttachment =
4241 framebuffer->getStencilOrDepthStencilAttachment();
4242 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
4243 ASSERT(stencilBits <= 8);
4244
4245 const DepthStencilState &depthStencilState = state.getDepthStencilState();
4246 if (depthStencilState.stencilTest && stencilBits > 0)
4247 {
4248 auto maxStencilValue = angle::BitMask<GLuint>(stencilBits);
4249
4250 bool differentRefs =
4251 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
4252 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
4253 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
4254 (depthStencilState.stencilBackWritemask & maxStencilValue);
4255 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
4256 (depthStencilState.stencilBackMask & maxStencilValue);
4257
4258 if (differentRefs || differentWritemasks || differentMasks)
4259 {
4260 if (!extensions.webglCompatibilityANGLE)
4261 {
4262 WARN() << "This ANGLE implementation does not support separate front/back "
4263 "stencil writemasks, reference values, or stencil mask values.";
4264 }
4265 return kStencilReferenceMaskOrMismatch;
4266 }
4267 }
4268 }
4269
4270 if (!extensions.floatBlendEXT)
4271 {
4272 const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
4273 state.getBlendEnabledDrawBufferMask() &
4274 framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
4275 if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
4276 {
4277 return kUnsupportedFloatBlending;
4278 }
4279 }
4280
4281 if (extensions.renderSharedExponentQCOM)
4282 {
4283 if (!ValidateColorMasksForSharedExponentColorBuffers(state.getBlendStateExt(), framebuffer))
4284 {
4285 return kUnsupportedColorMaskForSharedExponentColorBuffer;
4286 }
4287 }
4288
4289 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
4290 extensions.webglCompatibilityANGLE)
4291 {
4292 if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
4293 {
4294 if (extensions.webglCompatibilityANGLE)
4295 {
4296 return kInvalidConstantColor;
4297 }
4298
4299 WARN() << kConstantColorAlphaLimitation;
4300 return kConstantColorAlphaLimitation;
4301 }
4302 }
4303
4304 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
4305 if (!framebufferStatus.isComplete())
4306 {
4307 *outErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION;
4308 ASSERT(framebufferStatus.reason);
4309 return framebufferStatus.reason;
4310 }
4311
4312 bool framebufferIsYUV = framebuffer->hasYUVAttachment();
4313 if (framebufferIsYUV)
4314 {
4315 const BlendState &blendState = state.getBlendState();
4316 if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue)
4317 {
4318 // When rendering into a YUV framebuffer, the color mask must have r g and b set to
4319 // true.
4320 return kInvalidColorMaskForYUV;
4321 }
4322
4323 if (blendState.blend)
4324 {
4325 // When rendering into a YUV framebuffer, blending must be disabled.
4326 return kInvalidBlendStateForYUV;
4327 }
4328 }
4329 else
4330 {
4331 if (framebuffer->hasExternalTextureAttachment())
4332 {
4333 // It is an error to render into an external texture that is not YUV.
4334 return kExternalTextureAttachmentNotYUV;
4335 }
4336 }
4337
4338 // Advanced blend equation can only be enabled for a single render target.
4339 const BlendStateExt &blendStateExt = state.getBlendStateExt();
4340 if (blendStateExt.getUsesAdvancedBlendEquationMask().any())
4341 {
4342 const size_t drawBufferCount = framebuffer->getDrawbufferStateCount();
4343 uint32_t advancedBlendRenderTargetCount = 0;
4344
4345 for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask())
4346 {
4347 if (drawBufferIndex < drawBufferCount &&
4348 framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE &&
4349 blendStateExt.getEnabledMask().test(drawBufferIndex) &&
4350 blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex))
4351 {
4352 ++advancedBlendRenderTargetCount;
4353 }
4354 }
4355
4356 if (advancedBlendRenderTargetCount > 1)
4357 {
4358 return kAdvancedBlendEquationWithMRT;
4359 }
4360 }
4361
4362 // Dual-source blending functions limit the number of supported draw buffers.
4363 if (blendStateExt.getUsesExtendedBlendFactorMask().any())
4364 {
4365 // Imply the strictest spec interpretation to pass on all OpenGL drivers:
4366 // dual-source blending is considered active if the blend state contains
4367 // any SRC1 factor no matter what.
4368 const size_t drawBufferCount = framebuffer->getDrawbufferStateCount();
4369 for (size_t drawBufferIndex = context->getCaps().maxDualSourceDrawBuffers;
4370 drawBufferIndex < drawBufferCount; ++drawBufferIndex)
4371 {
4372 if (framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE)
4373 {
4374 return kDualSourceBlendingDrawBuffersLimit;
4375 }
4376 }
4377 }
4378
4379 if (context->getStateCache().hasAnyEnabledClientAttrib())
4380 {
4381 if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled())
4382 {
4383 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
4384 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
4385 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
4386 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
4387 return kVertexArrayNoBuffer;
4388 }
4389
4390 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
4391 {
4392 // This is an application error that would normally result in a crash, but we catch it
4393 // and return an error
4394 return kVertexArrayNoBufferPointer;
4395 }
4396 }
4397
4398 // If we are running GLES1, there is no current program.
4399 if (context->getClientVersion() >= Version(2, 0))
4400 {
4401 Program *program = state.getLinkedProgram(context);
4402 ProgramPipeline *programPipeline = state.getLinkedProgramPipeline(context);
4403 const ProgramExecutable *executable = state.getProgramExecutable();
4404
4405 bool programIsYUVOutput = false;
4406
4407 if (program)
4408 {
4409 const char *errorMsg = ValidateProgramDrawStates(context, extensions, *executable);
4410 if (errorMsg)
4411 {
4412 return errorMsg;
4413 }
4414
4415 programIsYUVOutput = executable->isYUVOutput();
4416 }
4417 else if (programPipeline)
4418 {
4419 const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
4420 if (errorMsg)
4421 {
4422 return errorMsg;
4423 }
4424
4425 errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline);
4426 if (errorMsg)
4427 {
4428 return errorMsg;
4429 }
4430
4431 if (!programPipeline->isLinked())
4432 {
4433 return kProgramPipelineLinkFailed;
4434 }
4435
4436 programIsYUVOutput = executable->isYUVOutput();
4437 }
4438
4439 if (executable)
4440 {
4441 if (!executable->validateSamplers(context->getCaps()))
4442 {
4443 return kTextureTypeConflict;
4444 }
4445
4446 if (executable->hasLinkedTessellationShader())
4447 {
4448 if (!executable->hasLinkedShaderStage(ShaderType::Vertex))
4449 {
4450 return kTessellationShaderRequiresVertexShader;
4451 }
4452
4453 if (!executable->hasLinkedShaderStage(ShaderType::TessControl) ||
4454 !executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
4455 {
4456 return kTessellationShaderRequiresBothControlAndEvaluation;
4457 }
4458 }
4459
4460 if (state.isTransformFeedbackActive())
4461 {
4462 if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
4463 {
4464 return kTransformFeedbackBufferMissing;
4465 }
4466 }
4467 }
4468
4469 if (programIsYUVOutput != framebufferIsYUV)
4470 {
4471 // Both the program and framebuffer must match in YUV output state.
4472 return kYUVOutputMissmatch;
4473 }
4474
4475 if (!state.validateSamplerFormats())
4476 {
4477 return kSamplerFormatMismatch;
4478 }
4479
4480 // Do some additional WebGL-specific validation
4481 if (extensions.webglCompatibilityANGLE)
4482 {
4483 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
4484 if (state.isTransformFeedbackActive() &&
4485 transformFeedbackObject->buffersBoundForOtherUseInWebGL())
4486 {
4487 return kTransformFeedbackBufferDoubleBound;
4488 }
4489
4490 // Detect rendering feedback loops for WebGL.
4491 if (framebuffer->formsRenderingFeedbackLoopWith(context))
4492 {
4493 return kFeedbackLoop;
4494 }
4495
4496 // Detect that the vertex shader input types match the attribute types
4497 if (!ValidateVertexShaderAttributeTypeMatch(context))
4498 {
4499 return kVertexShaderTypeMismatch;
4500 }
4501
4502 if (!context->getState().getRasterizerState().rasterizerDiscard &&
4503 !context->getState().allActiveDrawBufferChannelsMasked())
4504 {
4505 // Detect that if there's active color buffer without fragment shader output
4506 if (!ValidateFragmentShaderColorBufferMaskMatch(context))
4507 {
4508 return kDrawBufferMaskMismatch;
4509 }
4510
4511 // Detect that the color buffer types match the fragment shader output types
4512 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
4513 {
4514 return kDrawBufferTypeMismatch;
4515 }
4516 }
4517
4518 const VertexArray *vao = context->getState().getVertexArray();
4519 if (vao->hasTransformFeedbackBindingConflict(context))
4520 {
4521 return kVertexBufferBoundForTransformFeedback;
4522 }
4523
4524 // Validate that we are rendering with a linked program.
4525 if (!program->isLinked())
4526 {
4527 return kProgramNotLinked;
4528 }
4529 }
4530
4531 // The QCOM_framebuffer_foveated spec:
4532 if (framebuffer->isFoveationEnabled())
4533 {
4534 ASSERT(extensions.framebufferFoveatedQCOM);
4535
4536 // INVALID_OPERATION is generated if a rendering command is issued and the
4537 // current bound program uses tessellation or geometry shaders.
4538 if (executable->hasLinkedShaderStage(gl::ShaderType::Geometry) ||
4539 executable->hasLinkedShaderStage(gl::ShaderType::TessControl) ||
4540 executable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
4541 {
4542 return err::kGeometryOrTessellationShaderBoundForFoveatedDraw;
4543 }
4544
4545 // INVALID_OPERATION is generated by any API call which causes a framebuffer
4546 // attachment to be written to if the framebuffer attachments have changed for
4547 // a foveated fbo.
4548 if (framebuffer->hasAnyAttachmentChanged())
4549 {
4550 return err::kFramebufferFoveationAttachmentChanged;
4551 }
4552 }
4553 }
4554
4555 *outErrorCode = GL_NO_ERROR;
4556 return nullptr;
4557 }
4558
ValidateProgramPipeline(const Context * context)4559 const char *ValidateProgramPipeline(const Context *context)
4560 {
4561 const State &state = context->getState();
4562 // If we are running GLES1, there is no current program.
4563 if (context->getClientVersion() >= Version(2, 0))
4564 {
4565 ProgramPipeline *programPipeline = state.getProgramPipeline();
4566 if (programPipeline)
4567 {
4568 const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
4569 if (errorMsg)
4570 {
4571 return errorMsg;
4572 }
4573 }
4574 }
4575 return nullptr;
4576 }
4577
RecordDrawModeError(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode)4578 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode)
4579 {
4580 const State &state = context->getState();
4581 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
4582 if (state.isTransformFeedbackActiveUnpaused())
4583 {
4584 if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint,
4585 curTransformFeedback->getPrimitiveMode(), mode))
4586 {
4587 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
4588 return;
4589 }
4590 }
4591
4592 const Extensions &extensions = context->getExtensions();
4593
4594 switch (mode)
4595 {
4596 case PrimitiveMode::Points:
4597 case PrimitiveMode::Lines:
4598 case PrimitiveMode::LineLoop:
4599 case PrimitiveMode::LineStrip:
4600 case PrimitiveMode::Triangles:
4601 case PrimitiveMode::TriangleStrip:
4602 case PrimitiveMode::TriangleFan:
4603 break;
4604
4605 case PrimitiveMode::LinesAdjacency:
4606 case PrimitiveMode::LineStripAdjacency:
4607 case PrimitiveMode::TrianglesAdjacency:
4608 case PrimitiveMode::TriangleStripAdjacency:
4609 if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2)
4610 {
4611 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
4612 return;
4613 }
4614 break;
4615
4616 case PrimitiveMode::Patches:
4617 if (!extensions.tessellationShaderAny() && context->getClientVersion() < ES_3_2)
4618 {
4619 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled);
4620 return;
4621 }
4622 break;
4623
4624 default:
4625 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawMode);
4626 return;
4627 }
4628
4629 // If we are running GLES1, there is no current program.
4630 if (context->getClientVersion() >= Version(2, 0))
4631 {
4632 const ProgramExecutable *executable = state.getProgramExecutable();
4633 ASSERT(executable);
4634
4635 // Do geometry shader specific validations
4636 if (executable->hasLinkedShaderStage(ShaderType::Geometry))
4637 {
4638 if (!IsCompatibleDrawModeWithGeometryShader(
4639 mode, executable->getGeometryShaderInputPrimitiveType()))
4640 {
4641 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4642 kIncompatibleDrawModeAgainstGeometryShader);
4643 return;
4644 }
4645 }
4646
4647 if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches)
4648 {
4649 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4650 kIncompatibleDrawModeWithTessellationShader);
4651 return;
4652 }
4653
4654 if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches)
4655 {
4656 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
4657 kIncompatibleDrawModeWithoutTessellationShader);
4658 return;
4659 }
4660 }
4661
4662 // An error should be recorded.
4663 UNREACHABLE();
4664 }
4665
ValidateDrawArraysInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4666 bool ValidateDrawArraysInstancedANGLE(const Context *context,
4667 angle::EntryPoint entryPoint,
4668 PrimitiveMode mode,
4669 GLint first,
4670 GLsizei count,
4671 GLsizei primcount)
4672 {
4673 if (!context->getExtensions().instancedArraysANGLE)
4674 {
4675 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4676 return false;
4677 }
4678
4679 if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0))
4680 {
4681 return false;
4682 }
4683
4684 return ValidateDrawInstancedANGLE(context, entryPoint);
4685 }
4686
ValidateDrawArraysInstancedEXT(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLint first,GLsizei count,GLsizei primcount)4687 bool ValidateDrawArraysInstancedEXT(const Context *context,
4688 angle::EntryPoint entryPoint,
4689 PrimitiveMode mode,
4690 GLint first,
4691 GLsizei count,
4692 GLsizei primcount)
4693 {
4694 if (!context->getExtensions().instancedArraysEXT)
4695 {
4696 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4697 return false;
4698 }
4699
4700 if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0))
4701 {
4702 return false;
4703 }
4704
4705 return true;
4706 }
4707
ValidateDrawElementsStates(const Context * context)4708 const char *ValidateDrawElementsStates(const Context *context)
4709 {
4710 const State &state = context->getState();
4711
4712 if (context->getStateCache().isTransformFeedbackActiveUnpaused())
4713 {
4714 // EXT_geometry_shader allows transform feedback to work with all draw commands.
4715 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
4716 if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2)
4717 {
4718 // It is an invalid operation to call DrawElements, DrawRangeElements or
4719 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
4720 // 86)
4721 return kUnsupportedDrawModeForTransformFeedback;
4722 }
4723 }
4724
4725 const VertexArray *vao = state.getVertexArray();
4726 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
4727
4728 if (elementArrayBuffer)
4729 {
4730 if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
4731 {
4732 return kElementArrayBufferBoundForTransformFeedback;
4733 }
4734 if (elementArrayBuffer->isMapped() &&
4735 (!elementArrayBuffer->isImmutable() ||
4736 (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0))
4737 {
4738 return kBufferMapped;
4739 }
4740 }
4741 else
4742 {
4743 // [WebGL 1.0] Section 6.2 No Client Side Arrays
4744 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
4745 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
4746 if (!context->getState().areClientArraysEnabled() || context->isWebGL())
4747 {
4748 return kMustHaveElementArrayBinding;
4749 }
4750 }
4751
4752 return nullptr;
4753 }
4754
ValidateDrawElementsInstancedANGLE(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)4755 bool ValidateDrawElementsInstancedANGLE(const Context *context,
4756 angle::EntryPoint entryPoint,
4757 PrimitiveMode mode,
4758 GLsizei count,
4759 DrawElementsType type,
4760 const void *indices,
4761 GLsizei primcount)
4762 {
4763 if (!context->getExtensions().instancedArraysANGLE)
4764 {
4765 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4766 return false;
4767 }
4768
4769 if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
4770 primcount, 0))
4771 {
4772 return false;
4773 }
4774
4775 return ValidateDrawInstancedANGLE(context, entryPoint);
4776 }
4777
ValidateDrawElementsInstancedEXT(const Context * context,angle::EntryPoint entryPoint,PrimitiveMode mode,GLsizei count,DrawElementsType type,const void * indices,GLsizei primcount)4778 bool ValidateDrawElementsInstancedEXT(const Context *context,
4779 angle::EntryPoint entryPoint,
4780 PrimitiveMode mode,
4781 GLsizei count,
4782 DrawElementsType type,
4783 const void *indices,
4784 GLsizei primcount)
4785 {
4786 if (!context->getExtensions().instancedArraysEXT)
4787 {
4788 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
4789 return false;
4790 }
4791
4792 if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
4793 primcount, 0))
4794 {
4795 return false;
4796 }
4797
4798 return true;
4799 }
4800
ValidateGetUniformBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location)4801 bool ValidateGetUniformBase(const Context *context,
4802 angle::EntryPoint entryPoint,
4803 ShaderProgramID program,
4804 UniformLocation location)
4805 {
4806 if (program.value == 0)
4807 {
4808 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kProgramDoesNotExist);
4809 return false;
4810 }
4811
4812 Program *programObject = GetValidProgram(context, entryPoint, program);
4813 if (!programObject)
4814 {
4815 return false;
4816 }
4817
4818 if (!programObject || !programObject->isLinked())
4819 {
4820 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
4821 return false;
4822 }
4823
4824 if (!programObject->getExecutable().isValidUniformLocation(location))
4825 {
4826 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
4827 return false;
4828 }
4829
4830 return true;
4831 }
4832
ValidateSizedGetUniform(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,GLsizei * length)4833 bool ValidateSizedGetUniform(const Context *context,
4834 angle::EntryPoint entryPoint,
4835 ShaderProgramID program,
4836 UniformLocation location,
4837 GLsizei bufSize,
4838 GLsizei *length)
4839 {
4840 if (length)
4841 {
4842 *length = 0;
4843 }
4844
4845 if (!ValidateGetUniformBase(context, entryPoint, program, location))
4846 {
4847 return false;
4848 }
4849
4850 if (bufSize < 0)
4851 {
4852 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNegativeBufferSize);
4853 return false;
4854 }
4855
4856 Program *programObject = context->getProgramResolveLink(program);
4857 ASSERT(programObject);
4858
4859 // sized queries -- ensure the provided buffer is large enough
4860 const LinkedUniform &uniform = programObject->getExecutable().getUniformByLocation(location);
4861 size_t requiredBytes = VariableExternalSize(uniform.getType());
4862 if (static_cast<size_t>(bufSize) < requiredBytes)
4863 {
4864 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
4865 return false;
4866 }
4867
4868 if (length)
4869 {
4870 *length = VariableComponentCount(uniform.getType());
4871 }
4872 return true;
4873 }
4874
ValidateGetnUniformfvEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLfloat * params)4875 bool ValidateGetnUniformfvEXT(const Context *context,
4876 angle::EntryPoint entryPoint,
4877 ShaderProgramID program,
4878 UniformLocation location,
4879 GLsizei bufSize,
4880 const GLfloat *params)
4881 {
4882 return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
4883 }
4884
ValidateGetnUniformfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4885 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
4886 angle::EntryPoint entryPoint,
4887 ShaderProgramID program,
4888 UniformLocation location,
4889 GLsizei bufSize,
4890 const GLsizei *length,
4891 const GLfloat *params)
4892 {
4893 UNIMPLEMENTED();
4894 return false;
4895 }
4896
ValidateGetnUniformivEXT(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLint * params)4897 bool ValidateGetnUniformivEXT(const Context *context,
4898 angle::EntryPoint entryPoint,
4899 ShaderProgramID program,
4900 UniformLocation location,
4901 GLsizei bufSize,
4902 const GLint *params)
4903 {
4904 return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
4905 }
4906
ValidateGetnUniformivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)4907 bool ValidateGetnUniformivRobustANGLE(const Context *context,
4908 angle::EntryPoint entryPoint,
4909 ShaderProgramID program,
4910 UniformLocation location,
4911 GLsizei bufSize,
4912 const GLsizei *length,
4913 const GLint *params)
4914 {
4915 UNIMPLEMENTED();
4916 return false;
4917 }
4918
ValidateGetnUniformuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)4919 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
4920 angle::EntryPoint entryPoint,
4921 ShaderProgramID program,
4922 UniformLocation location,
4923 GLsizei bufSize,
4924 const GLsizei *length,
4925 const GLuint *params)
4926 {
4927 UNIMPLEMENTED();
4928 return false;
4929 }
4930
ValidateGetUniformfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLfloat * params)4931 bool ValidateGetUniformfvRobustANGLE(const Context *context,
4932 angle::EntryPoint entryPoint,
4933 ShaderProgramID program,
4934 UniformLocation location,
4935 GLsizei bufSize,
4936 const GLsizei *length,
4937 const GLfloat *params)
4938 {
4939 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4940 {
4941 return false;
4942 }
4943
4944 GLsizei writeLength = 0;
4945
4946 // bufSize is validated in ValidateSizedGetUniform
4947 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
4948 {
4949 return false;
4950 }
4951
4952 SetRobustLengthParam(length, writeLength);
4953
4954 return true;
4955 }
4956
ValidateGetUniformivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLint * params)4957 bool ValidateGetUniformivRobustANGLE(const Context *context,
4958 angle::EntryPoint entryPoint,
4959 ShaderProgramID program,
4960 UniformLocation location,
4961 GLsizei bufSize,
4962 const GLsizei *length,
4963 const GLint *params)
4964 {
4965 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4966 {
4967 return false;
4968 }
4969
4970 GLsizei writeLength = 0;
4971
4972 // bufSize is validated in ValidateSizedGetUniform
4973 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
4974 {
4975 return false;
4976 }
4977
4978 SetRobustLengthParam(length, writeLength);
4979
4980 return true;
4981 }
4982
ValidateGetUniformuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformLocation location,GLsizei bufSize,const GLsizei * length,const GLuint * params)4983 bool ValidateGetUniformuivRobustANGLE(const Context *context,
4984 angle::EntryPoint entryPoint,
4985 ShaderProgramID program,
4986 UniformLocation location,
4987 GLsizei bufSize,
4988 const GLsizei *length,
4989 const GLuint *params)
4990 {
4991 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
4992 {
4993 return false;
4994 }
4995
4996 if (context->getClientMajorVersion() < 3)
4997 {
4998 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
4999 return false;
5000 }
5001
5002 GLsizei writeLength = 0;
5003
5004 // bufSize is validated in ValidateSizedGetUniform
5005 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
5006 {
5007 return false;
5008 }
5009
5010 SetRobustLengthParam(length, writeLength);
5011
5012 return true;
5013 }
5014
ValidateDiscardFramebufferBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLsizei numAttachments,const GLenum * attachments,bool defaultFramebuffer)5015 bool ValidateDiscardFramebufferBase(const Context *context,
5016 angle::EntryPoint entryPoint,
5017 GLenum target,
5018 GLsizei numAttachments,
5019 const GLenum *attachments,
5020 bool defaultFramebuffer)
5021 {
5022 if (numAttachments < 0)
5023 {
5024 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeAttachments);
5025 return false;
5026 }
5027
5028 for (GLsizei i = 0; i < numAttachments; ++i)
5029 {
5030 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
5031 {
5032 if (defaultFramebuffer)
5033 {
5034 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
5035 return false;
5036 }
5037
5038 if (attachments[i] >=
5039 GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
5040 {
5041 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
5042 return false;
5043 }
5044 }
5045 else
5046 {
5047 switch (attachments[i])
5048 {
5049 case GL_DEPTH_ATTACHMENT:
5050 case GL_STENCIL_ATTACHMENT:
5051 case GL_DEPTH_STENCIL_ATTACHMENT:
5052 if (defaultFramebuffer)
5053 {
5054 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
5055 kDefaultFramebufferInvalidAttachment);
5056 return false;
5057 }
5058 break;
5059 case GL_COLOR:
5060 case GL_DEPTH:
5061 case GL_STENCIL:
5062 if (!defaultFramebuffer)
5063 {
5064 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
5065 kDefaultFramebufferAttachmentOnUserFBO);
5066 return false;
5067 }
5068 break;
5069 default:
5070 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5071 return false;
5072 }
5073 }
5074 }
5075
5076 return true;
5077 }
5078
ValidateInsertEventMarkerEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei length,const char * marker)5079 bool ValidateInsertEventMarkerEXT(const Context *context,
5080 angle::EntryPoint entryPoint,
5081 GLsizei length,
5082 const char *marker)
5083 {
5084 if (!context->getExtensions().debugMarkerEXT)
5085 {
5086 // The debug marker calls should not set error state
5087 // However, it seems reasonable to set an error state if the extension is not enabled
5088 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5089 return false;
5090 }
5091
5092 // Note that debug marker calls must not set error state
5093 if (length < 0)
5094 {
5095 return false;
5096 }
5097
5098 if (marker == nullptr)
5099 {
5100 return false;
5101 }
5102
5103 return true;
5104 }
5105
ValidatePushGroupMarkerEXT(const Context * context,angle::EntryPoint entryPoint,GLsizei length,const char * marker)5106 bool ValidatePushGroupMarkerEXT(const Context *context,
5107 angle::EntryPoint entryPoint,
5108 GLsizei length,
5109 const char *marker)
5110 {
5111 if (!context->getExtensions().debugMarkerEXT)
5112 {
5113 // The debug marker calls should not set error state
5114 // However, it seems reasonable to set an error state if the extension is not enabled
5115 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5116 return false;
5117 }
5118
5119 // Note that debug marker calls must not set error state
5120 if (length < 0)
5121 {
5122 return false;
5123 }
5124
5125 if (length > 0 && marker == nullptr)
5126 {
5127 return false;
5128 }
5129
5130 return true;
5131 }
5132
ValidateEGLImageObject(const Context * context,angle::EntryPoint entryPoint,TextureType type,egl::ImageID imageID)5133 bool ValidateEGLImageObject(const Context *context,
5134 angle::EntryPoint entryPoint,
5135 TextureType type,
5136 egl::ImageID imageID)
5137 {
5138 ASSERT(context->getDisplay());
5139 if (!context->getDisplay()->isValidImage(imageID))
5140 {
5141 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
5142 return false;
5143 }
5144
5145 egl::Image *imageObject = context->getDisplay()->getImage(imageID);
5146 if (imageObject->getSamples() > 0)
5147 {
5148 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
5149 return false;
5150 }
5151
5152 if (!imageObject->isTexturable(context))
5153 {
5154 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
5155 return false;
5156 }
5157
5158 // Validate source egl image and target texture are compatible
5159 size_t depth = static_cast<size_t>(imageObject->getExtents().depth);
5160 if (imageObject->isYUV() && type != TextureType::External)
5161 {
5162 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5163 "Image is YUV, target must be TEXTURE_EXTERNAL_OES");
5164 return false;
5165 }
5166
5167 if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap &&
5168 type != TextureType::CubeMapArray && type != TextureType::_3D)
5169 {
5170 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5171 return false;
5172 }
5173
5174 if (imageObject->isCubeMap() && type != TextureType::CubeMapArray &&
5175 (type != TextureType::CubeMap || depth > gl::kCubeFaceCount))
5176 {
5177 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5178 return false;
5179 }
5180
5181 if (imageObject->getLevelCount() > 1 && type == TextureType::External)
5182 {
5183 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5184 return false;
5185 }
5186
5187 // 3d EGLImages are currently not supported
5188 if (type == TextureType::_3D)
5189 {
5190 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
5191 return false;
5192 }
5193
5194 if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent())
5195 {
5196 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5197 "Mismatch between Image and Context Protected Content state");
5198 return false;
5199 }
5200
5201 return true;
5202 }
5203
ValidateEGLImageTargetTexture2DOES(const Context * context,angle::EntryPoint entryPoint,TextureType type,egl::ImageID image)5204 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
5205 angle::EntryPoint entryPoint,
5206 TextureType type,
5207 egl::ImageID image)
5208 {
5209 if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES)
5210 {
5211 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5212 return false;
5213 }
5214
5215 switch (type)
5216 {
5217 case TextureType::_2D:
5218 if (!context->getExtensions().EGLImageOES)
5219 {
5220 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5221 }
5222 break;
5223
5224 case TextureType::_2DArray:
5225 if (!context->getExtensions().EGLImageArrayEXT)
5226 {
5227 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5228 }
5229 break;
5230
5231 case TextureType::External:
5232 if (!context->getExtensions().EGLImageExternalOES)
5233 {
5234 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
5235 }
5236 break;
5237
5238 default:
5239 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
5240 return false;
5241 }
5242
5243 return ValidateEGLImageObject(context, entryPoint, type, image);
5244 }
5245
ValidateEGLImageTargetRenderbufferStorageOES(const Context * context,angle::EntryPoint entryPoint,GLenum target,egl::ImageID image)5246 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
5247 angle::EntryPoint entryPoint,
5248 GLenum target,
5249 egl::ImageID image)
5250 {
5251 if (!context->getExtensions().EGLImageOES)
5252 {
5253 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5254 return false;
5255 }
5256
5257 switch (target)
5258 {
5259 case GL_RENDERBUFFER:
5260 break;
5261
5262 default:
5263 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
5264 return false;
5265 }
5266
5267 ASSERT(context->getDisplay());
5268 if (!context->getDisplay()->isValidImage(image))
5269 {
5270 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
5271 return false;
5272 }
5273
5274 egl::Image *imageObject = context->getDisplay()->getImage(image);
5275 if (!imageObject->isRenderable(context))
5276 {
5277 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
5278 return false;
5279 }
5280
5281 if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
5282 {
5283 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5284 "Mismatch between Image and Context Protected Content state");
5285 return false;
5286 }
5287
5288 return true;
5289 }
5290
ValidateProgramBinaryBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum binaryFormat,const void * binary,GLint length)5291 bool ValidateProgramBinaryBase(const Context *context,
5292 angle::EntryPoint entryPoint,
5293 ShaderProgramID program,
5294 GLenum binaryFormat,
5295 const void *binary,
5296 GLint length)
5297 {
5298 Program *programObject = GetValidProgram(context, entryPoint, program);
5299 if (programObject == nullptr)
5300 {
5301 return false;
5302 }
5303
5304 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
5305 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
5306 programBinaryFormats.end())
5307 {
5308 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
5309 return false;
5310 }
5311
5312 if (context->hasActiveTransformFeedback(program))
5313 {
5314 // ES 3.0.4 section 2.15 page 91
5315 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
5316 return false;
5317 }
5318
5319 return true;
5320 }
5321
ValidateGetProgramBinaryBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLsizei bufSize,const GLsizei * length,const GLenum * binaryFormat,const void * binary)5322 bool ValidateGetProgramBinaryBase(const Context *context,
5323 angle::EntryPoint entryPoint,
5324 ShaderProgramID program,
5325 GLsizei bufSize,
5326 const GLsizei *length,
5327 const GLenum *binaryFormat,
5328 const void *binary)
5329 {
5330 Program *programObject = GetValidProgram(context, entryPoint, program);
5331 if (programObject == nullptr)
5332 {
5333 return false;
5334 }
5335
5336 if (!programObject->isLinked())
5337 {
5338 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
5339 return false;
5340 }
5341
5342 if (context->getCaps().programBinaryFormats.empty())
5343 {
5344 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
5345 return false;
5346 }
5347
5348 return true;
5349 }
5350
ValidateDrawBuffersBase(const Context * context,angle::EntryPoint entryPoint,GLsizei n,const GLenum * bufs)5351 bool ValidateDrawBuffersBase(const Context *context,
5352 angle::EntryPoint entryPoint,
5353 GLsizei n,
5354 const GLenum *bufs)
5355 {
5356 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
5357 if (n < 0)
5358 {
5359 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
5360 return false;
5361 }
5362 if (n > context->getCaps().maxDrawBuffers)
5363 {
5364 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
5365 return false;
5366 }
5367
5368 ASSERT(context->getState().getDrawFramebuffer());
5369 FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
5370 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
5371
5372 // This should come first before the check for the default frame buffer
5373 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
5374 // rather than INVALID_OPERATION
5375 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
5376 {
5377 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
5378
5379 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
5380 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
5381 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
5382 {
5383 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
5384 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
5385 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
5386 // 3.1 is still a bit ambiguous about the error, but future specs are
5387 // expected to clarify that GL_INVALID_ENUM is the correct error.
5388 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawBuffer);
5389 return false;
5390 }
5391 else if (bufs[colorAttachment] >= maxColorAttachment)
5392 {
5393 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
5394 return false;
5395 }
5396 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
5397 frameBufferId.value != 0)
5398 {
5399 // INVALID_OPERATION-GL is bound to buffer and ith argument
5400 // is not COLOR_ATTACHMENTi or NONE
5401 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
5402 return false;
5403 }
5404 }
5405
5406 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
5407 // and n is not 1 or bufs is bound to value other than BACK and NONE
5408 if (frameBufferId.value == 0)
5409 {
5410 if (n != 1)
5411 {
5412 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
5413 return false;
5414 }
5415
5416 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
5417 {
5418 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
5419 return false;
5420 }
5421 }
5422
5423 return true;
5424 }
5425
ValidateGetBufferPointervBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei * length,void * const * params)5426 bool ValidateGetBufferPointervBase(const Context *context,
5427 angle::EntryPoint entryPoint,
5428 BufferBinding target,
5429 GLenum pname,
5430 GLsizei *length,
5431 void *const *params)
5432 {
5433 if (length)
5434 {
5435 *length = 0;
5436 }
5437
5438 if (!context->isValidBufferBinding(target))
5439 {
5440 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5441 return false;
5442 }
5443
5444 switch (pname)
5445 {
5446 case GL_BUFFER_MAP_POINTER:
5447 break;
5448
5449 default:
5450 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5451 return false;
5452 }
5453
5454 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
5455 // target bound to zero generate an INVALID_OPERATION error."
5456 // GLES 3.1 section 6.6 explicitly specifies this error.
5457 if (context->getState().getTargetBuffer(target) == nullptr)
5458 {
5459 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
5460 return false;
5461 }
5462
5463 if (length)
5464 {
5465 *length = 1;
5466 }
5467
5468 return true;
5469 }
5470
ValidateUnmapBufferBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target)5471 bool ValidateUnmapBufferBase(const Context *context,
5472 angle::EntryPoint entryPoint,
5473 BufferBinding target)
5474 {
5475 if (!context->isValidBufferBinding(target))
5476 {
5477 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5478 return false;
5479 }
5480
5481 Buffer *buffer = context->getState().getTargetBuffer(target);
5482
5483 if (buffer == nullptr || !buffer->isMapped())
5484 {
5485 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMapped);
5486 return false;
5487 }
5488
5489 return true;
5490 }
5491
ValidateMapBufferRangeBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length,GLbitfield access)5492 bool ValidateMapBufferRangeBase(const Context *context,
5493 angle::EntryPoint entryPoint,
5494 BufferBinding target,
5495 GLintptr offset,
5496 GLsizeiptr length,
5497 GLbitfield access)
5498 {
5499 if (!context->isValidBufferBinding(target))
5500 {
5501 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5502 return false;
5503 }
5504
5505 if (offset < 0)
5506 {
5507 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
5508 return false;
5509 }
5510
5511 if (length < 0)
5512 {
5513 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength);
5514 return false;
5515 }
5516
5517 Buffer *buffer = context->getState().getTargetBuffer(target);
5518
5519 if (!buffer)
5520 {
5521 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMappable);
5522 return false;
5523 }
5524
5525 // Check for buffer overflow
5526 CheckedNumeric<size_t> checkedOffset(offset);
5527 auto checkedSize = checkedOffset + length;
5528
5529 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
5530 {
5531 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMapOutOfRange);
5532 return false;
5533 }
5534
5535 // Check for invalid bits in the mask
5536 constexpr GLbitfield kAllAccessBits =
5537 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
5538 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5539
5540 if (buffer->isImmutable())
5541 {
5542 // GL_EXT_buffer_storage's additions to glMapBufferRange
5543 constexpr GLbitfield kBufferStorageAccessBits =
5544 kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT;
5545
5546 if ((access & ~kBufferStorageAccessBits) != 0)
5547 {
5548 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
5549 return false;
5550 }
5551
5552 // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access,
5553 // but the same bits are not included in the buffer's storage flags
5554 constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
5555 GL_MAP_PERSISTENT_BIT_EXT |
5556 GL_MAP_COHERENT_BIT_EXT;
5557 GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits;
5558 if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags)
5559 {
5560 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBits);
5561 return false;
5562 }
5563 }
5564 else if ((access & ~kAllAccessBits) != 0)
5565 {
5566 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
5567 return false;
5568 }
5569
5570 if (length == 0)
5571 {
5572 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kLengthZero);
5573 return false;
5574 }
5575
5576 if (buffer->isMapped())
5577 {
5578 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferAlreadyMapped);
5579 return false;
5580 }
5581
5582 // Check for invalid bit combinations
5583 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
5584 {
5585 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
5586 return false;
5587 }
5588
5589 GLbitfield writeOnlyBits =
5590 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5591
5592 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
5593 {
5594 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
5595 return false;
5596 }
5597
5598 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
5599 {
5600 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
5601 return false;
5602 }
5603
5604 return ValidateMapBufferBase(context, entryPoint, target);
5605 }
5606
ValidateFlushMappedBufferRangeBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLintptr offset,GLsizeiptr length)5607 bool ValidateFlushMappedBufferRangeBase(const Context *context,
5608 angle::EntryPoint entryPoint,
5609 BufferBinding target,
5610 GLintptr offset,
5611 GLsizeiptr length)
5612 {
5613 if (offset < 0)
5614 {
5615 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
5616 return false;
5617 }
5618
5619 if (length < 0)
5620 {
5621 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength);
5622 return false;
5623 }
5624
5625 if (!context->isValidBufferBinding(target))
5626 {
5627 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
5628 return false;
5629 }
5630
5631 Buffer *buffer = context->getState().getTargetBuffer(target);
5632
5633 if (buffer == nullptr)
5634 {
5635 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFlushZero);
5636 return false;
5637 }
5638
5639 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
5640 {
5641 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFlushTarget);
5642 return false;
5643 }
5644
5645 // Check for buffer overflow
5646 CheckedNumeric<size_t> checkedOffset(offset);
5647 auto checkedSize = checkedOffset + length;
5648
5649 if (!checkedSize.IsValid() ||
5650 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
5651 {
5652 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
5653 return false;
5654 }
5655
5656 return true;
5657 }
5658
ValidateGenOrDelete(const Context * context,angle::EntryPoint entryPoint,GLint n)5659 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n)
5660 {
5661 if (n < 0)
5662 {
5663 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
5664 return false;
5665 }
5666 return true;
5667 }
5668
ValidateRobustEntryPoint(const Context * context,angle::EntryPoint entryPoint,GLsizei bufSize)5669 bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize)
5670 {
5671 if (!context->getExtensions().robustClientMemoryANGLE)
5672 {
5673 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
5674 return false;
5675 }
5676
5677 if (bufSize < 0)
5678 {
5679 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufferSize);
5680 return false;
5681 }
5682
5683 return true;
5684 }
5685
ValidateRobustBufferSize(const Context * context,angle::EntryPoint entryPoint,GLsizei bufSize,GLsizei numParams)5686 bool ValidateRobustBufferSize(const Context *context,
5687 angle::EntryPoint entryPoint,
5688 GLsizei bufSize,
5689 GLsizei numParams)
5690 {
5691 if (bufSize < numParams)
5692 {
5693 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientParams);
5694 return false;
5695 }
5696
5697 return true;
5698 }
5699
ValidateGetFramebufferAttachmentParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum pname,GLsizei * numParams)5700 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
5701 angle::EntryPoint entryPoint,
5702 GLenum target,
5703 GLenum attachment,
5704 GLenum pname,
5705 GLsizei *numParams)
5706 {
5707 if (!ValidFramebufferTarget(context, target))
5708 {
5709 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
5710 return false;
5711 }
5712
5713 int clientVersion = context->getClientMajorVersion();
5714
5715 switch (pname)
5716 {
5717 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5718 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5719 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5720 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5721 break;
5722
5723 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
5724 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
5725 if (clientVersion < 3 ||
5726 !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
5727 {
5728 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5729 return false;
5730 }
5731 break;
5732
5733 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
5734 if (!context->getExtensions().multisampledRenderToTextureEXT)
5735 {
5736 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5737 return false;
5738 }
5739 break;
5740
5741 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
5742 if (clientVersion < 3 && !context->getExtensions().sRGBEXT)
5743 {
5744 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5745 return false;
5746 }
5747 break;
5748
5749 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5750 if (clientVersion < 3 && !context->getExtensions().colorBufferHalfFloatEXT &&
5751 !context->getExtensions().colorBufferFloatRgbCHROMIUM &&
5752 !context->getExtensions().colorBufferFloatRgbaCHROMIUM)
5753 {
5754 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
5755 return false;
5756 }
5757 break;
5758
5759 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
5760 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
5761 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
5762 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
5763 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
5764 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
5765 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5766 if (clientVersion < 3)
5767 {
5768 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
5769 return false;
5770 }
5771 break;
5772
5773 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
5774 if (!context->getExtensions().geometryShaderAny() &&
5775 context->getClientVersion() < ES_3_2)
5776 {
5777 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
5778 return false;
5779 }
5780 break;
5781
5782 default:
5783 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
5784 return false;
5785 }
5786
5787 // Determine if the attachment is a valid enum
5788 switch (attachment)
5789 {
5790 case GL_BACK:
5791 case GL_DEPTH:
5792 case GL_STENCIL:
5793 if (clientVersion < 3)
5794 {
5795 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5796 return false;
5797 }
5798 break;
5799
5800 case GL_DEPTH_STENCIL_ATTACHMENT:
5801 if (clientVersion < 3 && !context->isWebGL1())
5802 {
5803 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5804 return false;
5805 }
5806 break;
5807
5808 case GL_COLOR_ATTACHMENT0:
5809 case GL_DEPTH_ATTACHMENT:
5810 case GL_STENCIL_ATTACHMENT:
5811 break;
5812
5813 default:
5814 if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) ||
5815 attachment < GL_COLOR_ATTACHMENT0_EXT ||
5816 (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
5817 static_cast<GLuint>(context->getCaps().maxColorAttachments))
5818 {
5819 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
5820 return false;
5821 }
5822 break;
5823 }
5824
5825 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
5826 ASSERT(framebuffer);
5827
5828 if (framebuffer->isDefault())
5829 {
5830 if (clientVersion < 3)
5831 {
5832 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
5833 return false;
5834 }
5835
5836 switch (attachment)
5837 {
5838 case GL_BACK:
5839 case GL_DEPTH:
5840 case GL_STENCIL:
5841 break;
5842
5843 default:
5844 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5845 return false;
5846 }
5847 }
5848 else
5849 {
5850 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5851 {
5852 // Valid attachment query
5853 }
5854 else
5855 {
5856 switch (attachment)
5857 {
5858 case GL_DEPTH_ATTACHMENT:
5859 case GL_STENCIL_ATTACHMENT:
5860 break;
5861
5862 case GL_DEPTH_STENCIL_ATTACHMENT:
5863 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
5864 {
5865 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5866 return false;
5867 }
5868 break;
5869
5870 default:
5871 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5872 return false;
5873 }
5874 }
5875 }
5876
5877 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
5878 if (attachmentObject)
5879 {
5880 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5881 attachmentObject->type() == GL_TEXTURE ||
5882 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5883
5884 switch (pname)
5885 {
5886 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5887 if (attachmentObject->type() != GL_RENDERBUFFER &&
5888 attachmentObject->type() != GL_TEXTURE)
5889 {
5890 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5891 return false;
5892 }
5893 break;
5894
5895 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5896 if (attachmentObject->type() != GL_TEXTURE)
5897 {
5898 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5899 return false;
5900 }
5901 break;
5902
5903 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5904 if (attachmentObject->type() != GL_TEXTURE)
5905 {
5906 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5907 return false;
5908 }
5909 break;
5910
5911 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5912 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5913 {
5914 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
5915 return false;
5916 }
5917 break;
5918
5919 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5920 if (attachmentObject->type() != GL_TEXTURE)
5921 {
5922 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
5923 return false;
5924 }
5925 break;
5926
5927 default:
5928 break;
5929 }
5930 }
5931 else
5932 {
5933 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5934 // is NONE, then querying any other pname will generate INVALID_ENUM.
5935
5936 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5937 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5938 // INVALID_OPERATION for all other pnames
5939
5940 switch (pname)
5941 {
5942 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5943 break;
5944
5945 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5946 if (clientVersion < 3)
5947 {
5948 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
5949 return false;
5950 }
5951 break;
5952
5953 default:
5954 if (clientVersion < 3)
5955 {
5956 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
5957 return false;
5958 }
5959 else
5960 {
5961 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
5962 kInvalidFramebufferAttachmentParameter);
5963 return false;
5964 }
5965 }
5966 }
5967
5968 if (numParams)
5969 {
5970 *numParams = 1;
5971 }
5972
5973 return true;
5974 }
5975
ValidateGetFramebufferParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,const GLint * params)5976 bool ValidateGetFramebufferParameterivBase(const Context *context,
5977 angle::EntryPoint entryPoint,
5978 GLenum target,
5979 GLenum pname,
5980 const GLint *params)
5981 {
5982 if (!ValidFramebufferTarget(context, target))
5983 {
5984 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
5985 return false;
5986 }
5987
5988 switch (pname)
5989 {
5990 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
5991 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
5992 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
5993 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
5994 break;
5995 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
5996 if (!context->getExtensions().geometryShaderAny() &&
5997 context->getClientVersion() < ES_3_2)
5998 {
5999 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
6000 return false;
6001 }
6002 break;
6003 case GL_FRAMEBUFFER_FLIP_Y_MESA:
6004 if (!context->getExtensions().framebufferFlipYMESA)
6005 {
6006 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
6007 return false;
6008 }
6009 break;
6010 default:
6011 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
6012 return false;
6013 }
6014
6015 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
6016 ASSERT(framebuffer);
6017
6018 if (framebuffer->isDefault())
6019 {
6020 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
6021 return false;
6022 }
6023 return true;
6024 }
6025
ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum attachment,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6026 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
6027 angle::EntryPoint entryPoint,
6028 GLenum target,
6029 GLenum attachment,
6030 GLenum pname,
6031 GLsizei bufSize,
6032 const GLsizei *length,
6033 const GLint *params)
6034 {
6035 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6036 {
6037 return false;
6038 }
6039
6040 GLsizei numParams = 0;
6041 if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
6042 pname, &numParams))
6043 {
6044 return false;
6045 }
6046
6047 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6048 {
6049 return false;
6050 }
6051
6052 SetRobustLengthParam(length, numParams);
6053
6054 return true;
6055 }
6056
ValidateGetBufferParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6057 bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
6058 angle::EntryPoint entryPoint,
6059 BufferBinding target,
6060 GLenum pname,
6061 GLsizei bufSize,
6062 const GLsizei *length,
6063 const GLint *params)
6064 {
6065 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6066 {
6067 return false;
6068 }
6069
6070 GLsizei numParams = 0;
6071
6072 if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
6073 {
6074 return false;
6075 }
6076
6077 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6078 {
6079 return false;
6080 }
6081
6082 SetRobustLengthParam(length, numParams);
6083 return true;
6084 }
6085
ValidateGetBufferParameteri64vRobustANGLE(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint64 * params)6086 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
6087 angle::EntryPoint entryPoint,
6088 BufferBinding target,
6089 GLenum pname,
6090 GLsizei bufSize,
6091 const GLsizei *length,
6092 const GLint64 *params)
6093 {
6094 GLsizei numParams = 0;
6095
6096 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6097 {
6098 return false;
6099 }
6100
6101 if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
6102 {
6103 return false;
6104 }
6105
6106 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6107 {
6108 return false;
6109 }
6110
6111 SetRobustLengthParam(length, numParams);
6112
6113 return true;
6114 }
6115
ValidateGetProgramivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLsizei * numParams)6116 bool ValidateGetProgramivBase(const Context *context,
6117 angle::EntryPoint entryPoint,
6118 ShaderProgramID program,
6119 GLenum pname,
6120 GLsizei *numParams)
6121 {
6122 // Currently, all GetProgramiv queries return 1 parameter
6123 if (numParams)
6124 {
6125 *numParams = 1;
6126 }
6127
6128 if (context->isContextLost())
6129 {
6130 ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
6131
6132 if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
6133 {
6134 // Generate an error but still return true, the context still needs to return a
6135 // value in this case.
6136 return true;
6137 }
6138 else
6139 {
6140 return false;
6141 }
6142 }
6143
6144 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
6145 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
6146 ? GetValidProgramNoResolve(context, entryPoint, program)
6147 : GetValidProgram(context, entryPoint, program);
6148 if (!programObject)
6149 {
6150 return false;
6151 }
6152
6153 switch (pname)
6154 {
6155 case GL_DELETE_STATUS:
6156 case GL_LINK_STATUS:
6157 case GL_VALIDATE_STATUS:
6158 case GL_INFO_LOG_LENGTH:
6159 case GL_ATTACHED_SHADERS:
6160 case GL_ACTIVE_ATTRIBUTES:
6161 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
6162 case GL_ACTIVE_UNIFORMS:
6163 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
6164 break;
6165
6166 case GL_PROGRAM_BINARY_READY_ANGLE:
6167 if (!context->getExtensions().programBinaryReadinessQueryANGLE)
6168 {
6169 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6170 return false;
6171 }
6172 break;
6173
6174 case GL_PROGRAM_BINARY_LENGTH:
6175 if (context->getClientMajorVersion() < 3 &&
6176 !context->getExtensions().getProgramBinaryOES)
6177 {
6178 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6179 return false;
6180 }
6181 break;
6182
6183 case GL_ACTIVE_UNIFORM_BLOCKS:
6184 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
6185 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
6186 case GL_TRANSFORM_FEEDBACK_VARYINGS:
6187 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
6188 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
6189 if (context->getClientMajorVersion() < 3)
6190 {
6191 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
6192 return false;
6193 }
6194 break;
6195
6196 case GL_PROGRAM_SEPARABLE:
6197 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
6198 if (context->getClientVersion() < Version(3, 1))
6199 {
6200 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
6201 return false;
6202 }
6203 break;
6204
6205 case GL_COMPUTE_WORK_GROUP_SIZE:
6206 if (context->getClientVersion() < Version(3, 1))
6207 {
6208 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
6209 return false;
6210 }
6211
6212 // [OpenGL ES 3.1] Chapter 7.12 Page 122
6213 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
6214 // program which has not been linked successfully, or which does not contain objects to
6215 // form a compute shader.
6216 if (!programObject->isLinked())
6217 {
6218 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6219 return false;
6220 }
6221 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
6222 {
6223 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
6224 return false;
6225 }
6226 break;
6227
6228 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
6229 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
6230 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
6231 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
6232 if (!context->getExtensions().geometryShaderAny() &&
6233 context->getClientVersion() < ES_3_2)
6234 {
6235 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
6236 return false;
6237 }
6238
6239 // [EXT_geometry_shader] Chapter 7.12
6240 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
6241 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
6242 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
6243 // successfully, or which does not contain objects to form a geometry shader.
6244 if (!programObject->isLinked())
6245 {
6246 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6247 return false;
6248 }
6249 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
6250 {
6251 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
6252 return false;
6253 }
6254 break;
6255
6256 case GL_COMPLETION_STATUS_KHR:
6257 if (!context->getExtensions().parallelShaderCompileKHR)
6258 {
6259 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
6260 return false;
6261 }
6262 break;
6263 case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
6264 case GL_TESS_GEN_MODE_EXT:
6265 case GL_TESS_GEN_SPACING_EXT:
6266 case GL_TESS_GEN_VERTEX_ORDER_EXT:
6267 case GL_TESS_GEN_POINT_MODE_EXT:
6268 if (!context->getExtensions().tessellationShaderAny() &&
6269 context->getClientVersion() < ES_3_2)
6270 {
6271 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled);
6272 return false;
6273 }
6274 if (!programObject->isLinked())
6275 {
6276 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
6277 return false;
6278 }
6279 break;
6280 default:
6281 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6282 return false;
6283 }
6284
6285 return true;
6286 }
6287
ValidateGetProgramivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6288 bool ValidateGetProgramivRobustANGLE(const Context *context,
6289 angle::EntryPoint entryPoint,
6290 ShaderProgramID program,
6291 GLenum pname,
6292 GLsizei bufSize,
6293 const GLsizei *length,
6294 const GLint *params)
6295 {
6296 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6297 {
6298 return false;
6299 }
6300
6301 GLsizei numParams = 0;
6302
6303 if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams))
6304 {
6305 return false;
6306 }
6307
6308 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6309 {
6310 return false;
6311 }
6312
6313 SetRobustLengthParam(length, numParams);
6314
6315 return true;
6316 }
6317
ValidateGetRenderbufferParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6318 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
6319 angle::EntryPoint entryPoint,
6320 GLenum target,
6321 GLenum pname,
6322 GLsizei bufSize,
6323 const GLsizei *length,
6324 const GLint *params)
6325 {
6326 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6327 {
6328 return false;
6329 }
6330
6331 GLsizei numParams = 0;
6332
6333 if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams))
6334 {
6335 return false;
6336 }
6337
6338 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6339 {
6340 return false;
6341 }
6342
6343 SetRobustLengthParam(length, numParams);
6344
6345 return true;
6346 }
6347
ValidateGetShaderivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID shader,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6348 bool ValidateGetShaderivRobustANGLE(const Context *context,
6349 angle::EntryPoint entryPoint,
6350 ShaderProgramID shader,
6351 GLenum pname,
6352 GLsizei bufSize,
6353 const GLsizei *length,
6354 const GLint *params)
6355 {
6356 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6357 {
6358 return false;
6359 }
6360
6361 GLsizei numParams = 0;
6362
6363 if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams))
6364 {
6365 return false;
6366 }
6367
6368 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6369 {
6370 return false;
6371 }
6372
6373 SetRobustLengthParam(length, numParams);
6374
6375 return true;
6376 }
6377
ValidateGetTexParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6378 bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
6379 angle::EntryPoint entryPoint,
6380 TextureType target,
6381 GLenum pname,
6382 GLsizei bufSize,
6383 const GLsizei *length,
6384 const GLfloat *params)
6385 {
6386 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6387 {
6388 return false;
6389 }
6390
6391 GLsizei numParams = 0;
6392
6393 if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
6394 {
6395 return false;
6396 }
6397
6398 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6399 {
6400 return false;
6401 }
6402
6403 SetRobustLengthParam(length, numParams);
6404
6405 return true;
6406 }
6407
ValidateGetTexParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6408 bool ValidateGetTexParameterivRobustANGLE(const Context *context,
6409 angle::EntryPoint entryPoint,
6410 TextureType target,
6411 GLenum pname,
6412 GLsizei bufSize,
6413 const GLsizei *length,
6414 const GLint *params)
6415 {
6416
6417 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6418 {
6419 return false;
6420 }
6421 GLsizei numParams = 0;
6422 if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
6423 {
6424 return false;
6425 }
6426
6427 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6428 {
6429 return false;
6430 }
6431
6432 SetRobustLengthParam(length, numParams);
6433 return true;
6434 }
6435
ValidateGetTexParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6436 bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
6437 angle::EntryPoint entryPoint,
6438 TextureType target,
6439 GLenum pname,
6440 GLsizei bufSize,
6441 const GLsizei *length,
6442 const GLint *params)
6443 {
6444 UNIMPLEMENTED();
6445 return false;
6446 }
6447
ValidateGetTexParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6448 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
6449 angle::EntryPoint entryPoint,
6450 TextureType target,
6451 GLenum pname,
6452 GLsizei bufSize,
6453 const GLsizei *length,
6454 const GLuint *params)
6455 {
6456 UNIMPLEMENTED();
6457 return false;
6458 }
6459
ValidateTexParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLfloat * params)6460 bool ValidateTexParameterfvRobustANGLE(const Context *context,
6461 angle::EntryPoint entryPoint,
6462 TextureType target,
6463 GLenum pname,
6464 GLsizei bufSize,
6465 const GLfloat *params)
6466 {
6467 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6468 {
6469 return false;
6470 }
6471
6472 return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
6473 }
6474
ValidateTexParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)6475 bool ValidateTexParameterivRobustANGLE(const Context *context,
6476 angle::EntryPoint entryPoint,
6477 TextureType target,
6478 GLenum pname,
6479 GLsizei bufSize,
6480 const GLint *params)
6481 {
6482 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6483 {
6484 return false;
6485 }
6486
6487 return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
6488 }
6489
ValidateTexParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLint * params)6490 bool ValidateTexParameterIivRobustANGLE(const Context *context,
6491 angle::EntryPoint entryPoint,
6492 TextureType target,
6493 GLenum pname,
6494 GLsizei bufSize,
6495 const GLint *params)
6496 {
6497 UNIMPLEMENTED();
6498 return false;
6499 }
6500
ValidateTexParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,const GLuint * params)6501 bool ValidateTexParameterIuivRobustANGLE(const Context *context,
6502 angle::EntryPoint entryPoint,
6503 TextureType target,
6504 GLenum pname,
6505 GLsizei bufSize,
6506 const GLuint *params)
6507 {
6508 UNIMPLEMENTED();
6509 return false;
6510 }
6511
ValidateGetSamplerParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6512 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
6513 angle::EntryPoint entryPoint,
6514 SamplerID sampler,
6515 GLenum pname,
6516 GLsizei bufSize,
6517 const GLsizei *length,
6518 const GLfloat *params)
6519 {
6520 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6521 {
6522 return false;
6523 }
6524
6525 GLsizei numParams = 0;
6526
6527 if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
6528 {
6529 return false;
6530 }
6531
6532 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6533 {
6534 return false;
6535 }
6536
6537 SetRobustLengthParam(length, numParams);
6538 return true;
6539 }
6540
ValidateGetSamplerParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6541 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
6542 angle::EntryPoint entryPoint,
6543 SamplerID sampler,
6544 GLenum pname,
6545 GLsizei bufSize,
6546 const GLsizei *length,
6547 const GLint *params)
6548 {
6549 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6550 {
6551 return false;
6552 }
6553
6554 GLsizei numParams = 0;
6555
6556 if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
6557 {
6558 return false;
6559 }
6560
6561 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6562 {
6563 return false;
6564 }
6565
6566 SetRobustLengthParam(length, numParams);
6567 return true;
6568 }
6569
ValidateGetSamplerParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6570 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
6571 angle::EntryPoint entryPoint,
6572 SamplerID sampler,
6573 GLenum pname,
6574 GLsizei bufSize,
6575 const GLsizei *length,
6576 const GLint *params)
6577 {
6578 UNIMPLEMENTED();
6579 return false;
6580 }
6581
ValidateGetSamplerParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6582 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
6583 angle::EntryPoint entryPoint,
6584 SamplerID sampler,
6585 GLenum pname,
6586 GLsizei bufSize,
6587 const GLsizei *length,
6588 const GLuint *params)
6589 {
6590 UNIMPLEMENTED();
6591 return false;
6592 }
6593
ValidateSamplerParameterfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLfloat * params)6594 bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
6595 angle::EntryPoint entryPoint,
6596 SamplerID sampler,
6597 GLenum pname,
6598 GLsizei bufSize,
6599 const GLfloat *params)
6600 {
6601 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6602 {
6603 return false;
6604 }
6605
6606 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
6607 }
6608
ValidateSamplerParameterivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * params)6609 bool ValidateSamplerParameterivRobustANGLE(const Context *context,
6610 angle::EntryPoint entryPoint,
6611 SamplerID sampler,
6612 GLenum pname,
6613 GLsizei bufSize,
6614 const GLint *params)
6615 {
6616 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6617 {
6618 return false;
6619 }
6620
6621 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
6622 }
6623
ValidateSamplerParameterIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLint * param)6624 bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
6625 angle::EntryPoint entryPoint,
6626 SamplerID sampler,
6627 GLenum pname,
6628 GLsizei bufSize,
6629 const GLint *param)
6630 {
6631 UNIMPLEMENTED();
6632 return false;
6633 }
6634
ValidateSamplerParameterIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,const GLuint * param)6635 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
6636 angle::EntryPoint entryPoint,
6637 SamplerID sampler,
6638 GLenum pname,
6639 GLsizei bufSize,
6640 const GLuint *param)
6641 {
6642 UNIMPLEMENTED();
6643 return false;
6644 }
6645
ValidateGetVertexAttribfvRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLfloat * params)6646 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
6647 angle::EntryPoint entryPoint,
6648 GLuint index,
6649 GLenum pname,
6650 GLsizei bufSize,
6651 const GLsizei *length,
6652 const GLfloat *params)
6653 {
6654 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6655 {
6656 return false;
6657 }
6658
6659 GLsizei writeLength = 0;
6660
6661 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
6662 {
6663 return false;
6664 }
6665
6666 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6667 {
6668 return false;
6669 }
6670
6671 SetRobustLengthParam(length, writeLength);
6672 return true;
6673 }
6674
ValidateGetVertexAttribivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6675 bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
6676 angle::EntryPoint entryPoint,
6677 GLuint index,
6678 GLenum pname,
6679 GLsizei bufSize,
6680 const GLsizei *length,
6681 const GLint *params)
6682 {
6683 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6684 {
6685 return false;
6686 }
6687
6688 GLsizei writeLength = 0;
6689
6690 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
6691 {
6692 return false;
6693 }
6694
6695 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6696 {
6697 return false;
6698 }
6699
6700 SetRobustLengthParam(length, writeLength);
6701
6702 return true;
6703 }
6704
ValidateGetVertexAttribPointervRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,void * const * pointer)6705 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
6706 angle::EntryPoint entryPoint,
6707 GLuint index,
6708 GLenum pname,
6709 GLsizei bufSize,
6710 const GLsizei *length,
6711 void *const *pointer)
6712 {
6713 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6714 {
6715 return false;
6716 }
6717
6718 GLsizei writeLength = 0;
6719
6720 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false))
6721 {
6722 return false;
6723 }
6724
6725 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6726 {
6727 return false;
6728 }
6729
6730 SetRobustLengthParam(length, writeLength);
6731
6732 return true;
6733 }
6734
ValidateGetVertexAttribIivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6735 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
6736 angle::EntryPoint entryPoint,
6737 GLuint index,
6738 GLenum pname,
6739 GLsizei bufSize,
6740 const GLsizei *length,
6741 const GLint *params)
6742 {
6743 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6744 {
6745 return false;
6746 }
6747
6748 GLsizei writeLength = 0;
6749
6750 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
6751 {
6752 return false;
6753 }
6754
6755 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6756 {
6757 return false;
6758 }
6759
6760 SetRobustLengthParam(length, writeLength);
6761
6762 return true;
6763 }
6764
ValidateGetVertexAttribIuivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLuint * params)6765 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
6766 angle::EntryPoint entryPoint,
6767 GLuint index,
6768 GLenum pname,
6769 GLsizei bufSize,
6770 const GLsizei *length,
6771 const GLuint *params)
6772 {
6773 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6774 {
6775 return false;
6776 }
6777
6778 GLsizei writeLength = 0;
6779
6780 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
6781 {
6782 return false;
6783 }
6784
6785 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6786 {
6787 return false;
6788 }
6789
6790 SetRobustLengthParam(length, writeLength);
6791
6792 return true;
6793 }
6794
ValidateGetActiveUniformBlockivRobustANGLE(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6795 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
6796 angle::EntryPoint entryPoint,
6797 ShaderProgramID program,
6798 UniformBlockIndex uniformBlockIndex,
6799 GLenum pname,
6800 GLsizei bufSize,
6801 const GLsizei *length,
6802 const GLint *params)
6803 {
6804 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6805 {
6806 return false;
6807 }
6808
6809 GLsizei writeLength = 0;
6810
6811 if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname,
6812 &writeLength))
6813 {
6814 return false;
6815 }
6816
6817 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
6818 {
6819 return false;
6820 }
6821
6822 SetRobustLengthParam(length, writeLength);
6823
6824 return true;
6825 }
6826
ValidateGetInternalformativRobustANGLE(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,const GLsizei * length,const GLint * params)6827 bool ValidateGetInternalformativRobustANGLE(const Context *context,
6828 angle::EntryPoint entryPoint,
6829 GLenum target,
6830 GLenum internalformat,
6831 GLenum pname,
6832 GLsizei bufSize,
6833 const GLsizei *length,
6834 const GLint *params)
6835 {
6836 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
6837 {
6838 return false;
6839 }
6840
6841 GLsizei numParams = 0;
6842
6843 if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
6844 bufSize, &numParams))
6845 {
6846 return false;
6847 }
6848
6849 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
6850 {
6851 return false;
6852 }
6853
6854 SetRobustLengthParam(length, numParams);
6855
6856 return true;
6857 }
6858
ValidateRobustCompressedTexImageBase(const Context * context,angle::EntryPoint entryPoint,GLsizei imageSize,GLsizei dataSize)6859 bool ValidateRobustCompressedTexImageBase(const Context *context,
6860 angle::EntryPoint entryPoint,
6861 GLsizei imageSize,
6862 GLsizei dataSize)
6863 {
6864 if (!ValidateRobustEntryPoint(context, entryPoint, dataSize))
6865 {
6866 return false;
6867 }
6868
6869 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
6870 if (pixelUnpackBuffer == nullptr)
6871 {
6872 if (dataSize < imageSize)
6873 {
6874 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
6875 }
6876 }
6877 return true;
6878 }
6879
ValidateGetBufferParameterBase(const Context * context,angle::EntryPoint entryPoint,BufferBinding target,GLenum pname,bool pointerVersion,GLsizei * numParams)6880 bool ValidateGetBufferParameterBase(const Context *context,
6881 angle::EntryPoint entryPoint,
6882 BufferBinding target,
6883 GLenum pname,
6884 bool pointerVersion,
6885 GLsizei *numParams)
6886 {
6887 if (numParams)
6888 {
6889 *numParams = 0;
6890 }
6891
6892 if (!context->isValidBufferBinding(target))
6893 {
6894 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
6895 return false;
6896 }
6897
6898 const Buffer *buffer = context->getState().getTargetBuffer(target);
6899 if (!buffer)
6900 {
6901 // A null buffer means that "0" is bound to the requested buffer target
6902 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
6903 return false;
6904 }
6905
6906 const Extensions &extensions = context->getExtensions();
6907
6908 switch (pname)
6909 {
6910 case GL_BUFFER_USAGE:
6911 case GL_BUFFER_SIZE:
6912 break;
6913
6914 case GL_BUFFER_ACCESS_OES:
6915 if (!extensions.mapbufferOES)
6916 {
6917 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6918 return false;
6919 }
6920 break;
6921
6922 case GL_BUFFER_MAPPED:
6923 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
6924 if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES &&
6925 !extensions.mapBufferRangeEXT)
6926 {
6927 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6928 return false;
6929 }
6930 break;
6931
6932 case GL_BUFFER_MAP_POINTER:
6933 if (!pointerVersion)
6934 {
6935 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMapPointerQuery);
6936 return false;
6937 }
6938 break;
6939
6940 case GL_BUFFER_ACCESS_FLAGS:
6941 case GL_BUFFER_MAP_OFFSET:
6942 case GL_BUFFER_MAP_LENGTH:
6943 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT)
6944 {
6945 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6946 return false;
6947 }
6948 break;
6949
6950 case GL_MEMORY_SIZE_ANGLE:
6951 if (!context->getExtensions().memorySizeANGLE)
6952 {
6953 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
6954 return false;
6955 }
6956 break;
6957
6958 case GL_RESOURCE_INITIALIZED_ANGLE:
6959 if (!context->getExtensions().robustResourceInitializationANGLE)
6960 {
6961 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
6962 kRobustResourceInitializationExtensionRequired);
6963 return false;
6964 }
6965 break;
6966
6967 default:
6968 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
6969 return false;
6970 }
6971
6972 // All buffer parameter queries return one value.
6973 if (numParams)
6974 {
6975 *numParams = 1;
6976 }
6977
6978 return true;
6979 }
6980
ValidateGetRenderbufferParameterivBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum pname,GLsizei * length)6981 bool ValidateGetRenderbufferParameterivBase(const Context *context,
6982 angle::EntryPoint entryPoint,
6983 GLenum target,
6984 GLenum pname,
6985 GLsizei *length)
6986 {
6987 if (length)
6988 {
6989 *length = 0;
6990 }
6991
6992 if (target != GL_RENDERBUFFER)
6993 {
6994 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
6995 return false;
6996 }
6997
6998 Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
6999 if (renderbuffer == nullptr)
7000 {
7001 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kRenderbufferNotBound);
7002 return false;
7003 }
7004
7005 switch (pname)
7006 {
7007 case GL_RENDERBUFFER_WIDTH:
7008 case GL_RENDERBUFFER_HEIGHT:
7009 case GL_RENDERBUFFER_INTERNAL_FORMAT:
7010 case GL_RENDERBUFFER_RED_SIZE:
7011 case GL_RENDERBUFFER_GREEN_SIZE:
7012 case GL_RENDERBUFFER_BLUE_SIZE:
7013 case GL_RENDERBUFFER_ALPHA_SIZE:
7014 case GL_RENDERBUFFER_DEPTH_SIZE:
7015 case GL_RENDERBUFFER_STENCIL_SIZE:
7016 break;
7017
7018 case GL_RENDERBUFFER_SAMPLES_ANGLE:
7019 if (context->getClientMajorVersion() < 3 &&
7020 !context->getExtensions().framebufferMultisampleANGLE)
7021 {
7022 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7023 return false;
7024 }
7025 break;
7026
7027 case GL_MEMORY_SIZE_ANGLE:
7028 if (!context->getExtensions().memorySizeANGLE)
7029 {
7030 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7031 return false;
7032 }
7033 break;
7034
7035 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
7036 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
7037 if (!context->getExtensions().getImageANGLE)
7038 {
7039 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
7040 return false;
7041 }
7042 break;
7043
7044 case GL_RESOURCE_INITIALIZED_ANGLE:
7045 if (!context->getExtensions().robustResourceInitializationANGLE)
7046 {
7047 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
7048 kRobustResourceInitializationExtensionRequired);
7049 return false;
7050 }
7051 break;
7052
7053 default:
7054 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7055 return false;
7056 }
7057
7058 if (length)
7059 {
7060 *length = 1;
7061 }
7062 return true;
7063 }
7064
ValidateGetShaderivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID shader,GLenum pname,GLsizei * length)7065 bool ValidateGetShaderivBase(const Context *context,
7066 angle::EntryPoint entryPoint,
7067 ShaderProgramID shader,
7068 GLenum pname,
7069 GLsizei *length)
7070 {
7071 if (length)
7072 {
7073 *length = 0;
7074 }
7075
7076 if (context->isContextLost())
7077 {
7078 ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
7079
7080 if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
7081 {
7082 // Generate an error but still return true, the context still needs to return a
7083 // value in this case.
7084 return true;
7085 }
7086 else
7087 {
7088 return false;
7089 }
7090 }
7091
7092 if (GetValidShader(context, entryPoint, shader) == nullptr)
7093 {
7094 return false;
7095 }
7096
7097 switch (pname)
7098 {
7099 case GL_SHADER_TYPE:
7100 case GL_DELETE_STATUS:
7101 case GL_COMPILE_STATUS:
7102 case GL_INFO_LOG_LENGTH:
7103 case GL_SHADER_SOURCE_LENGTH:
7104 break;
7105
7106 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
7107 if (!context->getExtensions().translatedShaderSourceANGLE)
7108 {
7109 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7110 return false;
7111 }
7112 break;
7113
7114 case GL_COMPLETION_STATUS_KHR:
7115 if (!context->getExtensions().parallelShaderCompileKHR)
7116 {
7117 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
7118 return false;
7119 }
7120 break;
7121
7122 default:
7123 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7124 return false;
7125 }
7126
7127 if (length)
7128 {
7129 *length = 1;
7130 }
7131 return true;
7132 }
7133
ValidateGetTexParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei * length)7134 bool ValidateGetTexParameterBase(const Context *context,
7135 angle::EntryPoint entryPoint,
7136 TextureType target,
7137 GLenum pname,
7138 GLsizei *length)
7139 {
7140 if (length)
7141 {
7142 *length = 0;
7143 }
7144
7145 if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
7146 target == TextureType::Buffer)
7147 {
7148 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
7149 return false;
7150 }
7151
7152 if (context->getTextureByType(target) == nullptr)
7153 {
7154 // Should only be possible for external textures
7155 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
7156 return false;
7157 }
7158
7159 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
7160 {
7161 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7162 return false;
7163 }
7164
7165 switch (pname)
7166 {
7167 case GL_TEXTURE_MAG_FILTER:
7168 case GL_TEXTURE_MIN_FILTER:
7169 case GL_TEXTURE_WRAP_S:
7170 case GL_TEXTURE_WRAP_T:
7171 break;
7172
7173 case GL_TEXTURE_USAGE_ANGLE:
7174 if (!context->getExtensions().textureUsageANGLE)
7175 {
7176 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7177 return false;
7178 }
7179 break;
7180
7181 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
7182 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
7183 {
7184 return false;
7185 }
7186 break;
7187
7188 case GL_TEXTURE_IMMUTABLE_FORMAT:
7189 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT)
7190 {
7191 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7192 return false;
7193 }
7194 break;
7195
7196 case GL_TEXTURE_WRAP_R:
7197 case GL_TEXTURE_IMMUTABLE_LEVELS:
7198 case GL_TEXTURE_SWIZZLE_R:
7199 case GL_TEXTURE_SWIZZLE_G:
7200 case GL_TEXTURE_SWIZZLE_B:
7201 case GL_TEXTURE_SWIZZLE_A:
7202 case GL_TEXTURE_BASE_LEVEL:
7203 case GL_TEXTURE_MAX_LEVEL:
7204 case GL_TEXTURE_MIN_LOD:
7205 case GL_TEXTURE_MAX_LOD:
7206 if (context->getClientMajorVersion() < 3)
7207 {
7208 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
7209 return false;
7210 }
7211 break;
7212
7213 case GL_TEXTURE_COMPARE_MODE:
7214 case GL_TEXTURE_COMPARE_FUNC:
7215 if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT)
7216 {
7217 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7218 return false;
7219 }
7220 break;
7221
7222 case GL_TEXTURE_SRGB_DECODE_EXT:
7223 if (!context->getExtensions().textureSRGBDecodeEXT)
7224 {
7225 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7226 return false;
7227 }
7228 break;
7229
7230 case GL_DEPTH_STENCIL_TEXTURE_MODE:
7231 if (context->getClientVersion() < ES_3_1 &&
7232 !context->getExtensions().stencilTexturingANGLE)
7233 {
7234 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7235 return false;
7236 }
7237 break;
7238
7239 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
7240 if (context->getClientVersion() < ES_3_1)
7241 {
7242 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
7243 return false;
7244 }
7245 break;
7246
7247 case GL_GENERATE_MIPMAP:
7248 case GL_TEXTURE_CROP_RECT_OES:
7249 // TODO([email protected]): Restrict to GL_OES_draw_texture
7250 // after GL_OES_draw_texture functionality implemented
7251 if (context->getClientMajorVersion() > 1)
7252 {
7253 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7254 return false;
7255 }
7256 break;
7257
7258 case GL_MEMORY_SIZE_ANGLE:
7259 if (!context->getExtensions().memorySizeANGLE)
7260 {
7261 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7262 return false;
7263 }
7264 break;
7265
7266 case GL_TEXTURE_BORDER_COLOR:
7267 if (!context->getExtensions().textureBorderClampAny() &&
7268 context->getClientVersion() < ES_3_2)
7269 {
7270 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7271 return false;
7272 }
7273 break;
7274
7275 case GL_TEXTURE_NATIVE_ID_ANGLE:
7276 if (!context->getExtensions().textureExternalUpdateANGLE)
7277 {
7278 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
7279 return false;
7280 }
7281 break;
7282
7283 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
7284 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
7285 if (!context->getExtensions().getImageANGLE)
7286 {
7287 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
7288 return false;
7289 }
7290 break;
7291
7292 case GL_RESOURCE_INITIALIZED_ANGLE:
7293 if (!context->getExtensions().robustResourceInitializationANGLE)
7294 {
7295 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
7296 kRobustResourceInitializationExtensionRequired);
7297 return false;
7298 }
7299 break;
7300
7301 case GL_TEXTURE_PROTECTED_EXT:
7302 if (!context->getExtensions().protectedTexturesEXT)
7303 {
7304 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
7305 return false;
7306 }
7307 break;
7308
7309 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
7310 break;
7311
7312 case GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM:
7313 if (!context->getExtensions().textureFoveatedQCOM)
7314 {
7315 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
7316 return false;
7317 }
7318 break;
7319
7320 case GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM:
7321 if (!context->getExtensions().textureFoveatedQCOM)
7322 {
7323 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
7324 return false;
7325 }
7326 break;
7327
7328 case GL_SURFACE_COMPRESSION_EXT:
7329 if (!context->getExtensions().textureStorageCompressionEXT)
7330 {
7331 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
7332 kTextureStorageCompressionExtensionRequired);
7333 return false;
7334 }
7335 break;
7336
7337 default:
7338 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7339 return false;
7340 }
7341
7342 if (length)
7343 {
7344 *length = GetTexParameterCount(pname);
7345 }
7346 return true;
7347 }
7348
ValidateGetVertexAttribBase(const Context * context,angle::EntryPoint entryPoint,GLuint index,GLenum pname,GLsizei * length,bool pointer,bool pureIntegerEntryPoint)7349 bool ValidateGetVertexAttribBase(const Context *context,
7350 angle::EntryPoint entryPoint,
7351 GLuint index,
7352 GLenum pname,
7353 GLsizei *length,
7354 bool pointer,
7355 bool pureIntegerEntryPoint)
7356 {
7357 if (length)
7358 {
7359 *length = 0;
7360 }
7361
7362 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
7363 {
7364 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
7365 return false;
7366 }
7367
7368 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
7369 {
7370 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
7371 return false;
7372 }
7373
7374 if (pointer)
7375 {
7376 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
7377 {
7378 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7379 return false;
7380 }
7381 }
7382 else
7383 {
7384 switch (pname)
7385 {
7386 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
7387 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
7388 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
7389 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
7390 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
7391 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
7392 case GL_CURRENT_VERTEX_ATTRIB:
7393 break;
7394
7395 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
7396 static_assert(
7397 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
7398 "ANGLE extension enums not equal to GL enums.");
7399 if (context->getClientMajorVersion() < 3 &&
7400 !context->getExtensions().instancedArraysAny())
7401 {
7402 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7403 return false;
7404 }
7405 break;
7406
7407 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
7408 if (context->getClientMajorVersion() < 3)
7409 {
7410 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7411 return false;
7412 }
7413 break;
7414
7415 case GL_VERTEX_ATTRIB_BINDING:
7416 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
7417 if (context->getClientVersion() < ES_3_1)
7418 {
7419 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
7420 return false;
7421 }
7422 break;
7423
7424 default:
7425 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7426 return false;
7427 }
7428 }
7429
7430 if (length)
7431 {
7432 if (pname == GL_CURRENT_VERTEX_ATTRIB)
7433 {
7434 *length = 4;
7435 }
7436 else
7437 {
7438 *length = 1;
7439 }
7440 }
7441
7442 return true;
7443 }
7444
ValidatePixelPack(const Context * context,angle::EntryPoint entryPoint,GLenum format,GLenum type,GLint x,GLint y,GLsizei width,GLsizei height,GLsizei bufSize,GLsizei * length,const void * pixels)7445 bool ValidatePixelPack(const Context *context,
7446 angle::EntryPoint entryPoint,
7447 GLenum format,
7448 GLenum type,
7449 GLint x,
7450 GLint y,
7451 GLsizei width,
7452 GLsizei height,
7453 GLsizei bufSize,
7454 GLsizei *length,
7455 const void *pixels)
7456 {
7457 // Check for pixel pack buffer related API errors
7458 Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
7459 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
7460 {
7461 // ...the buffer object's data store is currently mapped.
7462 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
7463 return false;
7464 }
7465 if (pixelPackBuffer != nullptr &&
7466 pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
7467 {
7468 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
7469 return false;
7470 }
7471
7472 // .. the data would be packed to the buffer object such that the memory writes required
7473 // would exceed the data store size.
7474 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
7475 const Extents size(width, height, 1);
7476 const auto &pack = context->getState().getPackState();
7477
7478 GLuint endByte = 0;
7479 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
7480 {
7481 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7482 return false;
7483 }
7484
7485 if (bufSize >= 0)
7486 {
7487 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
7488 {
7489 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
7490 return false;
7491 }
7492 }
7493
7494 if (pixelPackBuffer != nullptr)
7495 {
7496 CheckedNumeric<size_t> checkedEndByte(endByte);
7497 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
7498 checkedEndByte += checkedOffset;
7499
7500 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
7501 {
7502 // Overflow past the end of the buffer
7503 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kParamOverflow);
7504 return false;
7505 }
7506 }
7507
7508 if (pixelPackBuffer == nullptr && length != nullptr)
7509 {
7510 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
7511 {
7512 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7513 return false;
7514 }
7515
7516 *length = static_cast<GLsizei>(endByte);
7517 }
7518
7519 if (context->isWebGL())
7520 {
7521 // WebGL 2.0 disallows the scenario:
7522 // GL_PACK_SKIP_PIXELS + width > DataStoreWidth
7523 // where:
7524 // DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width)
7525 // Since these two pack parameters can only be set to non-zero values
7526 // on WebGL 2.0 contexts, verify them for all WebGL contexts.
7527 GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width;
7528 if (pack.skipPixels + width > dataStoreWidth)
7529 {
7530 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidPackParametersForWebGL);
7531 return false;
7532 }
7533 }
7534
7535 return true;
7536 }
7537
ValidateReadPixelsBase(const Context * context,angle::EntryPoint entryPoint,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLsizei * length,GLsizei * columns,GLsizei * rows,const void * pixels)7538 bool ValidateReadPixelsBase(const Context *context,
7539 angle::EntryPoint entryPoint,
7540 GLint x,
7541 GLint y,
7542 GLsizei width,
7543 GLsizei height,
7544 GLenum format,
7545 GLenum type,
7546 GLsizei bufSize,
7547 GLsizei *length,
7548 GLsizei *columns,
7549 GLsizei *rows,
7550 const void *pixels)
7551 {
7552 if (length != nullptr)
7553 {
7554 *length = 0;
7555 }
7556 if (rows != nullptr)
7557 {
7558 *rows = 0;
7559 }
7560 if (columns != nullptr)
7561 {
7562 *columns = 0;
7563 }
7564
7565 if (width < 0 || height < 0)
7566 {
7567 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
7568 return false;
7569 }
7570
7571 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
7572 ASSERT(readFramebuffer);
7573
7574 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
7575 {
7576 return false;
7577 }
7578
7579 // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
7580 // resolved before reading.
7581 if (!readFramebuffer->isDefault() &&
7582 !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
7583 {
7584 return false;
7585 }
7586
7587 if (readFramebuffer->getReadBufferState() == GL_NONE)
7588 {
7589 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
7590 return false;
7591 }
7592
7593 const FramebufferAttachment *readBuffer = nullptr;
7594 switch (format)
7595 {
7596 case GL_DEPTH_COMPONENT:
7597 readBuffer = readFramebuffer->getDepthAttachment();
7598 break;
7599 case GL_STENCIL_INDEX_OES:
7600 case GL_DEPTH_STENCIL_OES:
7601 readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
7602 break;
7603 default:
7604 readBuffer = readFramebuffer->getReadColorAttachment();
7605 break;
7606 }
7607
7608 // OVR_multiview2, Revision 1:
7609 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
7610 // the number of views in the current read framebuffer is more than one.
7611 if (readFramebuffer->readDisallowedByMultiview())
7612 {
7613 ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
7614 return false;
7615 }
7616
7617 if (context->isWebGL())
7618 {
7619 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
7620 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
7621 // and type before validating the combination of format and type. However, the
7622 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
7623 // verifies that GL_INVALID_OPERATION is generated.
7624 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
7625 // dEQP/WebGL.
7626 if (!ValidReadPixelsFormatEnum(context, format))
7627 {
7628 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
7629 return false;
7630 }
7631
7632 if (!ValidReadPixelsTypeEnum(context, type))
7633 {
7634 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
7635 return false;
7636 }
7637 }
7638
7639 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
7640 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
7641 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
7642 // situation is an application error that would lead to a crash in ANGLE.
7643 if (readBuffer == nullptr)
7644 {
7645 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
7646 return false;
7647 }
7648
7649 GLenum currentFormat = GL_NONE;
7650 GLenum currentType = GL_NONE;
7651
7652 switch (format)
7653 {
7654 case GL_DEPTH_COMPONENT:
7655 case GL_STENCIL_INDEX_OES:
7656 case GL_DEPTH_STENCIL_OES:
7657 // Only rely on ValidReadPixelsFormatType for depth/stencil formats
7658 break;
7659 default:
7660 currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
7661 currentType = readFramebuffer->getImplementationColorReadType(context);
7662 break;
7663 }
7664
7665 bool validFormatTypeCombination =
7666 ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
7667
7668 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
7669 {
7670 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
7671 return false;
7672 }
7673
7674 if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length,
7675 pixels))
7676 {
7677 return false;
7678 }
7679
7680 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
7681 angle::CheckedNumeric<int> clippedExtent(length);
7682 if (start < 0)
7683 {
7684 // "subtract" the area that is less than 0
7685 clippedExtent += start;
7686 }
7687
7688 angle::CheckedNumeric<int> readExtent = start;
7689 readExtent += length;
7690 if (!readExtent.IsValid())
7691 {
7692 return false;
7693 }
7694
7695 if (readExtent.ValueOrDie() > bufferSize)
7696 {
7697 // Subtract the region to the right of the read buffer
7698 clippedExtent -= (readExtent - bufferSize);
7699 }
7700
7701 if (!clippedExtent.IsValid())
7702 {
7703 return false;
7704 }
7705
7706 *outExtent = std::max<int>(clippedExtent.ValueOrDie(), 0);
7707 return true;
7708 };
7709
7710 GLsizei writtenColumns = 0;
7711 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
7712 {
7713 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7714 return false;
7715 }
7716
7717 GLsizei writtenRows = 0;
7718 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
7719 {
7720 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
7721 return false;
7722 }
7723
7724 if (columns != nullptr)
7725 {
7726 *columns = writtenColumns;
7727 }
7728
7729 if (rows != nullptr)
7730 {
7731 *rows = writtenRows;
7732 }
7733
7734 return true;
7735 }
7736
7737 template <typename ParamType>
ValidateTexParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)7738 bool ValidateTexParameterBase(const Context *context,
7739 angle::EntryPoint entryPoint,
7740 TextureType target,
7741 GLenum pname,
7742 GLsizei bufSize,
7743 bool vectorParams,
7744 const ParamType *params)
7745 {
7746 if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
7747 target == TextureType::Buffer)
7748 {
7749 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
7750 return false;
7751 }
7752
7753 if (context->getTextureByType(target) == nullptr)
7754 {
7755 // Should only be possible for external textures
7756 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
7757 return false;
7758 }
7759
7760 const GLsizei minBufSize = GetTexParameterCount(pname);
7761 if (bufSize >= 0 && bufSize < minBufSize)
7762 {
7763 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
7764 return false;
7765 }
7766
7767 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
7768 {
7769 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7770 return false;
7771 }
7772
7773 switch (pname)
7774 {
7775 case GL_TEXTURE_WRAP_R:
7776 case GL_TEXTURE_SWIZZLE_R:
7777 case GL_TEXTURE_SWIZZLE_G:
7778 case GL_TEXTURE_SWIZZLE_B:
7779 case GL_TEXTURE_SWIZZLE_A:
7780 case GL_TEXTURE_BASE_LEVEL:
7781 case GL_TEXTURE_MAX_LEVEL:
7782 case GL_TEXTURE_COMPARE_MODE:
7783 case GL_TEXTURE_COMPARE_FUNC:
7784 case GL_TEXTURE_MIN_LOD:
7785 case GL_TEXTURE_MAX_LOD:
7786 if (context->getClientMajorVersion() < 3 &&
7787 !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
7788 {
7789 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
7790 return false;
7791 }
7792 if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL)
7793 {
7794 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7795 }
7796 break;
7797
7798 case GL_GENERATE_MIPMAP:
7799 case GL_TEXTURE_CROP_RECT_OES:
7800 if (context->getClientMajorVersion() > 1)
7801 {
7802 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
7803 return false;
7804 }
7805 break;
7806
7807 default:
7808 break;
7809 }
7810
7811 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
7812 {
7813 switch (pname)
7814 {
7815 case GL_TEXTURE_MIN_FILTER:
7816 case GL_TEXTURE_MAG_FILTER:
7817 case GL_TEXTURE_WRAP_S:
7818 case GL_TEXTURE_WRAP_T:
7819 case GL_TEXTURE_WRAP_R:
7820 case GL_TEXTURE_MIN_LOD:
7821 case GL_TEXTURE_MAX_LOD:
7822 case GL_TEXTURE_COMPARE_MODE:
7823 case GL_TEXTURE_COMPARE_FUNC:
7824 case GL_TEXTURE_BORDER_COLOR:
7825 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
7826 return false;
7827 }
7828 }
7829
7830 switch (pname)
7831 {
7832 case GL_TEXTURE_WRAP_S:
7833 case GL_TEXTURE_WRAP_T:
7834 case GL_TEXTURE_WRAP_R:
7835 {
7836 bool restrictedWrapModes = ((target == TextureType::External &&
7837 !context->getExtensions().EGLImageExternalWrapModesEXT) ||
7838 target == TextureType::Rectangle);
7839 if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes))
7840 {
7841 return false;
7842 }
7843 }
7844 break;
7845
7846 case GL_TEXTURE_MIN_FILTER:
7847 {
7848 bool restrictedMinFilter =
7849 target == TextureType::External || target == TextureType::Rectangle;
7850 if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter))
7851 {
7852 return false;
7853 }
7854 }
7855 break;
7856
7857 case GL_TEXTURE_MAG_FILTER:
7858 if (!ValidateTextureMagFilterValue(context, entryPoint, params))
7859 {
7860 return false;
7861 }
7862 break;
7863
7864 case GL_TEXTURE_USAGE_ANGLE:
7865 if (!context->getExtensions().textureUsageANGLE)
7866 {
7867 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7868 return false;
7869 }
7870
7871 switch (ConvertToGLenum(params[0]))
7872 {
7873 case GL_NONE:
7874 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
7875 break;
7876
7877 default:
7878 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7879 return false;
7880 }
7881 break;
7882
7883 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
7884 {
7885 GLfloat paramValue = static_cast<GLfloat>(params[0]);
7886 if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
7887 {
7888 return false;
7889 }
7890 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
7891 }
7892 break;
7893
7894 case GL_TEXTURE_MIN_LOD:
7895 case GL_TEXTURE_MAX_LOD:
7896 // any value is permissible
7897 break;
7898
7899 case GL_TEXTURE_COMPARE_MODE:
7900 if (!ValidateTextureCompareModeValue(context, entryPoint, params))
7901 {
7902 return false;
7903 }
7904 break;
7905
7906 case GL_TEXTURE_COMPARE_FUNC:
7907 if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
7908 {
7909 return false;
7910 }
7911 break;
7912
7913 case GL_TEXTURE_SWIZZLE_R:
7914 case GL_TEXTURE_SWIZZLE_G:
7915 case GL_TEXTURE_SWIZZLE_B:
7916 case GL_TEXTURE_SWIZZLE_A:
7917 switch (ConvertToGLenum(params[0]))
7918 {
7919 case GL_RED:
7920 case GL_GREEN:
7921 case GL_BLUE:
7922 case GL_ALPHA:
7923 case GL_ZERO:
7924 case GL_ONE:
7925 break;
7926
7927 default:
7928 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7929 return false;
7930 }
7931 break;
7932
7933 case GL_TEXTURE_BASE_LEVEL:
7934 if (ConvertToGLint(params[0]) < 0)
7935 {
7936 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBaseLevelNegative);
7937 return false;
7938 }
7939 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
7940 {
7941 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7942 return false;
7943 }
7944 if ((target == TextureType::_2DMultisample ||
7945 target == TextureType::_2DMultisampleArray) &&
7946 static_cast<GLuint>(params[0]) != 0)
7947 {
7948 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7949 return false;
7950 }
7951 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
7952 {
7953 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
7954 return false;
7955 }
7956 break;
7957
7958 case GL_TEXTURE_MAX_LEVEL:
7959 if (ConvertToGLint(params[0]) < 0)
7960 {
7961 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
7962 return false;
7963 }
7964 break;
7965
7966 case GL_DEPTH_STENCIL_TEXTURE_MODE:
7967 if (context->getClientVersion() < ES_3_1 &&
7968 !context->getExtensions().stencilTexturingANGLE)
7969 {
7970 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7971 return false;
7972 }
7973 switch (ConvertToGLenum(params[0]))
7974 {
7975 case GL_DEPTH_COMPONENT:
7976 case GL_STENCIL_INDEX:
7977 break;
7978
7979 default:
7980 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
7981 return false;
7982 }
7983 break;
7984
7985 case GL_TEXTURE_SRGB_DECODE_EXT:
7986 if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
7987 {
7988 return false;
7989 }
7990 break;
7991
7992 case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
7993 if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params))
7994 {
7995 return false;
7996 }
7997 break;
7998
7999 case GL_GENERATE_MIPMAP:
8000 if (context->getClientMajorVersion() > 1)
8001 {
8002 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
8003 return false;
8004 }
8005 break;
8006
8007 case GL_TEXTURE_CROP_RECT_OES:
8008 if (context->getClientMajorVersion() > 1)
8009 {
8010 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
8011 return false;
8012 }
8013 if (!vectorParams)
8014 {
8015 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
8016 return false;
8017 }
8018 break;
8019
8020 case GL_TEXTURE_BORDER_COLOR:
8021 if (!context->getExtensions().textureBorderClampAny() &&
8022 context->getClientVersion() < ES_3_2)
8023 {
8024 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
8025 return false;
8026 }
8027 if (!vectorParams)
8028 {
8029 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
8030 return false;
8031 }
8032 break;
8033
8034 case GL_RESOURCE_INITIALIZED_ANGLE:
8035 if (!context->getExtensions().robustResourceInitializationANGLE)
8036 {
8037 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
8038 kRobustResourceInitializationExtensionRequired);
8039 return false;
8040 }
8041 break;
8042
8043 case GL_TEXTURE_PROTECTED_EXT:
8044 if (!context->getExtensions().protectedTexturesEXT)
8045 {
8046 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
8047 return false;
8048 }
8049 if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
8050 {
8051 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
8052 "Protected Texture must match Protected Context");
8053 return false;
8054 }
8055 break;
8056
8057 case GL_RENDERABILITY_VALIDATION_ANGLE:
8058 if (!context->getExtensions().renderabilityValidationANGLE)
8059 {
8060 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8061 return false;
8062 }
8063 break;
8064
8065 case GL_TEXTURE_TILING_EXT:
8066 if (!context->getExtensions().memoryObjectEXT)
8067 {
8068 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
8069 return false;
8070 }
8071 switch (ConvertToGLenum(params[0]))
8072 {
8073 case GL_OPTIMAL_TILING_EXT:
8074 case GL_LINEAR_TILING_EXT:
8075 break;
8076
8077 default:
8078 ANGLE_VALIDATION_ERROR(
8079 GL_INVALID_OPERATION,
8080 "Texture Tilling Mode must be OPTIMAL_TILING_EXT or LINEAR_TILING_EXT");
8081 return false;
8082 }
8083 break;
8084
8085 case GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM:
8086 if (!context->getExtensions().textureFoveatedQCOM)
8087 {
8088 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
8089 return false;
8090 }
8091 {
8092 const GLuint features = static_cast<GLuint>(params[0]);
8093 constexpr GLuint kSupportedFeatures = GL_FOVEATION_ENABLE_BIT_QCOM;
8094 if (features != (features & kSupportedFeatures))
8095 {
8096 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureInvalidParameters);
8097 return false;
8098 }
8099 if ((context->getTextureByType(target)->getFoveatedFeatureBits() &
8100 GL_FOVEATION_ENABLE_BIT_QCOM) &&
8101 (features & GL_FOVEATION_ENABLE_BIT_QCOM) == 0)
8102 {
8103 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFoveatedTextureCannotDisable);
8104 return false;
8105 }
8106 }
8107 break;
8108
8109 case GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM:
8110 if (!context->getExtensions().textureFoveatedQCOM)
8111 {
8112 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
8113 return false;
8114 }
8115 if (static_cast<GLfloat>(params[0]) < 0.0 || static_cast<GLfloat>(params[0]) > 1.0)
8116 {
8117 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFoveatedTextureInvalidPixelDensity);
8118 return false;
8119 }
8120 break;
8121
8122 default:
8123 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8124 return false;
8125 }
8126
8127 return true;
8128 }
8129
8130 template bool ValidateTexParameterBase(const Context *,
8131 angle::EntryPoint,
8132 TextureType,
8133 GLenum,
8134 GLsizei,
8135 bool,
8136 const GLfloat *);
8137 template bool ValidateTexParameterBase(const Context *,
8138 angle::EntryPoint,
8139 TextureType,
8140 GLenum,
8141 GLsizei,
8142 bool,
8143 const GLint *);
8144 template bool ValidateTexParameterBase(const Context *,
8145 angle::EntryPoint,
8146 TextureType,
8147 GLenum,
8148 GLsizei,
8149 bool,
8150 const GLuint *);
8151
ValidateGetActiveUniformBlockivBase(const Context * context,angle::EntryPoint entryPoint,ShaderProgramID program,UniformBlockIndex uniformBlockIndex,GLenum pname,GLsizei * length)8152 bool ValidateGetActiveUniformBlockivBase(const Context *context,
8153 angle::EntryPoint entryPoint,
8154 ShaderProgramID program,
8155 UniformBlockIndex uniformBlockIndex,
8156 GLenum pname,
8157 GLsizei *length)
8158 {
8159 if (length)
8160 {
8161 *length = 0;
8162 }
8163
8164 if (context->getClientMajorVersion() < 3)
8165 {
8166 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8167 return false;
8168 }
8169
8170 Program *programObject = GetValidProgram(context, entryPoint, program);
8171 if (!programObject)
8172 {
8173 return false;
8174 }
8175
8176 const ProgramExecutable &executable = programObject->getExecutable();
8177 if (uniformBlockIndex.value >= executable.getUniformBlocks().size())
8178 {
8179 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
8180 return false;
8181 }
8182
8183 switch (pname)
8184 {
8185 case GL_UNIFORM_BLOCK_BINDING:
8186 case GL_UNIFORM_BLOCK_DATA_SIZE:
8187 case GL_UNIFORM_BLOCK_NAME_LENGTH:
8188 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
8189 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
8190 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
8191 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
8192 break;
8193
8194 default:
8195 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8196 return false;
8197 }
8198
8199 if (length)
8200 {
8201 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
8202 {
8203 const InterfaceBlock &uniformBlock =
8204 executable.getUniformBlockByIndex(uniformBlockIndex.value);
8205 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
8206 }
8207 else
8208 {
8209 *length = 1;
8210 }
8211 }
8212
8213 return true;
8214 }
8215
8216 template <typename ParamType>
ValidateSamplerParameterBase(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei bufSize,bool vectorParams,const ParamType * params)8217 bool ValidateSamplerParameterBase(const Context *context,
8218 angle::EntryPoint entryPoint,
8219 SamplerID sampler,
8220 GLenum pname,
8221 GLsizei bufSize,
8222 bool vectorParams,
8223 const ParamType *params)
8224 {
8225 if (context->getClientMajorVersion() < 3)
8226 {
8227 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8228 return false;
8229 }
8230
8231 if (!context->isSampler(sampler))
8232 {
8233 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
8234 return false;
8235 }
8236
8237 const GLsizei minBufSize = GetSamplerParameterCount(pname);
8238 if (bufSize >= 0 && bufSize < minBufSize)
8239 {
8240 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
8241 return false;
8242 }
8243
8244 switch (pname)
8245 {
8246 case GL_TEXTURE_WRAP_S:
8247 case GL_TEXTURE_WRAP_T:
8248 case GL_TEXTURE_WRAP_R:
8249 if (!ValidateTextureWrapModeValue(context, entryPoint, params, false))
8250 {
8251 return false;
8252 }
8253 break;
8254
8255 case GL_TEXTURE_MIN_FILTER:
8256 if (!ValidateTextureMinFilterValue(context, entryPoint, params, false))
8257 {
8258 return false;
8259 }
8260 break;
8261
8262 case GL_TEXTURE_MAG_FILTER:
8263 if (!ValidateTextureMagFilterValue(context, entryPoint, params))
8264 {
8265 return false;
8266 }
8267 break;
8268
8269 case GL_TEXTURE_MIN_LOD:
8270 case GL_TEXTURE_MAX_LOD:
8271 // any value is permissible
8272 break;
8273
8274 case GL_TEXTURE_COMPARE_MODE:
8275 if (!ValidateTextureCompareModeValue(context, entryPoint, params))
8276 {
8277 return false;
8278 }
8279 break;
8280
8281 case GL_TEXTURE_COMPARE_FUNC:
8282 if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
8283 {
8284 return false;
8285 }
8286 break;
8287
8288 case GL_TEXTURE_SRGB_DECODE_EXT:
8289 if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
8290 {
8291 return false;
8292 }
8293 break;
8294
8295 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
8296 {
8297 GLfloat paramValue = static_cast<GLfloat>(params[0]);
8298 if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
8299 {
8300 return false;
8301 }
8302 }
8303 break;
8304
8305 case GL_TEXTURE_BORDER_COLOR:
8306 if (!context->getExtensions().textureBorderClampAny() &&
8307 context->getClientVersion() < ES_3_2)
8308 {
8309 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
8310 return false;
8311 }
8312 if (!vectorParams)
8313 {
8314 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
8315 return false;
8316 }
8317 break;
8318
8319 default:
8320 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8321 return false;
8322 }
8323
8324 return true;
8325 }
8326
8327 template bool ValidateSamplerParameterBase(const Context *,
8328 angle::EntryPoint,
8329 SamplerID,
8330 GLenum,
8331 GLsizei,
8332 bool,
8333 const GLfloat *);
8334 template bool ValidateSamplerParameterBase(const Context *,
8335 angle::EntryPoint,
8336 SamplerID,
8337 GLenum,
8338 GLsizei,
8339 bool,
8340 const GLint *);
8341 template bool ValidateSamplerParameterBase(const Context *,
8342 angle::EntryPoint,
8343 SamplerID,
8344 GLenum,
8345 GLsizei,
8346 bool,
8347 const GLuint *);
8348
ValidateGetSamplerParameterBase(const Context * context,angle::EntryPoint entryPoint,SamplerID sampler,GLenum pname,GLsizei * length)8349 bool ValidateGetSamplerParameterBase(const Context *context,
8350 angle::EntryPoint entryPoint,
8351 SamplerID sampler,
8352 GLenum pname,
8353 GLsizei *length)
8354 {
8355 if (length)
8356 {
8357 *length = 0;
8358 }
8359
8360 if (context->getClientMajorVersion() < 3)
8361 {
8362 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8363 return false;
8364 }
8365
8366 if (!context->isSampler(sampler))
8367 {
8368 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
8369 return false;
8370 }
8371
8372 switch (pname)
8373 {
8374 case GL_TEXTURE_WRAP_S:
8375 case GL_TEXTURE_WRAP_T:
8376 case GL_TEXTURE_WRAP_R:
8377 case GL_TEXTURE_MIN_FILTER:
8378 case GL_TEXTURE_MAG_FILTER:
8379 case GL_TEXTURE_MIN_LOD:
8380 case GL_TEXTURE_MAX_LOD:
8381 case GL_TEXTURE_COMPARE_MODE:
8382 case GL_TEXTURE_COMPARE_FUNC:
8383 break;
8384
8385 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
8386 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
8387 {
8388 return false;
8389 }
8390 break;
8391
8392 case GL_TEXTURE_SRGB_DECODE_EXT:
8393 if (!context->getExtensions().textureSRGBDecodeEXT)
8394 {
8395 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8396 return false;
8397 }
8398 break;
8399
8400 case GL_TEXTURE_BORDER_COLOR:
8401 if (!context->getExtensions().textureBorderClampAny() &&
8402 context->getClientVersion() < ES_3_2)
8403 {
8404 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
8405 return false;
8406 }
8407 break;
8408
8409 default:
8410 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8411 return false;
8412 }
8413
8414 if (length)
8415 {
8416 *length = GetSamplerParameterCount(pname);
8417 }
8418 return true;
8419 }
8420
ValidateGetInternalFormativBase(const Context * context,angle::EntryPoint entryPoint,GLenum target,GLenum internalformat,GLenum pname,GLsizei bufSize,GLsizei * numParams)8421 bool ValidateGetInternalFormativBase(const Context *context,
8422 angle::EntryPoint entryPoint,
8423 GLenum target,
8424 GLenum internalformat,
8425 GLenum pname,
8426 GLsizei bufSize,
8427 GLsizei *numParams)
8428 {
8429 if (numParams)
8430 {
8431 *numParams = 0;
8432 }
8433
8434 if (context->getClientMajorVersion() < 3)
8435 {
8436 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
8437 return false;
8438 }
8439
8440 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
8441 if (!formatCaps.renderbuffer)
8442 {
8443 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFormatNotRenderable);
8444 return false;
8445 }
8446
8447 switch (target)
8448 {
8449 case GL_RENDERBUFFER:
8450 break;
8451
8452 case GL_TEXTURE_2D_MULTISAMPLE:
8453 if (context->getClientVersion() < ES_3_1 &&
8454 !context->getExtensions().textureMultisampleANGLE)
8455 {
8456 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
8457 return false;
8458 }
8459 break;
8460 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
8461 if (context->getClientVersion() < ES_3_2 &&
8462 !context->getExtensions().textureStorageMultisample2dArrayOES)
8463 {
8464 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required);
8465 return false;
8466 }
8467 break;
8468 case GL_TEXTURE_2D:
8469 case GL_TEXTURE_CUBE_MAP:
8470 case GL_TEXTURE_3D:
8471 case GL_TEXTURE_2D_ARRAY:
8472 if (pname != GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT &&
8473 pname != GL_SURFACE_COMPRESSION_EXT)
8474 {
8475 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8476 return false;
8477 }
8478 if (!context->getExtensions().textureStorageCompressionEXT)
8479 {
8480 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
8481 kTextureStorageCompressionExtensionRequired);
8482 return false;
8483 }
8484 break;
8485 default:
8486 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8487 return false;
8488 }
8489
8490 if (bufSize < 0)
8491 {
8492 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInsufficientBufferSize);
8493 return false;
8494 }
8495
8496 GLsizei maxWriteParams = 0;
8497 switch (pname)
8498 {
8499 case GL_NUM_SAMPLE_COUNTS:
8500 maxWriteParams = 1;
8501 break;
8502
8503 case GL_SAMPLES:
8504 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
8505 break;
8506
8507 case GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT:
8508 case GL_SURFACE_COMPRESSION_EXT:
8509 if (!context->getExtensions().textureStorageCompressionEXT)
8510 {
8511 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
8512 kTextureStorageCompressionExtensionRequired);
8513 return false;
8514 }
8515 break;
8516
8517 default:
8518 ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
8519 return false;
8520 }
8521
8522 if (numParams)
8523 {
8524 // glGetInternalFormativ will not overflow bufSize
8525 *numParams = std::min(bufSize, maxWriteParams);
8526 }
8527
8528 return true;
8529 }
8530
ValidateFramebufferNotMultisampled(const Context * context,angle::EntryPoint entryPoint,const Framebuffer * framebuffer,bool checkReadBufferResourceSamples)8531 bool ValidateFramebufferNotMultisampled(const Context *context,
8532 angle::EntryPoint entryPoint,
8533 const Framebuffer *framebuffer,
8534 bool checkReadBufferResourceSamples)
8535 {
8536 int samples = checkReadBufferResourceSamples
8537 ? framebuffer->getReadBufferResourceSamples(context)
8538 : framebuffer->getSamples(context);
8539 if (samples != 0)
8540 {
8541 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
8542 return false;
8543 }
8544 return true;
8545 }
8546
ValidateMultitextureUnit(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLenum texture)8547 bool ValidateMultitextureUnit(const PrivateState &state,
8548 ErrorSet *errors,
8549 angle::EntryPoint entryPoint,
8550 GLenum texture)
8551 {
8552 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + state.getCaps().maxMultitextureUnits)
8553 {
8554 errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit);
8555 return false;
8556 }
8557 return true;
8558 }
8559
ValidateTexStorageMultisample(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)8560 bool ValidateTexStorageMultisample(const Context *context,
8561 angle::EntryPoint entryPoint,
8562 TextureType target,
8563 GLsizei samples,
8564 GLint internalFormat,
8565 GLsizei width,
8566 GLsizei height)
8567 {
8568 const Caps &caps = context->getCaps();
8569 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
8570 {
8571 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
8572 return false;
8573 }
8574
8575 if (samples == 0)
8576 {
8577 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesZero);
8578 return false;
8579 }
8580
8581 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
8582 if (!formatCaps.textureAttachment)
8583 {
8584 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRenderableInternalFormat);
8585 return false;
8586 }
8587
8588 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
8589 // is one of the unsized base internalformats listed in table 8.11.
8590 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
8591 if (formatInfo.internalFormat == GL_NONE)
8592 {
8593 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
8594 return false;
8595 }
8596
8597 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
8598 {
8599 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
8600 return false;
8601 }
8602
8603 Texture *texture = context->getTextureByType(target);
8604 if (!texture || texture->id().value == 0)
8605 {
8606 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kZeroBoundToTarget);
8607 return false;
8608 }
8609
8610 if (texture->getImmutableFormat())
8611 {
8612 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImmutableTextureBound);
8613 return false;
8614 }
8615 return true;
8616 }
8617
ValidateTexStorage2DMultisampleBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLint internalFormat,GLsizei width,GLsizei height)8618 bool ValidateTexStorage2DMultisampleBase(const Context *context,
8619 angle::EntryPoint entryPoint,
8620 TextureType target,
8621 GLsizei samples,
8622 GLint internalFormat,
8623 GLsizei width,
8624 GLsizei height)
8625 {
8626 if (target != TextureType::_2DMultisample)
8627 {
8628 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8629 return false;
8630 }
8631
8632 if (width < 1 || height < 1)
8633 {
8634 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
8635 return false;
8636 }
8637
8638 return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat,
8639 width, height);
8640 }
8641
ValidateTexStorage3DMultisampleBase(const Context * context,angle::EntryPoint entryPoint,TextureType target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth)8642 bool ValidateTexStorage3DMultisampleBase(const Context *context,
8643 angle::EntryPoint entryPoint,
8644 TextureType target,
8645 GLsizei samples,
8646 GLenum internalformat,
8647 GLsizei width,
8648 GLsizei height,
8649 GLsizei depth)
8650 {
8651 if (target != TextureType::_2DMultisampleArray)
8652 {
8653 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
8654 return false;
8655 }
8656
8657 if (width < 1 || height < 1 || depth < 1)
8658 {
8659 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
8660 return false;
8661 }
8662
8663 if (depth > context->getCaps().maxArrayTextureLayers)
8664 {
8665 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureDepthOutOfRange);
8666 return false;
8667 }
8668
8669 return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalformat,
8670 width, height);
8671 }
8672
ValidateGetTexLevelParameterBase(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLenum pname,GLsizei * length)8673 bool ValidateGetTexLevelParameterBase(const Context *context,
8674 angle::EntryPoint entryPoint,
8675 TextureTarget target,
8676 GLint level,
8677 GLenum pname,
8678 GLsizei *length)
8679 {
8680
8681 if (length)
8682 {
8683 *length = 0;
8684 }
8685
8686 TextureType type = TextureTargetToType(target);
8687
8688 if (!ValidTexLevelDestinationTarget(context, type))
8689 {
8690 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8691 return false;
8692 }
8693
8694 // If type is valid, the texture object must exist
8695 ASSERT(context->getTextureByType(type) != nullptr);
8696
8697 if (!ValidMipLevel(context, type, level))
8698 {
8699 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
8700 return false;
8701 }
8702
8703 switch (pname)
8704 {
8705 case GL_TEXTURE_RED_TYPE:
8706 case GL_TEXTURE_GREEN_TYPE:
8707 case GL_TEXTURE_BLUE_TYPE:
8708 case GL_TEXTURE_ALPHA_TYPE:
8709 case GL_TEXTURE_DEPTH_TYPE:
8710 case GL_TEXTURE_RED_SIZE:
8711 case GL_TEXTURE_GREEN_SIZE:
8712 case GL_TEXTURE_BLUE_SIZE:
8713 case GL_TEXTURE_ALPHA_SIZE:
8714 case GL_TEXTURE_DEPTH_SIZE:
8715 case GL_TEXTURE_STENCIL_SIZE:
8716 case GL_TEXTURE_SHARED_SIZE:
8717 case GL_TEXTURE_INTERNAL_FORMAT:
8718 case GL_TEXTURE_WIDTH:
8719 case GL_TEXTURE_HEIGHT:
8720 case GL_TEXTURE_COMPRESSED:
8721 break;
8722
8723 case GL_TEXTURE_DEPTH:
8724 if (context->getClientVersion() < ES_3_0 && !context->getExtensions().texture3DOES)
8725 {
8726 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumNotSupported);
8727 return false;
8728 }
8729 break;
8730
8731 case GL_TEXTURE_SAMPLES:
8732 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
8733 if (context->getClientVersion() < ES_3_1 &&
8734 !context->getExtensions().textureMultisampleANGLE)
8735 {
8736 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
8737 return false;
8738 }
8739 break;
8740
8741 case GL_RESOURCE_INITIALIZED_ANGLE:
8742 if (!context->getExtensions().robustResourceInitializationANGLE)
8743 {
8744 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
8745 kRobustResourceInitializationExtensionRequired);
8746 return false;
8747 }
8748 break;
8749
8750 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
8751 case GL_TEXTURE_BUFFER_OFFSET:
8752 case GL_TEXTURE_BUFFER_SIZE:
8753 if (context->getClientVersion() < Version(3, 2) &&
8754 !context->getExtensions().textureBufferAny())
8755 {
8756 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
8757 return false;
8758 }
8759 break;
8760
8761 default:
8762 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
8763 return false;
8764 }
8765
8766 if (length)
8767 {
8768 *length = 1;
8769 }
8770 return true;
8771 }
8772
ValidateGetMultisamplefvBase(const Context * context,angle::EntryPoint entryPoint,GLenum pname,GLuint index,const GLfloat * val)8773 bool ValidateGetMultisamplefvBase(const Context *context,
8774 angle::EntryPoint entryPoint,
8775 GLenum pname,
8776 GLuint index,
8777 const GLfloat *val)
8778 {
8779 if (pname != GL_SAMPLE_POSITION)
8780 {
8781 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
8782 return false;
8783 }
8784
8785 Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
8786 GLint samples = framebuffer->getSamples(context);
8787
8788 if (index >= static_cast<GLuint>(samples))
8789 {
8790 ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsSamples);
8791 return false;
8792 }
8793
8794 return true;
8795 }
8796
ValidateSampleMaskiBase(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,GLuint maskNumber,GLbitfield mask)8797 bool ValidateSampleMaskiBase(const PrivateState &state,
8798 ErrorSet *errors,
8799 angle::EntryPoint entryPoint,
8800 GLuint maskNumber,
8801 GLbitfield mask)
8802 {
8803 if (maskNumber >= static_cast<GLuint>(state.getCaps().maxSampleMaskWords))
8804 {
8805 errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
8806 return false;
8807 }
8808
8809 return true;
8810 }
8811
RecordDrawAttribsError(const Context * context,angle::EntryPoint entryPoint)8812 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint)
8813 {
8814 // An overflow can happen when adding the offset. Check against a special constant.
8815 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
8816 VertexAttribute::kIntegerOverflow ||
8817 context->getStateCache().getInstancedVertexElementLimit() ==
8818 VertexAttribute::kIntegerOverflow)
8819 {
8820 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
8821 }
8822 else
8823 {
8824 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
8825 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
8826 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
8827 }
8828 }
8829
ValidateLoseContextCHROMIUM(const Context * context,angle::EntryPoint entryPoint,GraphicsResetStatus current,GraphicsResetStatus other)8830 bool ValidateLoseContextCHROMIUM(const Context *context,
8831 angle::EntryPoint entryPoint,
8832 GraphicsResetStatus current,
8833 GraphicsResetStatus other)
8834 {
8835 if (!context->getExtensions().loseContextCHROMIUM)
8836 {
8837 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8838 return false;
8839 }
8840
8841 switch (current)
8842 {
8843 case GraphicsResetStatus::GuiltyContextReset:
8844 case GraphicsResetStatus::InnocentContextReset:
8845 case GraphicsResetStatus::UnknownContextReset:
8846 break;
8847
8848 default:
8849 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus);
8850 }
8851
8852 switch (other)
8853 {
8854 case GraphicsResetStatus::GuiltyContextReset:
8855 case GraphicsResetStatus::InnocentContextReset:
8856 case GraphicsResetStatus::UnknownContextReset:
8857 break;
8858
8859 default:
8860 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidResetStatus);
8861 }
8862
8863 return true;
8864 }
8865
8866 // GL_ANGLE_texture_storage_external
ValidateTexImage2DExternalANGLE(const Context * context,angle::EntryPoint entryPoint,TextureTarget target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type)8867 bool ValidateTexImage2DExternalANGLE(const Context *context,
8868 angle::EntryPoint entryPoint,
8869 TextureTarget target,
8870 GLint level,
8871 GLint internalformat,
8872 GLsizei width,
8873 GLsizei height,
8874 GLint border,
8875 GLenum format,
8876 GLenum type)
8877 {
8878 if (!context->getExtensions().textureExternalUpdateANGLE)
8879 {
8880 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8881 return false;
8882 }
8883
8884 if (!ValidTexture2DDestinationTarget(context, target) &&
8885 !ValidTextureExternalTarget(context, target))
8886 {
8887 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8888 return false;
8889 }
8890
8891 if (context->getClientMajorVersion() <= 2)
8892 {
8893 if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
8894 false, false, 0, 0, width, height, border, format,
8895 type, -1, nullptr))
8896 {
8897 return false;
8898 }
8899 }
8900 else
8901 {
8902 if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat,
8903 false, false, 0, 0, 0, width, height, 1, border,
8904 format, type, -1, nullptr))
8905 {
8906 return false;
8907 }
8908 }
8909
8910 return true;
8911 }
8912
ValidateInvalidateTextureANGLE(const Context * context,angle::EntryPoint entryPoint,TextureType target)8913 bool ValidateInvalidateTextureANGLE(const Context *context,
8914 angle::EntryPoint entryPoint,
8915 TextureType target)
8916 {
8917 if (!context->getExtensions().textureExternalUpdateANGLE)
8918 {
8919 ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
8920 return false;
8921 }
8922
8923 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
8924 {
8925 ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
8926 return false;
8927 }
8928
8929 return true;
8930 }
8931
ValidateProgramExecutableXFBBuffersPresent(const Context * context,const ProgramExecutable * programExecutable)8932 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
8933 const ProgramExecutable *programExecutable)
8934 {
8935 size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
8936 const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
8937 for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
8938 {
8939 const OffsetBindingPointer<Buffer> &buffer =
8940 transformFeedback->getIndexedBuffer(programXfbIndex);
8941 if (!buffer.get())
8942 {
8943 return false;
8944 }
8945 }
8946
8947 return true;
8948 }
8949
ValidateLogicOpCommon(const PrivateState & state,ErrorSet * errors,angle::EntryPoint entryPoint,LogicalOperation opcodePacked)8950 bool ValidateLogicOpCommon(const PrivateState &state,
8951 ErrorSet *errors,
8952 angle::EntryPoint entryPoint,
8953 LogicalOperation opcodePacked)
8954 {
8955 switch (opcodePacked)
8956 {
8957 case LogicalOperation::And:
8958 case LogicalOperation::AndInverted:
8959 case LogicalOperation::AndReverse:
8960 case LogicalOperation::Clear:
8961 case LogicalOperation::Copy:
8962 case LogicalOperation::CopyInverted:
8963 case LogicalOperation::Equiv:
8964 case LogicalOperation::Invert:
8965 case LogicalOperation::Nand:
8966 case LogicalOperation::Noop:
8967 case LogicalOperation::Nor:
8968 case LogicalOperation::Or:
8969 case LogicalOperation::OrInverted:
8970 case LogicalOperation::OrReverse:
8971 case LogicalOperation::Set:
8972 case LogicalOperation::Xor:
8973 return true;
8974 default:
8975 errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp);
8976 return false;
8977 }
8978 }
8979 } // namespace gl
8980