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