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