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