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