blob: 2a0b4a2ed8330f129afa76995ef99d9b866abcc3 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// 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
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madill16e28fd2018-09-12 11:03:05 -040082bool ValidateDrawAttribsImpl(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040083{
Jamie Madill51af38b2018-04-15 08:50:56 -040084 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040085 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040086
Jamie Madill88602e62018-08-08 12:49:30 -040087 // An overflow can happen when adding the offset. Check against a special constant.
88 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
89 VertexAttribute::kIntegerOverflow ||
90 context->getStateCache().getInstancedVertexElementLimit() ==
91 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040092 {
93 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
94 return false;
95 }
96
97 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
98 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
100 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400101}
102
Jamie Madill16e28fd2018-09-12 11:03:05 -0400103ANGLE_INLINE bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
104{
105 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
106 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
107 {
108 return true;
109 }
110 else
111 {
112 return ValidateDrawAttribsImpl(context, primcount, maxVertex);
113 }
114}
115
Jamie Madill5b772312018-03-08 20:28:32 -0500116bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400117{
118 switch (type)
119 {
120 // Types referenced in Table 3.4 of the ES 2.0.25 spec
121 case GL_UNSIGNED_BYTE:
122 case GL_UNSIGNED_SHORT_4_4_4_4:
123 case GL_UNSIGNED_SHORT_5_5_5_1:
124 case GL_UNSIGNED_SHORT_5_6_5:
125 return context->getClientVersion() >= ES_2_0;
126
127 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
128 case GL_BYTE:
129 case GL_INT:
130 case GL_SHORT:
131 case GL_UNSIGNED_INT:
132 case GL_UNSIGNED_INT_10F_11F_11F_REV:
133 case GL_UNSIGNED_INT_24_8:
134 case GL_UNSIGNED_INT_2_10_10_10_REV:
135 case GL_UNSIGNED_INT_5_9_9_9_REV:
136 case GL_UNSIGNED_SHORT:
137 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
138 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
139 return context->getClientVersion() >= ES_3_0;
140
141 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400142 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
143 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400144
145 case GL_HALF_FLOAT:
146 return context->getClientVersion() >= ES_3_0 ||
147 context->getExtensions().textureHalfFloat;
148
149 case GL_HALF_FLOAT_OES:
150 return context->getExtensions().colorBufferHalfFloat;
151
152 default:
153 return false;
154 }
155}
156
Jamie Madill5b772312018-03-08 20:28:32 -0500157bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400158{
159 switch (format)
160 {
161 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
162 case GL_RGBA:
163 case GL_RGB:
164 case GL_ALPHA:
165 return context->getClientVersion() >= ES_2_0;
166
167 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
168 case GL_RG:
169 case GL_RED:
170 case GL_RGBA_INTEGER:
171 case GL_RGB_INTEGER:
172 case GL_RG_INTEGER:
173 case GL_RED_INTEGER:
174 return context->getClientVersion() >= ES_3_0;
175
176 case GL_SRGB_ALPHA_EXT:
177 case GL_SRGB_EXT:
178 return context->getExtensions().sRGB;
179
180 case GL_BGRA_EXT:
181 return context->getExtensions().readFormatBGRA;
182
183 default:
184 return false;
185 }
186}
187
Jamie Madill5b772312018-03-08 20:28:32 -0500188bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400189 GLenum framebufferComponentType,
190 GLenum format,
191 GLenum type)
192{
193 switch (framebufferComponentType)
194 {
195 case GL_UNSIGNED_NORMALIZED:
196 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
197 // ReadPixels with BGRA even if the extension is not present
198 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
199 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
200 type == GL_UNSIGNED_BYTE);
201
202 case GL_SIGNED_NORMALIZED:
203 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
204
205 case GL_INT:
206 return (format == GL_RGBA_INTEGER && type == GL_INT);
207
208 case GL_UNSIGNED_INT:
209 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
210
211 case GL_FLOAT:
212 return (format == GL_RGBA && type == GL_FLOAT);
213
214 default:
215 UNREACHABLE();
216 return false;
217 }
218}
219
Geoff Langc1984ed2016-10-07 12:41:00 -0400220template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400221bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400222{
223 switch (ConvertToGLenum(params[0]))
224 {
225 case GL_CLAMP_TO_EDGE:
226 break;
227
228 case GL_REPEAT:
229 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400230 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400231 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400232 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400234 return false;
235 }
236 break;
237
238 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400240 return false;
241 }
242
243 return true;
244}
245
246template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400247bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400248{
249 switch (ConvertToGLenum(params[0]))
250 {
251 case GL_NEAREST:
252 case GL_LINEAR:
253 break;
254
255 case GL_NEAREST_MIPMAP_NEAREST:
256 case GL_LINEAR_MIPMAP_NEAREST:
257 case GL_NEAREST_MIPMAP_LINEAR:
258 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400259 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400260 {
261 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400263 return false;
264 }
265 break;
266
267 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700268 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400269 return false;
270 }
271
272 return true;
273}
274
275template <typename ParamType>
276bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
277{
278 switch (ConvertToGLenum(params[0]))
279 {
280 case GL_NEAREST:
281 case GL_LINEAR:
282 break;
283
284 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400286 return false;
287 }
288
289 return true;
290}
291
292template <typename ParamType>
293bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
294{
295 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
296 switch (ConvertToGLenum(params[0]))
297 {
298 case GL_NONE:
299 case GL_COMPARE_REF_TO_TEXTURE:
300 break;
301
302 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700303 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400304 return false;
305 }
306
307 return true;
308}
309
310template <typename ParamType>
311bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
312{
313 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_LEQUAL:
317 case GL_GEQUAL:
318 case GL_LESS:
319 case GL_GREATER:
320 case GL_EQUAL:
321 case GL_NOTEQUAL:
322 case GL_ALWAYS:
323 case GL_NEVER:
324 break;
325
326 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700327 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400328 return false;
329 }
330
331 return true;
332}
333
334template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700335bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
336{
337 if (!context->getExtensions().textureSRGBDecode)
338 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700340 return false;
341 }
342
343 switch (ConvertToGLenum(params[0]))
344 {
345 case GL_DECODE_EXT:
346 case GL_SKIP_DECODE_EXT:
347 break;
348
349 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700351 return false;
352 }
353
354 return true;
355}
356
Luc Ferron1b1a8642018-01-23 15:12:01 -0500357bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
358{
359 if (!context->getExtensions().textureFilterAnisotropic)
360 {
361 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
362 return false;
363 }
364
365 return true;
366}
367
368bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
369{
370 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
371 {
372 return false;
373 }
374
375 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
376
377 if (paramValue < 1 || paramValue > largest)
378 {
379 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
380 return false;
381 }
382
383 return true;
384}
385
Jamie Madill5b772312018-03-08 20:28:32 -0500386bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400387{
Jamie Madill44a6fbf2018-10-02 13:38:56 -0400388 const Program *program = context->getGLState().getLinkedProgram();
Geoff Lange0cff192017-05-30 13:04:56 -0400389 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
390
Jamie Madille7d80f32018-08-08 15:49:23 -0400391 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
392 framebuffer->getDrawBufferTypeMask().to_ulong(),
393 program->getActiveOutputVariables().to_ulong(),
394 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400395}
396
Jamie Madill5b772312018-03-08 20:28:32 -0500397bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400398{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700399 const auto &glState = context->getGLState();
Jamie Madill44a6fbf2018-10-02 13:38:56 -0400400 const Program *program = context->getGLState().getLinkedProgram();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400401 const VertexArray *vao = context->getGLState().getVertexArray();
402
Brandon Jonesc405ae72017-12-06 14:15:03 -0800403 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
404 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
405 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
406
407 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
408 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
409 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
410
Jamie Madille7d80f32018-08-08 15:49:23 -0400411 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
412 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
413 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400414}
415
Jamie Madill493f9572018-05-24 19:52:15 -0400416bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
417 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800418{
419 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400420 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800421 {
Jamie Madill493f9572018-05-24 19:52:15 -0400422 case PrimitiveMode::Points:
423 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
424 case PrimitiveMode::Lines:
425 case PrimitiveMode::LineStrip:
426 case PrimitiveMode::LineLoop:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
428 case PrimitiveMode::LinesAdjacency:
429 case PrimitiveMode::LineStripAdjacency:
430 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
431 case PrimitiveMode::Triangles:
432 case PrimitiveMode::TriangleFan:
433 case PrimitiveMode::TriangleStrip:
434 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
435 case PrimitiveMode::TrianglesAdjacency:
436 case PrimitiveMode::TriangleStripAdjacency:
437 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800438 default:
439 UNREACHABLE();
440 return false;
441 }
442}
443
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700444// GLES1 texture parameters are a small subset of the others
445bool IsValidGLES1TextureParameter(GLenum pname)
446{
447 switch (pname)
448 {
449 case GL_TEXTURE_MAG_FILTER:
450 case GL_TEXTURE_MIN_FILTER:
451 case GL_TEXTURE_WRAP_S:
452 case GL_TEXTURE_WRAP_T:
453 case GL_TEXTURE_WRAP_R:
454 case GL_GENERATE_MIPMAP:
455 case GL_TEXTURE_CROP_RECT_OES:
456 return true;
457 default:
458 return false;
459 }
460}
Geoff Langf41a7152016-09-19 15:11:17 -0400461} // anonymous namespace
462
Brandon Jonesd1049182018-03-28 10:02:20 -0700463void SetRobustLengthParam(GLsizei *length, GLsizei value)
464{
465 if (length)
466 {
467 *length = value;
468 }
469}
470
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500471bool IsETC2EACFormat(const GLenum format)
472{
473 // ES 3.1, Table 8.19
474 switch (format)
475 {
476 case GL_COMPRESSED_R11_EAC:
477 case GL_COMPRESSED_SIGNED_R11_EAC:
478 case GL_COMPRESSED_RG11_EAC:
479 case GL_COMPRESSED_SIGNED_RG11_EAC:
480 case GL_COMPRESSED_RGB8_ETC2:
481 case GL_COMPRESSED_SRGB8_ETC2:
482 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
483 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
484 case GL_COMPRESSED_RGBA8_ETC2_EAC:
485 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
486 return true;
487
488 default:
489 return false;
490 }
491}
492
Jamie Madill5b772312018-03-08 20:28:32 -0500493bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400494{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800495 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400496 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800497 case TextureType::_2D:
498 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800499 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400500
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400502 return context->getExtensions().textureRectangle;
503
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800504 case TextureType::_3D:
505 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800506 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500507
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800508 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800509 return (context->getClientVersion() >= Version(3, 1));
Olli Etuahod310a432018-08-24 15:40:23 +0300510 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300511 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400512
He Yunchaoced53ae2016-11-29 15:00:51 +0800513 default:
514 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500515 }
Jamie Madill35d15012013-10-07 10:46:37 -0400516}
517
Jamie Madill5b772312018-03-08 20:28:32 -0500518bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500519{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800520 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500521 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800522 case TextureType::_2D:
523 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500524 return true;
525
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400527 return context->getExtensions().textureRectangle;
528
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500529 default:
530 return false;
531 }
532}
533
Jamie Madill5b772312018-03-08 20:28:32 -0500534bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500535{
536 switch (target)
537 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800538 case TextureType::_3D:
539 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300540 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500541
542 default:
543 return false;
544 }
545}
546
Ian Ewellbda75592016-04-18 17:25:54 -0400547// Most texture GL calls are not compatible with external textures, so we have a separate validation
548// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500549bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400550{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800551 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400552 (context->getExtensions().eglImageExternal ||
553 context->getExtensions().eglStreamConsumerExternal);
554}
555
Shannon Woods4dfed832014-03-17 20:03:39 -0400556// This function differs from ValidTextureTarget in that the target must be
557// usable as the destination of a 2D operation-- so a cube face is valid, but
558// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400559// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500560bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400561{
562 switch (target)
563 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800564 case TextureTarget::_2D:
565 case TextureTarget::CubeMapNegativeX:
566 case TextureTarget::CubeMapNegativeY:
567 case TextureTarget::CubeMapNegativeZ:
568 case TextureTarget::CubeMapPositiveX:
569 case TextureTarget::CubeMapPositiveY:
570 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800571 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400573 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800574 default:
575 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500576 }
577}
578
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800579bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400580 PrimitiveMode transformFeedbackPrimitiveMode,
581 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800582{
583 ASSERT(context);
584
585 if (!context->getExtensions().geometryShader)
586 {
587 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
588 // that does not match the current transform feedback object's draw mode (if transform
589 // feedback is active), (3.0.2, section 2.14, pg 86)
590 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
591 }
592
593 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400594 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800595 {
Jamie Madill493f9572018-05-24 19:52:15 -0400596 case PrimitiveMode::Points:
597 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
598 case PrimitiveMode::Lines:
599 case PrimitiveMode::LineStrip:
600 case PrimitiveMode::LineLoop:
601 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
602 case PrimitiveMode::Triangles:
603 case PrimitiveMode::TriangleFan:
604 case PrimitiveMode::TriangleStrip:
605 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800606 default:
607 UNREACHABLE();
608 return false;
609 }
610}
611
Jamie Madill5b772312018-03-08 20:28:32 -0500612bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400613 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400614 GLsizei count,
615 GLenum type,
616 const GLvoid *indices,
617 GLsizei primcount)
618{
619 if (primcount < 0)
620 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700621 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400622 return false;
623 }
624
625 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
626 {
627 return false;
628 }
629
Jamie Madill9fdaa492018-02-16 10:52:11 -0500630 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400631}
632
633bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400634 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 GLint first,
636 GLsizei count,
637 GLsizei primcount)
638{
639 if (primcount < 0)
640 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400642 return false;
643 }
644
645 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
646 {
647 return false;
648 }
649
Jamie Madill9fdaa492018-02-16 10:52:11 -0500650 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400651}
652
Jamie Madill5b772312018-03-08 20:28:32 -0500653bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400654{
655 // Verify there is at least one active attribute with a divisor of zero
656 const State &state = context->getGLState();
657
Jamie Madill44a6fbf2018-10-02 13:38:56 -0400658 Program *program = state.getLinkedProgram();
Jamie Madillbe849e42017-05-02 15:49:00 -0400659
660 const auto &attribs = state.getVertexArray()->getVertexAttributes();
661 const auto &bindings = state.getVertexArray()->getVertexBindings();
662 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
663 {
664 const VertexAttribute &attrib = attribs[attributeIndex];
665 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300666 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400667 {
668 return true;
669 }
670 }
671
Brandon Jonesafa75152017-07-21 13:11:29 -0700672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400673 return false;
674}
675
Jamie Madill5b772312018-03-08 20:28:32 -0500676bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500677{
678 switch (target)
679 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800680 case TextureType::_3D:
681 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800682 return true;
683 default:
684 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400685 }
686}
687
Jamie Madill5b772312018-03-08 20:28:32 -0500688bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800689{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800690 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800691 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800692 case TextureType::_2D:
693 case TextureType::_2DArray:
694 case TextureType::_2DMultisample:
695 case TextureType::CubeMap:
696 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800697 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800698 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400699 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300700 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300701 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800702 default:
703 return false;
704 }
705}
706
Jamie Madill5b772312018-03-08 20:28:32 -0500707bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500708{
He Yunchaoced53ae2016-11-29 15:00:51 +0800709 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
710 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400711 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500712
713 switch (target)
714 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800715 case GL_FRAMEBUFFER:
716 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400717
He Yunchaoced53ae2016-11-29 15:00:51 +0800718 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800719 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400720 return (context->getExtensions().framebufferBlit ||
721 context->getClientMajorVersion() >= 3);
722
He Yunchaoced53ae2016-11-29 15:00:51 +0800723 default:
724 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500725 }
726}
727
Jamie Madill5b772312018-03-08 20:28:32 -0500728bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400729{
Jamie Madillc29968b2016-01-20 11:17:23 -0500730 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400731 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800732 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400733 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800734 case TextureType::_2D:
735 case TextureType::_2DArray:
736 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300737 case TextureType::_2DMultisampleArray:
738 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
739 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500740 maxDimension = caps.max2DTextureSize;
741 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800742 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 maxDimension = caps.maxCubeMapTextureSize;
744 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800745 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400746 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800747 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800748 maxDimension = caps.max3DTextureSize;
749 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800750 default:
751 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400752 }
753
Jamie Madill43da7c42018-08-01 11:34:49 -0400754 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400755}
756
Jamie Madill5b772312018-03-08 20:28:32 -0500757bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800758 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700759 GLint level,
760 GLsizei width,
761 GLsizei height,
762 GLsizei depth,
763 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400764{
Brandon Jones6cad5662017-06-14 13:25:13 -0700765 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400766 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700767 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400768 return false;
769 }
Austin Kinross08528e12015-10-07 16:24:40 -0700770 // TexSubImage parameters can be NPOT without textureNPOT extension,
771 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500772 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500773 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500774 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400775 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400776 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700777 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400778 return false;
779 }
780
781 if (!ValidMipLevel(context, target, level))
782 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700783 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400784 return false;
785 }
786
787 return true;
788}
789
Geoff Lang966c9402017-04-18 12:38:27 -0400790bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
791{
792 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
793 (size % blockSize == 0);
794}
795
Jamie Madill5b772312018-03-08 20:28:32 -0500796bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500797 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400798 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500799 GLsizei width,
800 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400801{
Jamie Madill43da7c42018-08-01 11:34:49 -0400802 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400803 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400804 {
805 return false;
806 }
807
Geoff Lang966c9402017-04-18 12:38:27 -0400808 if (width < 0 || height < 0)
809 {
810 return false;
811 }
812
813 if (CompressedTextureFormatRequiresExactSize(internalFormat))
814 {
815 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
816 // block size for level 0 but WebGL disallows this.
817 bool smallerThanBlockSizeAllowed =
818 level > 0 || !context->getExtensions().webglCompatibility;
819
820 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
821 smallerThanBlockSizeAllowed) ||
822 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
823 smallerThanBlockSizeAllowed))
824 {
825 return false;
826 }
827 }
828
829 return true;
830}
831
Jamie Madill5b772312018-03-08 20:28:32 -0500832bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400833 GLenum internalFormat,
834 GLint xoffset,
835 GLint yoffset,
836 GLsizei width,
837 GLsizei height,
838 size_t textureWidth,
839 size_t textureHeight)
840{
Jamie Madill43da7c42018-08-01 11:34:49 -0400841 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400842 if (!formatInfo.compressed)
843 {
844 return false;
845 }
846
Geoff Lang44ff5a72017-02-03 15:15:43 -0500847 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400848 {
849 return false;
850 }
851
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500852 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400853 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500854 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400855 yoffset % formatInfo.compressedBlockHeight != 0)
856 {
857 return false;
858 }
859
860 // Allowed to either have data that is a multiple of block size or is smaller than the block
861 // size but fills the entire mip
862 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
863 static_cast<size_t>(width) == textureWidth &&
864 static_cast<size_t>(height) == textureHeight;
865 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
866 (height % formatInfo.compressedBlockHeight) == 0;
867 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400868 {
869 return false;
870 }
871 }
872
Geoff Langd4f180b2013-09-24 13:57:44 -0400873 return true;
874}
875
Jamie Madill5b772312018-03-08 20:28:32 -0500876bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800877 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400878 GLsizei width,
879 GLsizei height,
880 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400881 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400882 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400883 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 GLsizei imageSize)
885{
Jamie Madill43da7c42018-08-01 11:34:49 -0400886 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400887 if (pixelUnpackBuffer == nullptr && imageSize < 0)
888 {
889 // Checks are not required
890 return true;
891 }
892
893 // ...the data would be unpacked from the buffer object such that the memory reads required
894 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400895 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400896 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400897 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400898 const auto &unpack = context->getGLState().getUnpackState();
899
Jamie Madill7f232932018-09-12 11:03:06 -0400900 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
901 GLuint endByte = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400902 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 return false;
906 }
907
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 if (pixelUnpackBuffer)
909 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400910 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400911 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
912 checkedEndByte += checkedOffset;
913
914 if (!checkedEndByte.IsValid() ||
915 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
916 {
917 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400919 return false;
920 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800921 if (context->getExtensions().webglCompatibility &&
922 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
923 {
924 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
925 PixelUnpackBufferBoundForTransformFeedback);
926 return false;
927 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 }
929 else
930 {
931 ASSERT(imageSize >= 0);
932 if (pixels == nullptr && imageSize != 0)
933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500934 context->handleError(InvalidOperation()
935 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400936 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 }
938
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400939 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400942 return false;
943 }
944 }
945
946 return true;
947}
948
Corentin Wallezad3ae902018-03-09 13:40:42 -0500949bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500950{
Geoff Lang37dde692014-01-31 16:34:54 -0500951 switch (queryType)
952 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500953 case QueryType::AnySamples:
954 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400955 return context->getClientMajorVersion() >= 3 ||
956 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500957 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800958 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500959 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500961 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500963 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800964 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800965 default:
966 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500967 }
968}
969
Jamie Madill5b772312018-03-08 20:28:32 -0500970bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400971 GLenum type,
972 GLboolean normalized,
973 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400974 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400975 bool pureInteger)
976{
977 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400978 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
979 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
980 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
981 // parameter exceeds 255.
982 constexpr GLsizei kMaxWebGLStride = 255;
983 if (stride > kMaxWebGLStride)
984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500985 context->handleError(InvalidValue()
986 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400987 return false;
988 }
989
990 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
991 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
992 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
993 // or an INVALID_OPERATION error is generated.
994 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
995 size_t typeSize = GetVertexFormatTypeSize(internalType);
996
997 ASSERT(isPow2(typeSize) && typeSize > 0);
998 size_t sizeMask = (typeSize - 1);
999 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001002 return false;
1003 }
1004
1005 if ((stride & sizeMask) != 0)
1006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001008 return false;
1009 }
1010
1011 return true;
1012}
1013
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001014Program *GetValidProgramNoResolve(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001015{
He Yunchaoced53ae2016-11-29 15:00:51 +08001016 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1017 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1018 // or program object and INVALID_OPERATION if the provided name identifies an object
1019 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001020
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001021 Program *validProgram = context->getProgramNoResolveLink(id);
Dian Xiang769769a2015-09-09 15:20:08 -07001022
1023 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001024 {
Dian Xiang769769a2015-09-09 15:20:08 -07001025 if (context->getShader(id))
1026 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001028 }
1029 else
1030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001031 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001032 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001033 }
Dian Xiang769769a2015-09-09 15:20:08 -07001034
1035 return validProgram;
1036}
1037
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001038Program *GetValidProgram(Context *context, GLuint id)
1039{
1040 Program *program = GetValidProgramNoResolve(context, id);
1041 if (program)
1042 {
1043 program->resolveLink();
1044 }
1045 return program;
1046}
1047
Jamie Madill5b772312018-03-08 20:28:32 -05001048Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001049{
1050 // See ValidProgram for spec details.
1051
1052 Shader *validShader = context->getShader(id);
1053
1054 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001055 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04001056 if (context->getProgramNoResolveLink(id))
Dian Xiang769769a2015-09-09 15:20:08 -07001057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001059 }
1060 else
1061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001062 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001063 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001064 }
Dian Xiang769769a2015-09-09 15:20:08 -07001065
1066 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001067}
1068
Jamie Madill43da7c42018-08-01 11:34:49 -04001069bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001070{
Geoff Langfa125c92017-10-24 13:01:46 -04001071 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001072 {
Geoff Langfa125c92017-10-24 13:01:46 -04001073 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1074 {
1075 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1076 return false;
1077 }
Jamie Madillb4472272014-07-03 10:38:55 -04001078
Geoff Langfa125c92017-10-24 13:01:46 -04001079 // Color attachment 0 is validated below because it is always valid
1080 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001081 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001082 {
Geoff Langfa125c92017-10-24 13:01:46 -04001083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001084 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001085 }
1086 }
1087 else
1088 {
1089 switch (attachment)
1090 {
Geoff Langfa125c92017-10-24 13:01:46 -04001091 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001092 case GL_DEPTH_ATTACHMENT:
1093 case GL_STENCIL_ATTACHMENT:
1094 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001095
He Yunchaoced53ae2016-11-29 15:00:51 +08001096 case GL_DEPTH_STENCIL_ATTACHMENT:
1097 if (!context->getExtensions().webglCompatibility &&
1098 context->getClientMajorVersion() < 3)
1099 {
Geoff Langfa125c92017-10-24 13:01:46 -04001100 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 return false;
1102 }
1103 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001104
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001108 }
1109 }
1110
1111 return true;
1112}
1113
Jamie Madill5b772312018-03-08 20:28:32 -05001114bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001115 GLenum target,
1116 GLsizei samples,
1117 GLenum internalformat,
1118 GLsizei width,
1119 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120{
1121 switch (target)
1122 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001123 case GL_RENDERBUFFER:
1124 break;
1125 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001128 }
1129
1130 if (width < 0 || height < 0 || samples < 0)
1131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001132 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001133 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 }
1135
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001136 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1137 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1138
1139 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001140 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001143 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 }
1145
1146 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1147 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001148 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001149 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001150 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 }
1155
Geoff Langaae65a42014-05-26 12:43:44 -04001156 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001158 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001159 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 }
1161
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001162 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 if (handle == 0)
1164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
1169 return true;
1170}
1171
Jamie Madill43da7c42018-08-01 11:34:49 -04001172bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001173 GLenum target,
1174 GLenum attachment,
1175 GLenum renderbuffertarget,
1176 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001177{
Geoff Lange8afa902017-09-27 15:00:43 -04001178 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001180 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001182 }
1183
Jamie Madill43da7c42018-08-01 11:34:49 -04001184 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001185
Jamie Madill84115c92015-04-23 15:00:07 -04001186 ASSERT(framebuffer);
1187 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001190 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001191 }
1192
Jamie Madillb4472272014-07-03 10:38:55 -04001193 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001194 {
Jamie Madillb4472272014-07-03 10:38:55 -04001195 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196 }
1197
Jamie Madillab9d82c2014-01-21 16:38:14 -05001198 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1199 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1200 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1201 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1202 if (renderbuffer != 0)
1203 {
1204 if (!context->getRenderbuffer(renderbuffer))
1205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001207 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001208 }
1209 }
1210
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001211 return true;
1212}
1213
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001214bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001215 GLint srcX0,
1216 GLint srcY0,
1217 GLint srcX1,
1218 GLint srcY1,
1219 GLint dstX0,
1220 GLint dstY0,
1221 GLint dstX1,
1222 GLint dstY1,
1223 GLbitfield mask,
1224 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225{
1226 switch (filter)
1227 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001228 case GL_NEAREST:
1229 break;
1230 case GL_LINEAR:
1231 break;
1232 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
1237 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1238 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001239 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 }
1242
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1244 // color buffer, leaving only nearest being unfiltered from above
1245 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1246 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
Jamie Madill7f232932018-09-12 11:03:06 -04001251 const auto &glState = context->getGLState();
1252 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1253 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001254
1255 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001257 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 }
1260
Jamie Madill427064d2018-04-13 16:20:34 -04001261 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001262 {
Jamie Madill48faf802014-11-06 15:27:22 -05001263 return false;
1264 }
1265
Jamie Madill427064d2018-04-13 16:20:34 -04001266 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001267 {
Jamie Madill48faf802014-11-06 15:27:22 -05001268 return false;
1269 }
1270
Qin Jiajiaaef92162018-02-27 13:51:44 +08001271 if (readFramebuffer->id() == drawFramebuffer->id())
1272 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001274 return false;
1275 }
1276
Jamie Madille98b1b52018-03-08 09:47:23 -05001277 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Geoff Langb1196682014-07-23 13:47:29 -04001279 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 }
1281
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001282 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1283 // always run it in order to avoid triggering driver bugs.
1284 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1285 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001286 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001287 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1288 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001289 }
1290
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1292
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 if (mask & GL_COLOR_BUFFER_BIT)
1294 {
Jamie Madill7f232932018-09-12 11:03:06 -04001295 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1296 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297
He Yunchao66a41a22016-12-15 16:45:05 +08001298 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001300 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301
Geoff Langa15472a2015-08-11 11:48:03 -04001302 for (size_t drawbufferIdx = 0;
1303 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 {
Geoff Langa15472a2015-08-11 11:48:03 -04001305 const FramebufferAttachment *attachment =
1306 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1307 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001309 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310
Geoff Langb2f3d052013-08-13 12:49:27 -04001311 // The GL ES 3.0.2 spec (pg 193) states that:
1312 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001313 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1314 // as well
1315 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1316 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001317 // Changes with EXT_color_buffer_float:
1318 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001319 GLenum readComponentType = readFormat.info->componentType;
1320 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001321 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001322 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001323 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001324 drawComponentType == GL_SIGNED_NORMALIZED);
1325
1326 if (extensions.colorBufferFloat)
1327 {
1328 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1329 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1330
1331 if (readFixedOrFloat != drawFixedOrFloat)
1332 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001333 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1334 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001335 return false;
1336 }
1337 }
1338 else if (readFixedPoint != drawFixedPoint)
1339 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001340 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1341 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001342 return false;
1343 }
1344
1345 if (readComponentType == GL_UNSIGNED_INT &&
1346 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001348 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1349 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
1352
Jamie Madill6163c752015-12-07 16:32:59 -05001353 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001355 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1356 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 }
1359
Jamie Madilla3944d42016-07-22 22:13:26 -04001360 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001361 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001363 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1364 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
Geoff Lange4915782017-04-12 15:19:07 -04001367
1368 if (context->getExtensions().webglCompatibility &&
1369 *readColorBuffer == *attachment)
1370 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001372 return false;
1373 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
1375 }
1376
Jamie Madilla3944d42016-07-22 22:13:26 -04001377 if ((readFormat.info->componentType == GL_INT ||
1378 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1379 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001381 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
He Yunchao66a41a22016-12-15 16:45:05 +08001385 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1386 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1387 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1388 // situation is an application error that would lead to a crash in ANGLE.
1389 else if (drawFramebuffer->hasEnabledDrawBuffer())
1390 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001391 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001392 return false;
1393 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 }
1395
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001397 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1398 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001400 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001402 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001403 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001404 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001405 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001407 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 {
Kenneth Russell69382852017-07-21 16:38:44 -04001409 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001411 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1412 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001416 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001418 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1419 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
Geoff Lange4915782017-04-12 15:19:07 -04001422
1423 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1424 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001426 return false;
1427 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 }
He Yunchao66a41a22016-12-15 16:45:05 +08001429 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1430 else if (drawBuffer)
1431 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001433 return false;
1434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
1436 }
1437
Martin Radeva3ed4572017-07-27 18:29:37 +03001438 // ANGLE_multiview, Revision 1:
1439 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001440 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1441 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1442 // views in the current read framebuffer is more than one.
1443 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001444 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001445 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001446 return false;
1447 }
1448 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1449 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001450 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001451 return false;
1452 }
1453
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 return true;
1455}
1456
Jamie Madill4928b7c2017-06-20 12:57:39 -04001457bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001458 GLint x,
1459 GLint y,
1460 GLsizei width,
1461 GLsizei height,
1462 GLenum format,
1463 GLenum type,
1464 GLsizei bufSize,
1465 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001466 GLsizei *columns,
1467 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001468 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001469{
1470 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 return false;
1473 }
1474
Brandon Jonesd1049182018-03-28 10:02:20 -07001475 GLsizei writeLength = 0;
1476 GLsizei writeColumns = 0;
1477 GLsizei writeRows = 0;
1478
1479 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1480 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001481 {
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001483 }
1484
Brandon Jonesd1049182018-03-28 10:02:20 -07001485 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001486 {
Geoff Langb1196682014-07-23 13:47:29 -04001487 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001488 }
1489
Brandon Jonesd1049182018-03-28 10:02:20 -07001490 SetRobustLengthParam(length, writeLength);
1491 SetRobustLengthParam(columns, writeColumns);
1492 SetRobustLengthParam(rows, writeRows);
1493
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return true;
1495}
1496
1497bool ValidateReadnPixelsEXT(Context *context,
1498 GLint x,
1499 GLint y,
1500 GLsizei width,
1501 GLsizei height,
1502 GLenum format,
1503 GLenum type,
1504 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001505 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001506{
1507 if (bufSize < 0)
1508 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001509 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001510 return false;
1511 }
1512
Geoff Lang62fce5b2016-09-30 10:46:35 -04001513 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001514 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001515}
Jamie Madill26e91952014-03-05 15:01:27 -05001516
Jamie Madill4928b7c2017-06-20 12:57:39 -04001517bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 GLint x,
1519 GLint y,
1520 GLsizei width,
1521 GLsizei height,
1522 GLenum format,
1523 GLenum type,
1524 GLsizei bufSize,
1525 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001526 GLsizei *columns,
1527 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001528 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529{
Brandon Jonesd1049182018-03-28 10:02:20 -07001530 GLsizei writeLength = 0;
1531 GLsizei writeColumns = 0;
1532 GLsizei writeRows = 0;
1533
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001535 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001536 return false;
1537 }
1538
Brandon Jonesd1049182018-03-28 10:02:20 -07001539 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1540 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001541 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001542 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001543 }
1544
Brandon Jonesd1049182018-03-28 10:02:20 -07001545 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001546 {
1547 return false;
1548 }
1549
Brandon Jonesd1049182018-03-28 10:02:20 -07001550 SetRobustLengthParam(length, writeLength);
1551 SetRobustLengthParam(columns, writeColumns);
1552 SetRobustLengthParam(rows, writeRows);
1553
Geoff Lang62fce5b2016-09-30 10:46:35 -04001554 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001555}
1556
Jamie Madill43da7c42018-08-01 11:34:49 -04001557bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001558{
1559 if (!context->getExtensions().occlusionQueryBoolean &&
1560 !context->getExtensions().disjointTimerQuery)
1561 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001563 return false;
1564 }
1565
Olli Etuaho41997e72016-03-10 13:38:39 +02001566 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001567}
1568
Jamie Madill43da7c42018-08-01 11:34:49 -04001569bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001570{
1571 if (!context->getExtensions().occlusionQueryBoolean &&
1572 !context->getExtensions().disjointTimerQuery)
1573 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575 return false;
1576 }
1577
Olli Etuaho41997e72016-03-10 13:38:39 +02001578 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579}
1580
Jamie Madill43da7c42018-08-01 11:34:49 -04001581bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001582{
1583 if (!context->getExtensions().occlusionQueryBoolean &&
1584 !context->getExtensions().disjointTimerQuery)
1585 {
1586 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1587 return false;
1588 }
1589
1590 return true;
1591}
1592
Jamie Madill43da7c42018-08-01 11:34:49 -04001593bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001594{
1595 if (!ValidQueryType(context, target))
1596 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001597 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001598 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599 }
1600
1601 if (id == 0)
1602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001603 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001604 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001605 }
1606
1607 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1608 // of zero, if the active query object name for <target> is non-zero (for the
1609 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1610 // the active query for either target is non-zero), if <id> is the name of an
1611 // existing query object whose type does not match <target>, or if <id> is the
1612 // active query object name for any query type, the error INVALID_OPERATION is
1613 // generated.
1614
1615 // Ensure no other queries are active
1616 // NOTE: If other queries than occlusion are supported, we will need to check
1617 // separately that:
1618 // a) The query ID passed is not the current active query for any target/type
1619 // b) There are no active queries for the requested target (and in the case
1620 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1621 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001622
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001623 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 Query *queryObject = context->getQuery(id, true, target);
1630
1631 // check that name was obtained with glGenQueries
1632 if (!queryObject)
1633 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001635 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001636 }
1637
1638 // check for type mismatch
1639 if (queryObject->getType() != target)
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001642 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001643 }
1644
1645 return true;
1646}
1647
Jamie Madill43da7c42018-08-01 11:34:49 -04001648bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001649{
1650 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001651 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 return false;
1655 }
1656
1657 return ValidateBeginQueryBase(context, target, id);
1658}
1659
Jamie Madill43da7c42018-08-01 11:34:49 -04001660bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001661{
1662 if (!ValidQueryType(context, target))
1663 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001665 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001666 }
1667
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001668 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001669
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001672 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001673 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001674 }
1675
Jamie Madill45c785d2014-05-13 14:09:34 -04001676 return true;
1677}
1678
Jamie Madill43da7c42018-08-01 11:34:49 -04001679bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680{
1681 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001682 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685 return false;
1686 }
1687
1688 return ValidateEndQueryBase(context, target);
1689}
1690
Corentin Wallezad3ae902018-03-09 13:40:42 -05001691bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692{
1693 if (!context->getExtensions().disjointTimerQuery)
1694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001695 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 return false;
1697 }
1698
Corentin Wallezad3ae902018-03-09 13:40:42 -05001699 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001701 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 return false;
1703 }
1704
1705 Query *queryObject = context->getQuery(id, true, target);
1706 if (queryObject == nullptr)
1707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709 return false;
1710 }
1711
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001712 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 return true;
1719}
1720
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722{
Geoff Lang2186c382016-10-14 10:54:54 -04001723 if (numParams)
1724 {
1725 *numParams = 0;
1726 }
1727
Corentin Wallezad3ae902018-03-09 13:40:42 -05001728 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
1734 switch (pname)
1735 {
1736 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001737 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 return false;
1741 }
1742 break;
1743 case GL_QUERY_COUNTER_BITS_EXT:
1744 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001745 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001747 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 return false;
1749 }
1750 break;
1751 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
Geoff Lang2186c382016-10-14 10:54:54 -04001756 if (numParams)
1757 {
1758 // All queries return only one value
1759 *numParams = 1;
1760 }
1761
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001762 return true;
1763}
1764
Corentin Wallezad3ae902018-03-09 13:40:42 -05001765bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766{
1767 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001768 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
Geoff Lang2186c382016-10-14 10:54:54 -04001774 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775}
1776
Geoff Lang2186c382016-10-14 10:54:54 -04001777bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001778 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001779 GLenum pname,
1780 GLsizei bufSize,
1781 GLsizei *length,
1782 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783{
Geoff Lang2186c382016-10-14 10:54:54 -04001784 if (!ValidateRobustEntryPoint(context, bufSize))
1785 {
1786 return false;
1787 }
1788
Brandon Jonesd1049182018-03-28 10:02:20 -07001789 GLsizei numParams = 0;
1790
1791 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001792 {
1793 return false;
1794 }
1795
Brandon Jonesd1049182018-03-28 10:02:20 -07001796 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001797 {
1798 return false;
1799 }
1800
Brandon Jonesd1049182018-03-28 10:02:20 -07001801 SetRobustLengthParam(length, numParams);
1802
Geoff Lang2186c382016-10-14 10:54:54 -04001803 return true;
1804}
1805
1806bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1807{
1808 if (numParams)
1809 {
1810 *numParams = 0;
1811 }
1812
Corentin Wallezad3ae902018-03-09 13:40:42 -05001813 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814
1815 if (!queryObject)
1816 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001817 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818 return false;
1819 }
1820
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001821 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001823 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 return false;
1825 }
1826
1827 switch (pname)
1828 {
1829 case GL_QUERY_RESULT_EXT:
1830 case GL_QUERY_RESULT_AVAILABLE_EXT:
1831 break;
1832
1833 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001834 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 return false;
1836 }
1837
Geoff Lang2186c382016-10-14 10:54:54 -04001838 if (numParams)
1839 {
1840 *numParams = 1;
1841 }
1842
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 return true;
1844}
1845
1846bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1847{
1848 if (!context->getExtensions().disjointTimerQuery)
1849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001850 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001851 return false;
1852 }
Geoff Lang2186c382016-10-14 10:54:54 -04001853 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1854}
1855
1856bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1857 GLuint id,
1858 GLenum pname,
1859 GLsizei bufSize,
1860 GLsizei *length,
1861 GLint *params)
1862{
1863 if (!context->getExtensions().disjointTimerQuery)
1864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001865 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001866 return false;
1867 }
1868
1869 if (!ValidateRobustEntryPoint(context, bufSize))
1870 {
1871 return false;
1872 }
1873
Brandon Jonesd1049182018-03-28 10:02:20 -07001874 GLsizei numParams = 0;
1875
1876 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001877 {
1878 return false;
1879 }
1880
Brandon Jonesd1049182018-03-28 10:02:20 -07001881 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001882 {
1883 return false;
1884 }
1885
Brandon Jonesd1049182018-03-28 10:02:20 -07001886 SetRobustLengthParam(length, numParams);
1887
Geoff Lang2186c382016-10-14 10:54:54 -04001888 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001889}
1890
1891bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1892{
1893 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001894 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001897 return false;
1898 }
Geoff Lang2186c382016-10-14 10:54:54 -04001899 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1900}
1901
1902bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1903 GLuint id,
1904 GLenum pname,
1905 GLsizei bufSize,
1906 GLsizei *length,
1907 GLuint *params)
1908{
1909 if (!context->getExtensions().disjointTimerQuery &&
1910 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001913 return false;
1914 }
1915
1916 if (!ValidateRobustEntryPoint(context, bufSize))
1917 {
1918 return false;
1919 }
1920
Brandon Jonesd1049182018-03-28 10:02:20 -07001921 GLsizei numParams = 0;
1922
1923 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001924 {
1925 return false;
1926 }
1927
Brandon Jonesd1049182018-03-28 10:02:20 -07001928 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001929 {
1930 return false;
1931 }
1932
Brandon Jonesd1049182018-03-28 10:02:20 -07001933 SetRobustLengthParam(length, numParams);
1934
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001936}
1937
1938bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1939{
1940 if (!context->getExtensions().disjointTimerQuery)
1941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001943 return false;
1944 }
Geoff Lang2186c382016-10-14 10:54:54 -04001945 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1946}
1947
1948bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1949 GLuint id,
1950 GLenum pname,
1951 GLsizei bufSize,
1952 GLsizei *length,
1953 GLint64 *params)
1954{
1955 if (!context->getExtensions().disjointTimerQuery)
1956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001958 return false;
1959 }
1960
1961 if (!ValidateRobustEntryPoint(context, bufSize))
1962 {
1963 return false;
1964 }
1965
Brandon Jonesd1049182018-03-28 10:02:20 -07001966 GLsizei numParams = 0;
1967
1968 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001969 {
1970 return false;
1971 }
1972
Brandon Jonesd1049182018-03-28 10:02:20 -07001973 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001974 {
1975 return false;
1976 }
1977
Brandon Jonesd1049182018-03-28 10:02:20 -07001978 SetRobustLengthParam(length, numParams);
1979
Geoff Lang2186c382016-10-14 10:54:54 -04001980 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001981}
1982
1983bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1984{
1985 if (!context->getExtensions().disjointTimerQuery)
1986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001988 return false;
1989 }
Geoff Lang2186c382016-10-14 10:54:54 -04001990 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1991}
1992
1993bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1994 GLuint id,
1995 GLenum pname,
1996 GLsizei bufSize,
1997 GLsizei *length,
1998 GLuint64 *params)
1999{
2000 if (!context->getExtensions().disjointTimerQuery)
2001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002003 return false;
2004 }
2005
2006 if (!ValidateRobustEntryPoint(context, bufSize))
2007 {
2008 return false;
2009 }
2010
Brandon Jonesd1049182018-03-28 10:02:20 -07002011 GLsizei numParams = 0;
2012
2013 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002014 {
2015 return false;
2016 }
2017
Brandon Jonesd1049182018-03-28 10:02:20 -07002018 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002019 {
2020 return false;
2021 }
2022
Brandon Jonesd1049182018-03-28 10:02:20 -07002023 SetRobustLengthParam(length, numParams);
2024
Geoff Lang2186c382016-10-14 10:54:54 -04002025 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026}
2027
Jamie Madill5b772312018-03-08 20:28:32 -05002028bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002029 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002030 GLint location,
2031 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002032 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002033{
Jiajia Qin5451d532017-11-16 17:16:34 +08002034 // TODO(Jiajia): Add image uniform check in future.
2035 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002036 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002037 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002038 return false;
2039 }
2040
Jiajia Qin5451d532017-11-16 17:16:34 +08002041 if (!program)
2042 {
2043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2044 return false;
2045 }
2046
2047 if (!program->isLinked())
2048 {
2049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2050 return false;
2051 }
2052
2053 if (location == -1)
2054 {
2055 // Silently ignore the uniform command
2056 return false;
2057 }
2058
2059 const auto &uniformLocations = program->getUniformLocations();
2060 size_t castedLocation = static_cast<size_t>(location);
2061 if (castedLocation >= uniformLocations.size())
2062 {
2063 context->handleError(InvalidOperation() << "Invalid uniform location");
2064 return false;
2065 }
2066
2067 const auto &uniformLocation = uniformLocations[castedLocation];
2068 if (uniformLocation.ignored)
2069 {
2070 // Silently ignore the uniform command
2071 return false;
2072 }
2073
2074 if (!uniformLocation.used())
2075 {
2076 context->handleError(InvalidOperation());
2077 return false;
2078 }
2079
2080 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2081
2082 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002083 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002084 {
2085 context->handleError(InvalidOperation());
2086 return false;
2087 }
2088
2089 *uniformOut = &uniform;
2090 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002091}
2092
Jamie Madill5b772312018-03-08 20:28:32 -05002093bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002094 GLenum uniformType,
2095 GLsizei count,
2096 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002097{
Jiajia Qin5451d532017-11-16 17:16:34 +08002098 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2099 // It is compatible with INT or BOOL.
2100 // Do these cheap tests first, for a little extra speed.
2101 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002102 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002104 }
2105
Jiajia Qin5451d532017-11-16 17:16:34 +08002106 if (IsSamplerType(uniformType))
2107 {
2108 // Check that the values are in range.
2109 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2110 for (GLsizei i = 0; i < count; ++i)
2111 {
2112 if (value[i] < 0 || value[i] >= max)
2113 {
2114 context->handleError(InvalidValue() << "sampler uniform value out of range");
2115 return false;
2116 }
2117 }
2118 return true;
2119 }
2120
2121 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2122 return false;
2123}
2124
Jamie Madill5b772312018-03-08 20:28:32 -05002125bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002126{
2127 // Check that the value type is compatible with uniform type.
2128 // Do the cheaper test first, for a little extra speed.
2129 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2130 {
2131 return true;
2132 }
2133
2134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2135 return false;
2136}
2137
Jamie Madill5b772312018-03-08 20:28:32 -05002138bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002139{
2140 // Check that the value type is compatible with uniform type.
2141 if (valueType == uniformType)
2142 {
2143 return true;
2144 }
2145
2146 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2147 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002148}
2149
Jamie Madill5b772312018-03-08 20:28:32 -05002150bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002151{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002152 const LinkedUniform *uniform = nullptr;
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002153 Program *programObject = context->getGLState().getLinkedProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002154 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2155 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156}
2157
Jamie Madill5b772312018-03-08 20:28:32 -05002158bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002159{
2160 const LinkedUniform *uniform = nullptr;
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002161 Program *programObject = context->getGLState().getLinkedProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002162 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2163 ValidateUniform1ivValue(context, uniform->type, count, value);
2164}
2165
Jamie Madill5b772312018-03-08 20:28:32 -05002166bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002167 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002168 GLint location,
2169 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002170 GLboolean transpose)
2171{
Geoff Lang92019432017-11-20 13:09:34 -05002172 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002175 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002176 }
2177
Jamie Madill62d31cb2015-09-11 13:25:51 -04002178 const LinkedUniform *uniform = nullptr;
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002179 Program *programObject = context->getGLState().getLinkedProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002180 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2181 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002182}
2183
Jamie Madill5b772312018-03-08 20:28:32 -05002184bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002185{
2186 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002188 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002189 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002190 }
2191
Jamie Madill0af26e12015-03-05 19:54:33 -05002192 const Caps &caps = context->getCaps();
2193
Jamie Madill893ab082014-05-16 16:56:10 -04002194 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2195 {
2196 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2197
Jamie Madill0af26e12015-03-05 19:54:33 -05002198 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002200 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002201 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002202 }
2203 }
2204
2205 switch (pname)
2206 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002207 case GL_TEXTURE_BINDING_2D:
2208 case GL_TEXTURE_BINDING_CUBE_MAP:
2209 case GL_TEXTURE_BINDING_3D:
2210 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002211 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002212 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002213 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002214 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002215 {
2216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2217 return false;
2218 }
2219 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002220 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2221 if (!context->getExtensions().textureRectangle)
2222 {
2223 context->handleError(InvalidEnum()
2224 << "ANGLE_texture_rectangle extension not present");
2225 return false;
2226 }
2227 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2229 if (!context->getExtensions().eglStreamConsumerExternal &&
2230 !context->getExtensions().eglImageExternal)
2231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002232 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2233 "nor GL_OES_EGL_image_external "
2234 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002235 return false;
2236 }
2237 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002238
He Yunchaoced53ae2016-11-29 15:00:51 +08002239 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2240 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002241 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002242 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2243 ASSERT(readFramebuffer);
2244
Jamie Madill427064d2018-04-13 16:20:34 -04002245 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002246 {
Geoff Langb1196682014-07-23 13:47:29 -04002247 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002248 }
2249
Jamie Madille98b1b52018-03-08 09:47:23 -05002250 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002251 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002253 return false;
2254 }
2255
Jamie Madille98b1b52018-03-08 09:47:23 -05002256 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002257 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002259 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002260 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002261 }
2262 }
2263 break;
2264
He Yunchaoced53ae2016-11-29 15:00:51 +08002265 default:
2266 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002267 }
2268
2269 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002270 if (*numParams == 0)
2271 {
2272 return false;
2273 }
2274
2275 return true;
2276}
2277
Brandon Jonesd1049182018-03-28 10:02:20 -07002278bool ValidateGetBooleanvRobustANGLE(Context *context,
2279 GLenum pname,
2280 GLsizei bufSize,
2281 GLsizei *length,
2282 GLboolean *params)
2283{
2284 GLenum nativeType;
2285 unsigned int numParams = 0;
2286
2287 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2288 {
2289 return false;
2290 }
2291
2292 SetRobustLengthParam(length, numParams);
2293
2294 return true;
2295}
2296
2297bool ValidateGetFloatvRobustANGLE(Context *context,
2298 GLenum pname,
2299 GLsizei bufSize,
2300 GLsizei *length,
2301 GLfloat *params)
2302{
2303 GLenum nativeType;
2304 unsigned int numParams = 0;
2305
2306 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2307 {
2308 return false;
2309 }
2310
2311 SetRobustLengthParam(length, numParams);
2312
2313 return true;
2314}
2315
2316bool ValidateGetIntegervRobustANGLE(Context *context,
2317 GLenum pname,
2318 GLsizei bufSize,
2319 GLsizei *length,
2320 GLint *data)
2321{
2322 GLenum nativeType;
2323 unsigned int numParams = 0;
2324
2325 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2326 {
2327 return false;
2328 }
2329
2330 SetRobustLengthParam(length, numParams);
2331
2332 return true;
2333}
2334
2335bool ValidateGetInteger64vRobustANGLE(Context *context,
2336 GLenum pname,
2337 GLsizei bufSize,
2338 GLsizei *length,
2339 GLint64 *data)
2340{
2341 GLenum nativeType;
2342 unsigned int numParams = 0;
2343
2344 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2345 {
2346 return false;
2347 }
2348
2349 if (nativeType == GL_INT_64_ANGLEX)
2350 {
2351 CastStateValues(context, nativeType, pname, numParams, data);
2352 return false;
2353 }
2354
2355 SetRobustLengthParam(length, numParams);
2356 return true;
2357}
2358
Jamie Madill5b772312018-03-08 20:28:32 -05002359bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002360 GLenum pname,
2361 GLsizei bufSize,
2362 GLenum *nativeType,
2363 unsigned int *numParams)
2364{
2365 if (!ValidateRobustEntryPoint(context, bufSize))
2366 {
2367 return false;
2368 }
2369
2370 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2371 {
2372 return false;
2373 }
2374
2375 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002376 {
2377 return false;
2378 }
2379
2380 return true;
2381}
2382
Jamie Madill5b772312018-03-08 20:28:32 -05002383bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002384 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002385 GLint level,
2386 GLenum internalformat,
2387 bool isSubImage,
2388 GLint xoffset,
2389 GLint yoffset,
2390 GLint zoffset,
2391 GLint x,
2392 GLint y,
2393 GLsizei width,
2394 GLsizei height,
2395 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002396 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002397{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002398 TextureType texType = TextureTargetToType(target);
2399
Brandon Jones6cad5662017-06-14 13:25:13 -07002400 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002401 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002402 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2403 return false;
2404 }
2405
2406 if (width < 0 || height < 0)
2407 {
2408 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002409 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 }
2411
He Yunchaoced53ae2016-11-29 15:00:51 +08002412 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2413 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002415 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002416 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 }
2418
2419 if (border != 0)
2420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002421 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002423 }
2424
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002425 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002427 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 }
2430
Jamie Madill43da7c42018-08-01 11:34:49 -04002431 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002432 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002433 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 {
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002436 }
2437
Jamie Madille98b1b52018-03-08 09:47:23 -05002438 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 {
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
Martin Radev138064f2016-07-15 12:03:41 +03002443 if (readFramebuffer->getReadBufferState() == GL_NONE)
2444 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002445 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002446 return false;
2447 }
2448
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002449 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2450 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002451 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002452 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002453 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2454 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002457 return false;
2458 }
2459
Martin Radev04e2c3b2017-07-27 16:54:35 +03002460 // ANGLE_multiview spec, Revision 1:
2461 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2462 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002463 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2464 // framebuffer is more than one.
2465 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002466 {
2467 context->handleError(InvalidFramebufferOperation()
2468 << "The active read framebuffer object has multiview attachments.");
2469 return false;
2470 }
2471
Jamie Madill43da7c42018-08-01 11:34:49 -04002472 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002473
Geoff Langaae65a42014-05-26 12:43:44 -04002474 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002475 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002476 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002477 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002478 maxDimension = caps.max2DTextureSize;
2479 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002480
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002481 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 maxDimension = caps.maxCubeMapTextureSize;
2483 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002486 maxDimension = caps.maxRectangleTextureSize;
2487 break;
2488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002490 maxDimension = caps.max2DTextureSize;
2491 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002493 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002494 maxDimension = caps.max3DTextureSize;
2495 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496
He Yunchaoced53ae2016-11-29 15:00:51 +08002497 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
Jamie Madill43da7c42018-08-01 11:34:49 -04002502 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 if (!texture)
2504 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002506 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 }
2508
Geoff Lang69cce582015-09-17 13:20:36 -04002509 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
Jamie Madill43da7c42018-08-01 11:34:49 -04002515 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002516 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002517 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002518
Geoff Lang966c9402017-04-18 12:38:27 -04002519 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524
2525 if (isSubImage)
2526 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002527 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2528 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2529 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 }
2534 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 else
2536 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002537 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002539 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002541 }
2542
Geoff Langeb66a6e2016-10-31 13:06:12 -04002543 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002547 }
2548
2549 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002550 if (static_cast<int>(width) > maxLevelDimension ||
2551 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002553 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002557
Jamie Madill0c8abca2016-07-22 20:21:26 -04002558 if (textureFormatOut)
2559 {
2560 *textureFormatOut = texture->getFormat(target, level);
2561 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002562
2563 // Detect texture copying feedback loops for WebGL.
2564 if (context->getExtensions().webglCompatibility)
2565 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002566 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002569 return false;
2570 }
2571 }
2572
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 return true;
2574}
2575
Jamie Madillb42162f2018-08-20 12:58:37 -04002576// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2577// completeness check.
2578const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002579{
2580 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002581 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002582
2583 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2584 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2585 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002586 VertexArray *vertexArray = state.getVertexArray();
2587 ASSERT(vertexArray);
2588
2589 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002590 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002591 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002592 }
2593
2594 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2595 // Section 6.10 of the WebGL 1.0 spec.
2596 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002597 ASSERT(framebuffer);
2598
Jamie Madille7d80f32018-08-08 15:49:23 -04002599 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2600 {
2601 ASSERT(framebuffer);
2602 const FramebufferAttachment *dsAttachment =
2603 framebuffer->getStencilOrDepthStencilAttachment();
2604 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2605 ASSERT(stencilBits <= 8);
2606
2607 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2608 if (depthStencilState.stencilTest && stencilBits > 0)
2609 {
2610 GLuint maxStencilValue = (1 << stencilBits) - 1;
2611
2612 bool differentRefs =
2613 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2614 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2615 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2616 (depthStencilState.stencilBackWritemask & maxStencilValue);
2617 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2618 (depthStencilState.stencilBackMask & maxStencilValue);
2619
2620 if (differentRefs || differentWritemasks || differentMasks)
2621 {
2622 if (!extensions.webglCompatibility)
2623 {
2624 WARN() << "This ANGLE implementation does not support separate front/back "
2625 "stencil writemasks, reference values, or stencil mask values.";
2626 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002627 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002628 }
2629 }
2630 }
2631
2632 if (!framebuffer->isComplete(context))
2633 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002634 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2635 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002636 }
2637
2638 if (context->getStateCache().hasAnyEnabledClientAttrib())
2639 {
2640 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2641 {
2642 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2643 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2644 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2645 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002646 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002647 }
2648
2649 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2650 {
2651 // This is an application error that would normally result in a crash, but we catch it
2652 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002653 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002654 }
2655 }
2656
2657 // If we are running GLES1, there is no current program.
2658 if (context->getClientVersion() >= Version(2, 0))
2659 {
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002660 Program *program = state.getLinkedProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002661 if (!program)
2662 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002663 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002664 }
2665
2666 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2667 // vertex shader stage or fragment shader stage is a undefined behaviour.
2668 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2669 // produce undefined result.
2670 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2671 !program->hasLinkedShaderStage(ShaderType::Fragment))
2672 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002673 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002674 }
2675
2676 if (!program->validateSamplers(nullptr, context->getCaps()))
2677 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002678 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680
2681 if (extensions.multiview)
2682 {
2683 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2684 const int framebufferNumViews = framebuffer->getNumViews();
2685 if (framebufferNumViews != programNumViews)
2686 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002687 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002688 }
2689
2690 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2691 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2692 framebufferNumViews > 1)
2693 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002694 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002695 }
2696
2697 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2698 state.isQueryActive(QueryType::TimeElapsed))
2699 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002700 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002701 }
2702 }
2703
2704 // Uniform buffer validation
2705 for (unsigned int uniformBlockIndex = 0;
2706 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2707 {
2708 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002709 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002710 const OffsetBindingPointer<Buffer> &uniformBuffer =
2711 state.getIndexedUniformBuffer(blockBinding);
2712
2713 if (uniformBuffer.get() == nullptr)
2714 {
2715 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002716 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002717 }
2718
2719 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2720 if (uniformBufferSize < uniformBlock.dataSize)
2721 {
2722 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002723 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002724 }
2725
2726 if (extensions.webglCompatibility &&
2727 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2728 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002729 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731 }
2732
2733 // Do some additonal WebGL-specific validation
2734 if (extensions.webglCompatibility)
2735 {
2736 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2737 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2738 transformFeedbackObject->buffersBoundForOtherUse())
2739 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002740 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002741 }
2742
2743 // Detect rendering feedback loops for WebGL.
2744 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2745 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002746 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002747 }
2748
2749 // Detect that the vertex shader input types match the attribute types
2750 if (!ValidateVertexShaderAttributeTypeMatch(context))
2751 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002752 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002753 }
2754
2755 // Detect that the color buffer types match the fragment shader output types
2756 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2757 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002758 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002759 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002760
2761 const VertexArray *vao = context->getGLState().getVertexArray();
2762 if (vao->hasTransformFeedbackBindingConflict(context))
2763 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002764 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002765 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002766 }
2767 }
2768
Jamie Madillb42162f2018-08-20 12:58:37 -04002769 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002770}
2771
Jamie Madill16e28fd2018-09-12 11:03:05 -04002772bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002773{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002774 const Extensions &extensions = context->getExtensions();
2775
Jamie Madill1aeb1312014-06-20 13:21:25 -04002776 switch (mode)
2777 {
Jamie Madill493f9572018-05-24 19:52:15 -04002778 case PrimitiveMode::Points:
2779 case PrimitiveMode::Lines:
2780 case PrimitiveMode::LineLoop:
2781 case PrimitiveMode::LineStrip:
2782 case PrimitiveMode::Triangles:
2783 case PrimitiveMode::TriangleStrip:
2784 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002785 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002786
Jamie Madill493f9572018-05-24 19:52:15 -04002787 case PrimitiveMode::LinesAdjacency:
2788 case PrimitiveMode::LineStripAdjacency:
2789 case PrimitiveMode::TrianglesAdjacency:
2790 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002791 if (!extensions.geometryShader)
2792 {
2793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2794 return false;
2795 }
2796 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002797 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002799 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002800 }
2801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // If we are running GLES1, there is no current program.
2803 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002804 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002805 const State &state = context->getGLState();
2806
Jamie Madill44a6fbf2018-10-02 13:38:56 -04002807 Program *program = state.getLinkedProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002808 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002809
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002810 // Do geometry shader specific validations
2811 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002812 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002813 if (!IsCompatibleDrawModeWithGeometryShader(
2814 mode, program->getGeometryShaderInputPrimitiveType()))
2815 {
2816 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2817 IncompatibleDrawModeAgainstGeometryShader);
2818 return false;
2819 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002820 }
2821 }
2822
Jamie Madill9fdaa492018-02-16 10:52:11 -05002823 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002824}
2825
Jamie Madill16e28fd2018-09-12 11:03:05 -04002826bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2827{
2828 if (!context->getStateCache().isValidDrawMode(mode))
2829 {
2830 return ValidateDrawMode(context, mode);
2831 }
2832
2833 if (count < 0)
2834 {
2835 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2836 return false;
2837 }
2838
2839 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2840 if (drawStatesError)
2841 {
2842 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2843
2844 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2845 // Incomplete.
2846 GLenum errorCode =
2847 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2848 : GL_INVALID_OPERATION);
2849 context->handleError(Error(errorCode, errorMessage));
2850 return false;
2851 }
2852
2853 return true;
2854}
2855
Jamie Madill5b772312018-03-08 20:28:32 -05002856bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002857 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002858 GLint first,
2859 GLsizei count,
2860 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002861{
Jamie Madillfd716582014-06-06 17:09:04 -04002862 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002864 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002865 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002866 }
2867
Jamie Madill16e28fd2018-09-12 11:03:05 -04002868 if (count < 0)
2869 {
2870 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2871 return false;
2872 }
2873
Jamie Madill7f232932018-09-12 11:03:06 -04002874 const State &state = context->getGLState();
2875 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002876 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002877 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002878 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002879 if (!ValidateTransformFeedbackPrimitiveMode(context,
2880 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002881 {
James Darpinian30b604d2018-03-12 17:26:57 -07002882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2883 return false;
2884 }
2885
2886 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2887 {
2888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2889 return false;
2890 }
Jamie Madillfd716582014-06-06 17:09:04 -04002891 }
2892
Jamie Madill16e28fd2018-09-12 11:03:05 -04002893 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002894 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002895 return ValidateDrawMode(context, mode);
2896 }
2897
2898 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2899 if (drawStatesError)
2900 {
2901 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2902
2903 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2904 // Incomplete.
2905 GLenum errorCode =
2906 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2907 : GL_INVALID_OPERATION);
2908 context->handleError(Error(errorCode, errorMessage));
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002909 return false;
2910 }
2911
Corentin Wallez71168a02016-12-19 15:11:18 -08002912 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002913 // - first < 0 has been checked as an error condition.
2914 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002915 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002916 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002917 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002918 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002919 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2920 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2921 {
2922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2923 return false;
2924 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002925
Jamie Madill2da53562018-08-01 11:34:47 -04002926 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002927 {
2928 return false;
2929 }
Jamie Madillfd716582014-06-06 17:09:04 -04002930 }
2931
2932 return true;
2933}
2934
He Yunchaoced53ae2016-11-29 15:00:51 +08002935bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002936 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002937 GLint first,
2938 GLsizei count,
2939 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002940{
Geoff Lang63c5a592017-09-27 14:08:16 -04002941 if (!context->getExtensions().instancedArrays)
2942 {
2943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2944 return false;
2945 }
2946
Corentin Wallez170efbf2017-05-02 13:45:01 -04002947 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002948 {
2949 return false;
2950 }
2951
Corentin Wallez0dc97812017-06-22 14:38:44 -04002952 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002953}
2954
Jamie Madill493f9572018-05-24 19:52:15 -04002955bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002956{
Jamie Madill250d33f2014-06-06 17:09:03 -04002957 switch (type)
2958 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002959 case GL_UNSIGNED_BYTE:
2960 case GL_UNSIGNED_SHORT:
2961 break;
2962 case GL_UNSIGNED_INT:
2963 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002966 return false;
2967 }
2968 break;
2969 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002971 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002972 }
2973
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002974 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002975
Jamie Madill43da7c42018-08-01 11:34:49 -04002976 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 if (curTransformFeedback && curTransformFeedback->isActive() &&
2978 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002979 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002980 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2981 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2982 if (context->getExtensions().geometryShader)
2983 {
2984 if (!ValidateTransformFeedbackPrimitiveMode(
2985 context, curTransformFeedback->getPrimitiveMode(), mode))
2986 {
2987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2988 return false;
2989 }
2990 }
2991 else
2992 {
2993 // It is an invalid operation to call DrawElements, DrawRangeElements or
2994 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2995 // 86)
2996 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2997 UnsupportedDrawModeForTransformFeedback);
2998 return false;
2999 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003000 }
3001
Jiajia Qind9671222016-11-29 16:30:31 +08003002 return true;
3003}
3004
Jamie Madill5b772312018-03-08 20:28:32 -05003005bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003006 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003007 GLsizei count,
3008 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003009 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003010 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003011{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003012 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003013 return false;
3014
3015 const State &state = context->getGLState();
3016
Corentin Wallez170efbf2017-05-02 13:45:01 -04003017 if (!ValidateDrawBase(context, mode, count))
3018 {
3019 return false;
3020 }
3021
Jamie Madill43da7c42018-08-01 11:34:49 -04003022 const VertexArray *vao = state.getVertexArray();
3023 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003024
Jamie Madill43da7c42018-08-01 11:34:49 -04003025 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003026
3027 if (context->getExtensions().webglCompatibility)
3028 {
3029 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3030 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3031 {
3032 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3033 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3034 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003035 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003036 return false;
3037 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003038
3039 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3040 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3041 // error is generated.
3042 if (reinterpret_cast<intptr_t>(indices) < 0)
3043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003044 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003045 return false;
3046 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003047 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003048 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3049 {
3050 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3051 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3052 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3053 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3054 return false;
3055 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003056
3057 if (context->getExtensions().webglCompatibility ||
3058 !context->getGLState().areClientArraysEnabled())
3059 {
Brandon Jones2a018152018-06-08 15:59:26 -07003060 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003061 {
3062 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003063 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3064 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003066 return false;
3067 }
3068 }
3069
Jamie Madill9fdaa492018-02-16 10:52:11 -05003070 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003071 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003072 // This is an application error that would normally result in a crash, but we catch it and
3073 // return an error
3074 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3075 return false;
3076 }
3077
3078 if (count > 0 && elementArrayBuffer)
3079 {
3080 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3081 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3082 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3083 constexpr uint64_t kMaxTypeSize = 8;
3084 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3085 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3086 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3087
3088 uint64_t typeSize = typeBytes;
3089 uint64_t elementCount = static_cast<uint64_t>(count);
3090 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3091
3092 // Doing the multiplication here is overflow-safe
3093 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3094
3095 // The offset can be any value, check for overflows
3096 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3097 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003098 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3100 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003101 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003102
3103 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3104 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003105 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3107 return false;
3108 }
3109
3110 ASSERT(isPow2(typeSize) && typeSize > 0);
3111 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3112 {
3113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003115 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003116
3117 if (context->getExtensions().webglCompatibility &&
3118 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3119 {
3120 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3121 ElementArrayBufferBoundForTransformFeedback);
3122 return false;
3123 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003124 }
3125
Jamie Madill2da53562018-08-01 11:34:47 -04003126 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003127 {
3128 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003129 const DrawCallParams &params = context->getParams<DrawCallParams>();
3130 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3131 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003132
3133 // If we use an index greater than our maximum supported index range, return an error.
3134 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3135 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003136 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003137 {
3138 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3139 return false;
3140 }
3141
Jamie Madill2da53562018-08-01 11:34:47 -04003142 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003143 {
3144 return false;
3145 }
3146
3147 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003148 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003149 }
3150
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003151 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003152}
3153
Jamie Madill5b772312018-03-08 20:28:32 -05003154bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003155 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003156 GLsizei count,
3157 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003158 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003159 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003160{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003161 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003162}
3163
Geoff Lang3edfe032015-09-04 16:38:24 -04003164bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003165 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003166 GLsizei count,
3167 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003168 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003169 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003170{
Geoff Lang63c5a592017-09-27 14:08:16 -04003171 if (!context->getExtensions().instancedArrays)
3172 {
3173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3174 return false;
3175 }
3176
Corentin Wallez170efbf2017-05-02 13:45:01 -04003177 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003178 {
3179 return false;
3180 }
3181
Corentin Wallez0dc97812017-06-22 14:38:44 -04003182 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003183}
3184
He Yunchaoced53ae2016-11-29 15:00:51 +08003185bool ValidateFramebufferTextureBase(Context *context,
3186 GLenum target,
3187 GLenum attachment,
3188 GLuint texture,
3189 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003190{
Geoff Lange8afa902017-09-27 15:00:43 -04003191 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003195 }
3196
3197 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003198 {
3199 return false;
3200 }
3201
Jamie Madill55ec3b12014-07-03 10:38:57 -04003202 if (texture != 0)
3203 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003204 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003205
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003206 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003208 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003209 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003210 }
3211
3212 if (level < 0)
3213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003214 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003215 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003216 }
3217 }
3218
Jamie Madill43da7c42018-08-01 11:34:49 -04003219 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003220 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003221
Jamie Madill84115c92015-04-23 15:00:07 -04003222 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003226 }
3227
3228 return true;
3229}
3230
Geoff Langb1196682014-07-23 13:47:29 -04003231bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003232{
3233 if (program == 0)
3234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003235 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003236 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003237 }
3238
Jamie Madill43da7c42018-08-01 11:34:49 -04003239 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003240 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003241 {
3242 return false;
3243 }
3244
Jamie Madill0063c512014-08-25 15:47:53 -04003245 if (!programObject || !programObject->isLinked())
3246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003249 }
3250
Geoff Lang7dd2e102014-11-10 15:19:26 -05003251 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003253 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003254 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003255 }
3256
Jamie Madill0063c512014-08-25 15:47:53 -04003257 return true;
3258}
3259
Geoff Langf41d0ee2016-10-07 13:04:23 -04003260static bool ValidateSizedGetUniform(Context *context,
3261 GLuint program,
3262 GLint location,
3263 GLsizei bufSize,
3264 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003265{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266 if (length)
3267 {
3268 *length = 0;
3269 }
3270
Jamie Madill78f41802014-08-25 15:47:55 -04003271 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003272 {
Jamie Madill78f41802014-08-25 15:47:55 -04003273 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003274 }
3275
Geoff Langf41d0ee2016-10-07 13:04:23 -04003276 if (bufSize < 0)
3277 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003278 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003279 return false;
3280 }
3281
Jamie Madill44a6fbf2018-10-02 13:38:56 -04003282 Program *programObject = context->getProgramResolveLink(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003283 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003284
Jamie Madill78f41802014-08-25 15:47:55 -04003285 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003286 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003287 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003288 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003289 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003291 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003292 }
3293
Geoff Langf41d0ee2016-10-07 13:04:23 -04003294 if (length)
3295 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003296 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297 }
3298
Jamie Madill0063c512014-08-25 15:47:53 -04003299 return true;
3300}
3301
He Yunchaoced53ae2016-11-29 15:00:51 +08003302bool ValidateGetnUniformfvEXT(Context *context,
3303 GLuint program,
3304 GLint location,
3305 GLsizei bufSize,
3306 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003307{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003309}
3310
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003311bool ValidateGetnUniformfvRobustANGLE(Context *context,
3312 GLuint program,
3313 GLint location,
3314 GLsizei bufSize,
3315 GLsizei *length,
3316 GLfloat *params)
3317{
3318 UNIMPLEMENTED();
3319 return false;
3320}
3321
He Yunchaoced53ae2016-11-29 15:00:51 +08003322bool ValidateGetnUniformivEXT(Context *context,
3323 GLuint program,
3324 GLint location,
3325 GLsizei bufSize,
3326 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003327{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003328 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3329}
3330
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003331bool ValidateGetnUniformivRobustANGLE(Context *context,
3332 GLuint program,
3333 GLint location,
3334 GLsizei bufSize,
3335 GLsizei *length,
3336 GLint *params)
3337{
3338 UNIMPLEMENTED();
3339 return false;
3340}
3341
3342bool ValidateGetnUniformuivRobustANGLE(Context *context,
3343 GLuint program,
3344 GLint location,
3345 GLsizei bufSize,
3346 GLsizei *length,
3347 GLuint *params)
3348{
3349 UNIMPLEMENTED();
3350 return false;
3351}
3352
Geoff Langf41d0ee2016-10-07 13:04:23 -04003353bool ValidateGetUniformfvRobustANGLE(Context *context,
3354 GLuint program,
3355 GLint location,
3356 GLsizei bufSize,
3357 GLsizei *length,
3358 GLfloat *params)
3359{
3360 if (!ValidateRobustEntryPoint(context, bufSize))
3361 {
3362 return false;
3363 }
3364
Brandon Jonesd1049182018-03-28 10:02:20 -07003365 GLsizei writeLength = 0;
3366
Geoff Langf41d0ee2016-10-07 13:04:23 -04003367 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003368 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3369 {
3370 return false;
3371 }
3372
3373 SetRobustLengthParam(length, writeLength);
3374
3375 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003376}
3377
3378bool ValidateGetUniformivRobustANGLE(Context *context,
3379 GLuint program,
3380 GLint location,
3381 GLsizei bufSize,
3382 GLsizei *length,
3383 GLint *params)
3384{
3385 if (!ValidateRobustEntryPoint(context, bufSize))
3386 {
3387 return false;
3388 }
3389
Brandon Jonesd1049182018-03-28 10:02:20 -07003390 GLsizei writeLength = 0;
3391
Geoff Langf41d0ee2016-10-07 13:04:23 -04003392 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003393 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3394 {
3395 return false;
3396 }
3397
3398 SetRobustLengthParam(length, writeLength);
3399
3400 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003401}
3402
3403bool ValidateGetUniformuivRobustANGLE(Context *context,
3404 GLuint program,
3405 GLint location,
3406 GLsizei bufSize,
3407 GLsizei *length,
3408 GLuint *params)
3409{
3410 if (!ValidateRobustEntryPoint(context, bufSize))
3411 {
3412 return false;
3413 }
3414
3415 if (context->getClientMajorVersion() < 3)
3416 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003417 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003418 return false;
3419 }
3420
Brandon Jonesd1049182018-03-28 10:02:20 -07003421 GLsizei writeLength = 0;
3422
Geoff Langf41d0ee2016-10-07 13:04:23 -04003423 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003424 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3425 {
3426 return false;
3427 }
3428
3429 SetRobustLengthParam(length, writeLength);
3430
3431 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003432}
3433
He Yunchaoced53ae2016-11-29 15:00:51 +08003434bool ValidateDiscardFramebufferBase(Context *context,
3435 GLenum target,
3436 GLsizei numAttachments,
3437 const GLenum *attachments,
3438 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003439{
3440 if (numAttachments < 0)
3441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003443 return false;
3444 }
3445
3446 for (GLsizei i = 0; i < numAttachments; ++i)
3447 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003448 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003449 {
3450 if (defaultFramebuffer)
3451 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003453 return false;
3454 }
3455
3456 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003458 context->handleError(InvalidOperation() << "Requested color attachment is "
3459 "greater than the maximum supported "
3460 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003461 return false;
3462 }
3463 }
3464 else
3465 {
3466 switch (attachments[i])
3467 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003468 case GL_DEPTH_ATTACHMENT:
3469 case GL_STENCIL_ATTACHMENT:
3470 case GL_DEPTH_STENCIL_ATTACHMENT:
3471 if (defaultFramebuffer)
3472 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003473 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3474 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003475 return false;
3476 }
3477 break;
3478 case GL_COLOR:
3479 case GL_DEPTH:
3480 case GL_STENCIL:
3481 if (!defaultFramebuffer)
3482 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003483 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3484 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003485 return false;
3486 }
3487 break;
3488 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003490 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003491 }
3492 }
3493 }
3494
3495 return true;
3496}
3497
Austin Kinross6ee1e782015-05-29 17:05:37 -07003498bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3499{
Jamie Madill007530e2017-12-28 14:27:04 -05003500 if (!context->getExtensions().debugMarker)
3501 {
3502 // The debug marker calls should not set error state
3503 // However, it seems reasonable to set an error state if the extension is not enabled
3504 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3505 return false;
3506 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003507
Jamie Madill007530e2017-12-28 14:27:04 -05003508 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003509 if (length < 0)
3510 {
3511 return false;
3512 }
3513
3514 if (marker == nullptr)
3515 {
3516 return false;
3517 }
3518
3519 return true;
3520}
3521
3522bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3523{
Jamie Madill007530e2017-12-28 14:27:04 -05003524 if (!context->getExtensions().debugMarker)
3525 {
3526 // The debug marker calls should not set error state
3527 // However, it seems reasonable to set an error state if the extension is not enabled
3528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3529 return false;
3530 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003531
Jamie Madill007530e2017-12-28 14:27:04 -05003532 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003533 if (length < 0)
3534 {
3535 return false;
3536 }
3537
3538 if (length > 0 && marker == nullptr)
3539 {
3540 return false;
3541 }
3542
3543 return true;
3544}
3545
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003546bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003547{
Geoff Langa8406172015-07-21 16:53:39 -04003548 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003551 return false;
3552 }
3553
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003554 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003555 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003556 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003557 if (!context->getExtensions().eglImage)
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidEnum()
3560 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003561 }
3562 break;
3563
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003564 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003565 if (!context->getExtensions().eglImageExternal)
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3568 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003569 }
Geoff Langa8406172015-07-21 16:53:39 -04003570 break;
3571
3572 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Rafael Cintron05a449a2018-06-20 18:08:04 -07003577 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003578
Jamie Madill61e16b42017-06-19 11:13:23 -04003579 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003580 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003582 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003583 return false;
3584 }
3585
Jamie Madill007530e2017-12-28 14:27:04 -05003586 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidOperation()
3589 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003590 return false;
3591 }
3592
Yuly Novikov2eb54072018-08-22 16:41:26 -04003593 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation()
3596 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003597 return false;
3598 }
3599
Geoff Langdcab33b2015-07-21 13:03:16 -04003600 return true;
3601}
3602
3603bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003604 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003605 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003606{
Geoff Langa8406172015-07-21 16:53:39 -04003607 if (!context->getExtensions().eglImage)
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003610 return false;
3611 }
3612
3613 switch (target)
3614 {
3615 case GL_RENDERBUFFER:
3616 break;
3617
3618 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003620 return false;
3621 }
3622
Rafael Cintron05a449a2018-06-20 18:08:04 -07003623 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003624
Jamie Madill61e16b42017-06-19 11:13:23 -04003625 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003626 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003629 return false;
3630 }
3631
Yuly Novikov2eb54072018-08-22 16:41:26 -04003632 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(InvalidOperation()
3635 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003636 return false;
3637 }
3638
Geoff Langdcab33b2015-07-21 13:03:16 -04003639 return true;
3640}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003641
3642bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3643{
Geoff Lang36167ab2015-12-07 10:27:14 -05003644 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003645 {
3646 // The default VAO should always exist
3647 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003648 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003649 return false;
3650 }
3651
3652 return true;
3653}
3654
Geoff Langc5629752015-12-07 16:29:04 -05003655bool ValidateProgramBinaryBase(Context *context,
3656 GLuint program,
3657 GLenum binaryFormat,
3658 const void *binary,
3659 GLint length)
3660{
3661 Program *programObject = GetValidProgram(context, program);
3662 if (programObject == nullptr)
3663 {
3664 return false;
3665 }
3666
3667 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3668 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3669 programBinaryFormats.end())
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003672 return false;
3673 }
3674
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003675 if (context->hasActiveTransformFeedback(program))
3676 {
3677 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3679 "is associated with an active transform "
3680 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003681 return false;
3682 }
3683
Geoff Langc5629752015-12-07 16:29:04 -05003684 return true;
3685}
3686
3687bool ValidateGetProgramBinaryBase(Context *context,
3688 GLuint program,
3689 GLsizei bufSize,
3690 GLsizei *length,
3691 GLenum *binaryFormat,
3692 void *binary)
3693{
3694 Program *programObject = GetValidProgram(context, program);
3695 if (programObject == nullptr)
3696 {
3697 return false;
3698 }
3699
3700 if (!programObject->isLinked())
3701 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003703 return false;
3704 }
3705
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003706 if (context->getCaps().programBinaryFormats.empty())
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003709 return false;
3710 }
3711
Geoff Langc5629752015-12-07 16:29:04 -05003712 return true;
3713}
Jamie Madillc29968b2016-01-20 11:17:23 -05003714
Jamie Madill5b772312018-03-08 20:28:32 -05003715bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003716{
3717 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003718 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003720 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3721 return false;
3722 }
3723 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3724 {
3725 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003726 return false;
3727 }
3728
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003729 ASSERT(context->getGLState().getDrawFramebuffer());
3730 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003731 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3732
3733 // This should come first before the check for the default frame buffer
3734 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3735 // rather than INVALID_OPERATION
3736 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3737 {
3738 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3739
3740 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003741 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3742 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003743 {
3744 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003745 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3746 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3747 // 3.1 is still a bit ambiguous about the error, but future specs are
3748 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003749 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003750 return false;
3751 }
3752 else if (bufs[colorAttachment] >= maxColorAttachment)
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation()
3755 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003756 return false;
3757 }
3758 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3759 frameBufferId != 0)
3760 {
3761 // INVALID_OPERATION-GL is bound to buffer and ith argument
3762 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidOperation()
3764 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003765 return false;
3766 }
3767 }
3768
3769 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3770 // and n is not 1 or bufs is bound to value other than BACK and NONE
3771 if (frameBufferId == 0)
3772 {
3773 if (n != 1)
3774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003775 context->handleError(InvalidOperation()
3776 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003777 return false;
3778 }
3779
3780 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(
3783 InvalidOperation()
3784 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003785 return false;
3786 }
3787 }
3788
3789 return true;
3790}
3791
Geoff Lang496c02d2016-10-20 11:38:11 -07003792bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003793 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003794 GLenum pname,
3795 GLsizei *length,
3796 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003797{
Geoff Lang496c02d2016-10-20 11:38:11 -07003798 if (length)
3799 {
3800 *length = 0;
3801 }
3802
3803 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3804 {
3805 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003806 InvalidOperation()
3807 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003808 return false;
3809 }
3810
Corentin Walleze4477002017-12-01 14:39:58 -05003811 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003813 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 return false;
3815 }
3816
Geoff Lang496c02d2016-10-20 11:38:11 -07003817 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003819 case GL_BUFFER_MAP_POINTER:
3820 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003821
Geoff Lang496c02d2016-10-20 11:38:11 -07003822 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003824 return false;
3825 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003826
3827 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3828 // target bound to zero generate an INVALID_OPERATION error."
3829 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003830 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidOperation()
3833 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003834 return false;
3835 }
3836
Geoff Lang496c02d2016-10-20 11:38:11 -07003837 if (length)
3838 {
3839 *length = 1;
3840 }
3841
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 return true;
3843}
3844
Corentin Wallez336129f2017-10-17 15:55:40 -04003845bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003846{
Corentin Walleze4477002017-12-01 14:39:58 -05003847 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003853 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003854
3855 if (buffer == nullptr || !buffer->isMapped())
3856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003857 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
3861 return true;
3862}
3863
3864bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003865 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 GLintptr offset,
3867 GLsizeiptr length,
3868 GLbitfield access)
3869{
Corentin Walleze4477002017-12-01 14:39:58 -05003870 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 return false;
3874 }
3875
Brandon Jones6cad5662017-06-14 13:25:13 -07003876 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003878 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3879 return false;
3880 }
3881
3882 if (length < 0)
3883 {
3884 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003888 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003889
3890 if (!buffer)
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003897 CheckedNumeric<size_t> checkedOffset(offset);
3898 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003899
Jamie Madille2e406c2016-06-02 13:04:10 -04003900 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003903 return false;
3904 }
3905
3906 // Check for invalid bits in the mask
3907 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3908 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3909 GL_MAP_UNSYNCHRONIZED_BIT;
3910
3911 if (access & ~(allAccessBits))
3912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003913 context->handleError(InvalidValue()
3914 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003915 return false;
3916 }
3917
3918 if (length == 0)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003921 return false;
3922 }
3923
3924 if (buffer->isMapped())
3925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003926 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
3929
3930 // Check for invalid bit combinations
3931 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidOperation()
3934 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003935 return false;
3936 }
3937
3938 GLbitfield writeOnlyBits =
3939 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3940
3941 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003943 context->handleError(InvalidOperation()
3944 << "Invalid access bits when mapping buffer for reading: 0x"
3945 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
3948
3949 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003951 context->handleError(
3952 InvalidOperation()
3953 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003954 return false;
3955 }
Geoff Lang79f71042017-08-14 16:43:43 -04003956
3957 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003958}
3959
3960bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003961 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 GLintptr offset,
3963 GLsizeiptr length)
3964{
Brandon Jones6cad5662017-06-14 13:25:13 -07003965 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3968 return false;
3969 }
3970
3971 if (length < 0)
3972 {
3973 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003974 return false;
3975 }
3976
Corentin Walleze4477002017-12-01 14:39:58 -05003977 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003980 return false;
3981 }
3982
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003983 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003984
3985 if (buffer == nullptr)
3986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003988 return false;
3989 }
3990
3991 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003993 context->handleError(InvalidOperation()
3994 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003995 return false;
3996 }
3997
3998 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003999 CheckedNumeric<size_t> checkedOffset(offset);
4000 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004001
Jamie Madille2e406c2016-06-02 13:04:10 -04004002 if (!checkedSize.IsValid() ||
4003 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004005 context->handleError(InvalidValue()
4006 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004007 return false;
4008 }
4009
4010 return true;
4011}
4012
Olli Etuaho41997e72016-03-10 13:38:39 +02004013bool ValidateGenOrDelete(Context *context, GLint n)
4014{
4015 if (n < 0)
4016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004017 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004018 return false;
4019 }
4020 return true;
4021}
4022
Jamie Madill5b772312018-03-08 20:28:32 -05004023bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004024{
4025 if (!context->getExtensions().robustClientMemory)
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation()
4028 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 return false;
4030 }
4031
4032 if (bufSize < 0)
4033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004034 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 return false;
4036 }
4037
4038 return true;
4039}
4040
Jamie Madill5b772312018-03-08 20:28:32 -05004041bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004042{
4043 if (bufSize < numParams)
4044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004045 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4046 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004047 return false;
4048 }
4049
4050 return true;
4051}
4052
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004053bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004054 GLenum target,
4055 GLenum attachment,
4056 GLenum pname,
4057 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004058{
Geoff Lange8afa902017-09-27 15:00:43 -04004059 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004062 return false;
4063 }
4064
4065 int clientVersion = context->getClientMajorVersion();
4066
4067 switch (pname)
4068 {
4069 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4071 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4072 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4073 break;
4074
Martin Radeve5285d22017-07-14 16:23:53 +03004075 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4076 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4077 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4078 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4079 if (clientVersion < 3 || !context->getExtensions().multiview)
4080 {
4081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4082 return false;
4083 }
4084 break;
4085
Geoff Langff5b2d52016-09-07 11:32:23 -04004086 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4087 if (clientVersion < 3 && !context->getExtensions().sRGB)
4088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004089 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 return false;
4091 }
4092 break;
4093
4094 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4095 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4096 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4097 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4098 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4099 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4100 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4101 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4102 if (clientVersion < 3)
4103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004104 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004105 return false;
4106 }
4107 break;
4108
Jiawei Shaoa8802472018-05-28 11:17:47 +08004109 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4110 if (!context->getExtensions().geometryShader)
4111 {
4112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4113 return false;
4114 }
4115 break;
4116
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004118 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 return false;
4120 }
4121
4122 // Determine if the attachment is a valid enum
4123 switch (attachment)
4124 {
4125 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 case GL_DEPTH:
4127 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 if (clientVersion < 3)
4129 {
Geoff Langfa125c92017-10-24 13:01:46 -04004130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004131 return false;
4132 }
4133 break;
4134
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004135 case GL_DEPTH_STENCIL_ATTACHMENT:
4136 if (clientVersion < 3 && !context->isWebGL1())
4137 {
4138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4139 return false;
4140 }
4141 break;
4142
Geoff Langfa125c92017-10-24 13:01:46 -04004143 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 case GL_DEPTH_ATTACHMENT:
4145 case GL_STENCIL_ATTACHMENT:
4146 break;
4147
4148 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004149 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4150 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4152 {
Geoff Langfa125c92017-10-24 13:01:46 -04004153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156 break;
4157 }
4158
4159 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4160 ASSERT(framebuffer);
4161
4162 if (framebuffer->id() == 0)
4163 {
4164 if (clientVersion < 3)
4165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004167 return false;
4168 }
4169
4170 switch (attachment)
4171 {
4172 case GL_BACK:
4173 case GL_DEPTH:
4174 case GL_STENCIL:
4175 break;
4176
4177 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 }
4182 else
4183 {
4184 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4185 {
4186 // Valid attachment query
4187 }
4188 else
4189 {
4190 switch (attachment)
4191 {
4192 case GL_DEPTH_ATTACHMENT:
4193 case GL_STENCIL_ATTACHMENT:
4194 break;
4195
4196 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004197 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004199 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
4204 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 }
4209 }
4210
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004211 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004212 if (attachmentObject)
4213 {
4214 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4215 attachmentObject->type() == GL_TEXTURE ||
4216 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4217
4218 switch (pname)
4219 {
4220 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4221 if (attachmentObject->type() != GL_RENDERBUFFER &&
4222 attachmentObject->type() != GL_TEXTURE)
4223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004225 return false;
4226 }
4227 break;
4228
4229 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4230 if (attachmentObject->type() != GL_TEXTURE)
4231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 return false;
4234 }
4235 break;
4236
4237 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4238 if (attachmentObject->type() != GL_TEXTURE)
4239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4246 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4247 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 break;
4252
4253 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4254 if (attachmentObject->type() != GL_TEXTURE)
4255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004257 return false;
4258 }
4259 break;
4260
4261 default:
4262 break;
4263 }
4264 }
4265 else
4266 {
4267 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4268 // is NONE, then querying any other pname will generate INVALID_ENUM.
4269
4270 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4271 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4272 // INVALID_OPERATION for all other pnames
4273
4274 switch (pname)
4275 {
4276 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4277 break;
4278
4279 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4280 if (clientVersion < 3)
4281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004282 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004283 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004284 return false;
4285 }
4286 break;
4287
4288 default:
4289 if (clientVersion < 3)
4290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004291 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004292 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004293 return false;
4294 }
4295 else
4296 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004297 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004298 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004299 return false;
4300 }
4301 }
4302 }
4303
Martin Radeve5285d22017-07-14 16:23:53 +03004304 if (numParams)
4305 {
4306 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4307 {
4308 // Only when the viewport offsets are queried we can have a varying number of output
4309 // parameters.
4310 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4311 *numParams = numViews * 2;
4312 }
4313 else
4314 {
4315 // For all other queries we can have only one output parameter.
4316 *numParams = 1;
4317 }
4318 }
4319
Geoff Langff5b2d52016-09-07 11:32:23 -04004320 return true;
4321}
4322
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004323bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 GLenum target,
4325 GLenum attachment,
4326 GLenum pname,
4327 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004328 GLsizei *length,
4329 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004330{
4331 if (!ValidateRobustEntryPoint(context, bufSize))
4332 {
4333 return false;
4334 }
4335
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004337 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004339 {
4340 return false;
4341 }
4342
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 SetRobustLengthParam(length, numParams);
4349
Geoff Langff5b2d52016-09-07 11:32:23 -04004350 return true;
4351}
4352
Jamie Madill5b772312018-03-08 20:28:32 -05004353bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004354 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 GLenum pname,
4356 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004357 GLsizei *length,
4358 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004359{
4360 if (!ValidateRobustEntryPoint(context, bufSize))
4361 {
4362 return false;
4363 }
4364
Brandon Jonesd1049182018-03-28 10:02:20 -07004365 GLsizei numParams = 0;
4366
4367 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004368 {
4369 return false;
4370 }
4371
Brandon Jonesd1049182018-03-28 10:02:20 -07004372 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004373 {
4374 return false;
4375 }
4376
Brandon Jonesd1049182018-03-28 10:02:20 -07004377 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004378 return true;
4379}
4380
Jamie Madill5b772312018-03-08 20:28:32 -05004381bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004382 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004383 GLenum pname,
4384 GLsizei bufSize,
4385 GLsizei *length,
4386 GLint64 *params)
4387{
Brandon Jonesd1049182018-03-28 10:02:20 -07004388 GLsizei numParams = 0;
4389
Geoff Langebebe1c2016-10-14 12:01:31 -04004390 if (!ValidateRobustEntryPoint(context, bufSize))
4391 {
4392 return false;
4393 }
4394
Brandon Jonesd1049182018-03-28 10:02:20 -07004395 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004396 {
4397 return false;
4398 }
4399
Brandon Jonesd1049182018-03-28 10:02:20 -07004400 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004401 {
4402 return false;
4403 }
4404
Brandon Jonesd1049182018-03-28 10:02:20 -07004405 SetRobustLengthParam(length, numParams);
4406
Geoff Langff5b2d52016-09-07 11:32:23 -04004407 return true;
4408}
4409
Jamie Madill5b772312018-03-08 20:28:32 -05004410bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004411{
4412 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004413 if (numParams)
4414 {
4415 *numParams = 1;
4416 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004417
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004418 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
4419 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
4420 ? GetValidProgramNoResolve(context, program)
4421 : GetValidProgram(context, program);
Geoff Langff5b2d52016-09-07 11:32:23 -04004422 if (!programObject)
4423 {
4424 return false;
4425 }
4426
4427 switch (pname)
4428 {
4429 case GL_DELETE_STATUS:
4430 case GL_LINK_STATUS:
4431 case GL_VALIDATE_STATUS:
4432 case GL_INFO_LOG_LENGTH:
4433 case GL_ATTACHED_SHADERS:
4434 case GL_ACTIVE_ATTRIBUTES:
4435 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4436 case GL_ACTIVE_UNIFORMS:
4437 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4438 break;
4439
4440 case GL_PROGRAM_BINARY_LENGTH:
4441 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004443 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4444 "requires GL_OES_get_program_binary or "
4445 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004446 return false;
4447 }
4448 break;
4449
4450 case GL_ACTIVE_UNIFORM_BLOCKS:
4451 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4452 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4453 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4454 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4455 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4456 if (context->getClientMajorVersion() < 3)
4457 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004459 return false;
4460 }
4461 break;
4462
Yunchao He61afff12017-03-14 15:34:03 +08004463 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004464 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004465 if (context->getClientVersion() < Version(3, 1))
4466 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004468 return false;
4469 }
4470 break;
4471
Jiawei Shao6ae51612018-02-23 14:03:25 +08004472 case GL_COMPUTE_WORK_GROUP_SIZE:
4473 if (context->getClientVersion() < Version(3, 1))
4474 {
4475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4476 return false;
4477 }
4478
4479 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4480 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4481 // program which has not been linked successfully, or which does not contain objects to
4482 // form a compute shader.
4483 if (!programObject->isLinked())
4484 {
4485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4486 return false;
4487 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004488 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004489 {
4490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4491 return false;
4492 }
4493 break;
4494
Jiawei Shao447bfac2018-03-14 14:23:40 +08004495 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4496 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4497 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4498 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4499 if (!context->getExtensions().geometryShader)
4500 {
4501 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4502 return false;
4503 }
4504
4505 // [EXT_geometry_shader] Chapter 7.12
4506 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4507 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4508 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4509 // successfully, or which does not contain objects to form a geometry shader.
4510 if (!programObject->isLinked())
4511 {
4512 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4513 return false;
4514 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004515 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004516 {
4517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4518 return false;
4519 }
4520 break;
4521
Jamie Madill44a6fbf2018-10-02 13:38:56 -04004522 case GL_COMPLETION_STATUS_KHR:
4523 if (!context->getExtensions().parallelShaderCompile)
4524 {
4525 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4526 return false;
4527 }
4528 break;
4529
Geoff Langff5b2d52016-09-07 11:32:23 -04004530 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004532 return false;
4533 }
4534
4535 return true;
4536}
4537
4538bool ValidateGetProgramivRobustANGLE(Context *context,
4539 GLuint program,
4540 GLenum pname,
4541 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004542 GLsizei *length,
4543 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004544{
4545 if (!ValidateRobustEntryPoint(context, bufSize))
4546 {
4547 return false;
4548 }
4549
Brandon Jonesd1049182018-03-28 10:02:20 -07004550 GLsizei numParams = 0;
4551
4552 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004553 {
4554 return false;
4555 }
4556
Brandon Jonesd1049182018-03-28 10:02:20 -07004557 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004558 {
4559 return false;
4560 }
4561
Brandon Jonesd1049182018-03-28 10:02:20 -07004562 SetRobustLengthParam(length, numParams);
4563
Geoff Langff5b2d52016-09-07 11:32:23 -04004564 return true;
4565}
4566
Geoff Lang740d9022016-10-07 11:20:52 -04004567bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4568 GLenum target,
4569 GLenum pname,
4570 GLsizei bufSize,
4571 GLsizei *length,
4572 GLint *params)
4573{
4574 if (!ValidateRobustEntryPoint(context, bufSize))
4575 {
4576 return false;
4577 }
4578
Brandon Jonesd1049182018-03-28 10:02:20 -07004579 GLsizei numParams = 0;
4580
4581 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004582 {
4583 return false;
4584 }
4585
Brandon Jonesd1049182018-03-28 10:02:20 -07004586 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004587 {
4588 return false;
4589 }
4590
Brandon Jonesd1049182018-03-28 10:02:20 -07004591 SetRobustLengthParam(length, numParams);
4592
Geoff Lang740d9022016-10-07 11:20:52 -04004593 return true;
4594}
4595
Geoff Langd7d0ed32016-10-07 11:33:51 -04004596bool ValidateGetShaderivRobustANGLE(Context *context,
4597 GLuint shader,
4598 GLenum pname,
4599 GLsizei bufSize,
4600 GLsizei *length,
4601 GLint *params)
4602{
4603 if (!ValidateRobustEntryPoint(context, bufSize))
4604 {
4605 return false;
4606 }
4607
Brandon Jonesd1049182018-03-28 10:02:20 -07004608 GLsizei numParams = 0;
4609
4610 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004611 {
4612 return false;
4613 }
4614
Brandon Jonesd1049182018-03-28 10:02:20 -07004615 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 SetRobustLengthParam(length, numParams);
4621
Geoff Langd7d0ed32016-10-07 11:33:51 -04004622 return true;
4623}
4624
Geoff Langc1984ed2016-10-07 12:41:00 -04004625bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004626 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004627 GLenum pname,
4628 GLsizei bufSize,
4629 GLsizei *length,
4630 GLfloat *params)
4631{
4632 if (!ValidateRobustEntryPoint(context, bufSize))
4633 {
4634 return false;
4635 }
4636
Brandon Jonesd1049182018-03-28 10:02:20 -07004637 GLsizei numParams = 0;
4638
4639 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004640 {
4641 return false;
4642 }
4643
Brandon Jonesd1049182018-03-28 10:02:20 -07004644 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004645 {
4646 return false;
4647 }
4648
Brandon Jonesd1049182018-03-28 10:02:20 -07004649 SetRobustLengthParam(length, numParams);
4650
Geoff Langc1984ed2016-10-07 12:41:00 -04004651 return true;
4652}
4653
Geoff Langc1984ed2016-10-07 12:41:00 -04004654bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004655 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004656 GLenum pname,
4657 GLsizei bufSize,
4658 GLsizei *length,
4659 GLint *params)
4660{
Brandon Jonesd1049182018-03-28 10:02:20 -07004661
Geoff Langc1984ed2016-10-07 12:41:00 -04004662 if (!ValidateRobustEntryPoint(context, bufSize))
4663 {
4664 return false;
4665 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004666 GLsizei numParams = 0;
4667 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004668 {
4669 return false;
4670 }
4671
Brandon Jonesd1049182018-03-28 10:02:20 -07004672 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004673 {
4674 return false;
4675 }
4676
Brandon Jonesd1049182018-03-28 10:02:20 -07004677 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004678 return true;
4679}
4680
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004681bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4682 TextureType target,
4683 GLenum pname,
4684 GLsizei bufSize,
4685 GLsizei *length,
4686 GLint *params)
4687{
4688 UNIMPLEMENTED();
4689 return false;
4690}
4691
4692bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4693 TextureType target,
4694 GLenum pname,
4695 GLsizei bufSize,
4696 GLsizei *length,
4697 GLuint *params)
4698{
4699 UNIMPLEMENTED();
4700 return false;
4701}
4702
Geoff Langc1984ed2016-10-07 12:41:00 -04004703bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004704 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004705 GLenum pname,
4706 GLsizei bufSize,
4707 const GLfloat *params)
4708{
4709 if (!ValidateRobustEntryPoint(context, bufSize))
4710 {
4711 return false;
4712 }
4713
4714 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4715}
4716
Geoff Langc1984ed2016-10-07 12:41:00 -04004717bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004718 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 GLenum pname,
4720 GLsizei bufSize,
4721 const GLint *params)
4722{
4723 if (!ValidateRobustEntryPoint(context, bufSize))
4724 {
4725 return false;
4726 }
4727
4728 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4729}
4730
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004731bool ValidateTexParameterIivRobustANGLE(Context *context,
4732 TextureType target,
4733 GLenum pname,
4734 GLsizei bufSize,
4735 const GLint *params)
4736{
4737 UNIMPLEMENTED();
4738 return false;
4739}
4740
4741bool ValidateTexParameterIuivRobustANGLE(Context *context,
4742 TextureType target,
4743 GLenum pname,
4744 GLsizei bufSize,
4745 const GLuint *params)
4746{
4747 UNIMPLEMENTED();
4748 return false;
4749}
4750
Geoff Langc1984ed2016-10-07 12:41:00 -04004751bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4752 GLuint sampler,
4753 GLenum pname,
4754 GLuint bufSize,
4755 GLsizei *length,
4756 GLfloat *params)
4757{
4758 if (!ValidateRobustEntryPoint(context, bufSize))
4759 {
4760 return false;
4761 }
4762
Brandon Jonesd1049182018-03-28 10:02:20 -07004763 GLsizei numParams = 0;
4764
4765 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004766 {
4767 return false;
4768 }
4769
Brandon Jonesd1049182018-03-28 10:02:20 -07004770 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004771 {
4772 return false;
4773 }
4774
Brandon Jonesd1049182018-03-28 10:02:20 -07004775 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004776 return true;
4777}
4778
Geoff Langc1984ed2016-10-07 12:41:00 -04004779bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4780 GLuint sampler,
4781 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004782 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004783 GLsizei *length,
4784 GLint *params)
4785{
4786 if (!ValidateRobustEntryPoint(context, bufSize))
4787 {
4788 return false;
4789 }
4790
Brandon Jonesd1049182018-03-28 10:02:20 -07004791 GLsizei numParams = 0;
4792
4793 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004794 {
4795 return false;
4796 }
4797
Brandon Jonesd1049182018-03-28 10:02:20 -07004798 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004799 {
4800 return false;
4801 }
4802
Brandon Jonesd1049182018-03-28 10:02:20 -07004803 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004804 return true;
4805}
4806
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004807bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4808 GLuint sampler,
4809 GLenum pname,
4810 GLsizei bufSize,
4811 GLsizei *length,
4812 GLint *params)
4813{
4814 UNIMPLEMENTED();
4815 return false;
4816}
4817
4818bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4819 GLuint sampler,
4820 GLenum pname,
4821 GLsizei bufSize,
4822 GLsizei *length,
4823 GLuint *params)
4824{
4825 UNIMPLEMENTED();
4826 return false;
4827}
4828
Geoff Langc1984ed2016-10-07 12:41:00 -04004829bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4830 GLuint sampler,
4831 GLenum pname,
4832 GLsizei bufSize,
4833 const GLfloat *params)
4834{
4835 if (!ValidateRobustEntryPoint(context, bufSize))
4836 {
4837 return false;
4838 }
4839
4840 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4841}
4842
Geoff Langc1984ed2016-10-07 12:41:00 -04004843bool ValidateSamplerParameterivRobustANGLE(Context *context,
4844 GLuint sampler,
4845 GLenum pname,
4846 GLsizei bufSize,
4847 const GLint *params)
4848{
4849 if (!ValidateRobustEntryPoint(context, bufSize))
4850 {
4851 return false;
4852 }
4853
4854 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4855}
4856
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004857bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4858 GLuint sampler,
4859 GLenum pname,
4860 GLsizei bufSize,
4861 const GLint *param)
4862{
4863 UNIMPLEMENTED();
4864 return false;
4865}
4866
4867bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4868 GLuint sampler,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 const GLuint *param)
4872{
4873 UNIMPLEMENTED();
4874 return false;
4875}
4876
Geoff Lang0b031062016-10-13 14:30:04 -04004877bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4878 GLuint index,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 GLsizei *length,
4882 GLfloat *params)
4883{
4884 if (!ValidateRobustEntryPoint(context, bufSize))
4885 {
4886 return false;
4887 }
4888
Brandon Jonesd1049182018-03-28 10:02:20 -07004889 GLsizei writeLength = 0;
4890
4891 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004892 {
4893 return false;
4894 }
4895
Brandon Jonesd1049182018-03-28 10:02:20 -07004896 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004897 {
4898 return false;
4899 }
4900
Brandon Jonesd1049182018-03-28 10:02:20 -07004901 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004902 return true;
4903}
4904
Geoff Lang0b031062016-10-13 14:30:04 -04004905bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4906 GLuint index,
4907 GLenum pname,
4908 GLsizei bufSize,
4909 GLsizei *length,
4910 GLint *params)
4911{
4912 if (!ValidateRobustEntryPoint(context, bufSize))
4913 {
4914 return false;
4915 }
4916
Brandon Jonesd1049182018-03-28 10:02:20 -07004917 GLsizei writeLength = 0;
4918
4919 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004920 {
4921 return false;
4922 }
4923
Brandon Jonesd1049182018-03-28 10:02:20 -07004924 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004925 {
4926 return false;
4927 }
4928
Brandon Jonesd1049182018-03-28 10:02:20 -07004929 SetRobustLengthParam(length, writeLength);
4930
Geoff Lang0b031062016-10-13 14:30:04 -04004931 return true;
4932}
4933
Geoff Lang0b031062016-10-13 14:30:04 -04004934bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4935 GLuint index,
4936 GLenum pname,
4937 GLsizei bufSize,
4938 GLsizei *length,
4939 void **pointer)
4940{
4941 if (!ValidateRobustEntryPoint(context, bufSize))
4942 {
4943 return false;
4944 }
4945
Brandon Jonesd1049182018-03-28 10:02:20 -07004946 GLsizei writeLength = 0;
4947
4948 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004949 {
4950 return false;
4951 }
4952
Brandon Jonesd1049182018-03-28 10:02:20 -07004953 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004954 {
4955 return false;
4956 }
4957
Brandon Jonesd1049182018-03-28 10:02:20 -07004958 SetRobustLengthParam(length, writeLength);
4959
Geoff Lang0b031062016-10-13 14:30:04 -04004960 return true;
4961}
4962
Geoff Lang0b031062016-10-13 14:30:04 -04004963bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4964 GLuint index,
4965 GLenum pname,
4966 GLsizei bufSize,
4967 GLsizei *length,
4968 GLint *params)
4969{
4970 if (!ValidateRobustEntryPoint(context, bufSize))
4971 {
4972 return false;
4973 }
4974
Brandon Jonesd1049182018-03-28 10:02:20 -07004975 GLsizei writeLength = 0;
4976
4977 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004978 {
4979 return false;
4980 }
4981
Brandon Jonesd1049182018-03-28 10:02:20 -07004982 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 SetRobustLengthParam(length, writeLength);
4988
Geoff Lang0b031062016-10-13 14:30:04 -04004989 return true;
4990}
4991
Geoff Lang0b031062016-10-13 14:30:04 -04004992bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4993 GLuint index,
4994 GLenum pname,
4995 GLsizei bufSize,
4996 GLsizei *length,
4997 GLuint *params)
4998{
4999 if (!ValidateRobustEntryPoint(context, bufSize))
5000 {
5001 return false;
5002 }
5003
Brandon Jonesd1049182018-03-28 10:02:20 -07005004 GLsizei writeLength = 0;
5005
5006 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005012 {
5013 return false;
5014 }
5015
Brandon Jonesd1049182018-03-28 10:02:20 -07005016 SetRobustLengthParam(length, writeLength);
5017
Geoff Lang0b031062016-10-13 14:30:04 -04005018 return true;
5019}
5020
Geoff Lang6899b872016-10-14 11:30:13 -04005021bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5022 GLuint program,
5023 GLuint uniformBlockIndex,
5024 GLenum pname,
5025 GLsizei bufSize,
5026 GLsizei *length,
5027 GLint *params)
5028{
5029 if (!ValidateRobustEntryPoint(context, bufSize))
5030 {
5031 return false;
5032 }
5033
Brandon Jonesd1049182018-03-28 10:02:20 -07005034 GLsizei writeLength = 0;
5035
5036 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5037 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005038 {
5039 return false;
5040 }
5041
Brandon Jonesd1049182018-03-28 10:02:20 -07005042 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005043 {
5044 return false;
5045 }
5046
Brandon Jonesd1049182018-03-28 10:02:20 -07005047 SetRobustLengthParam(length, writeLength);
5048
Geoff Lang6899b872016-10-14 11:30:13 -04005049 return true;
5050}
5051
Brandon Jones416aaf92018-04-10 08:10:16 -07005052bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005053 GLenum target,
5054 GLenum internalformat,
5055 GLenum pname,
5056 GLsizei bufSize,
5057 GLsizei *length,
5058 GLint *params)
5059{
5060 if (!ValidateRobustEntryPoint(context, bufSize))
5061 {
5062 return false;
5063 }
5064
Brandon Jonesd1049182018-03-28 10:02:20 -07005065 GLsizei numParams = 0;
5066
5067 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5068 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005069 {
5070 return false;
5071 }
5072
Brandon Jonesd1049182018-03-28 10:02:20 -07005073 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005074 {
5075 return false;
5076 }
5077
Brandon Jonesd1049182018-03-28 10:02:20 -07005078 SetRobustLengthParam(length, numParams);
5079
Geoff Lang0a9661f2016-10-20 10:59:20 -07005080 return true;
5081}
5082
Jamie Madill5b772312018-03-08 20:28:32 -05005083bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005084 GLuint attribIndex,
5085 GLint size,
5086 GLenum type,
5087 GLboolean pureInteger)
5088{
5089 const Caps &caps = context->getCaps();
5090 if (attribIndex >= caps.maxVertexAttributes)
5091 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005092 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005093 return false;
5094 }
5095
5096 if (size < 1 || size > 4)
5097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005098 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005099 return false;
Shao80957d92017-02-20 21:25:59 +08005100 }
5101
5102 switch (type)
5103 {
5104 case GL_BYTE:
5105 case GL_UNSIGNED_BYTE:
5106 case GL_SHORT:
5107 case GL_UNSIGNED_SHORT:
5108 break;
5109
5110 case GL_INT:
5111 case GL_UNSIGNED_INT:
5112 if (context->getClientMajorVersion() < 3)
5113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidEnum()
5115 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005116 return false;
5117 }
5118 break;
5119
5120 case GL_FIXED:
5121 case GL_FLOAT:
5122 if (pureInteger)
5123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005125 return false;
5126 }
5127 break;
5128
5129 case GL_HALF_FLOAT:
5130 if (context->getClientMajorVersion() < 3)
5131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005132 context->handleError(InvalidEnum()
5133 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005134 return false;
5135 }
5136 if (pureInteger)
5137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005139 return false;
5140 }
5141 break;
5142
5143 case GL_INT_2_10_10_10_REV:
5144 case GL_UNSIGNED_INT_2_10_10_10_REV:
5145 if (context->getClientMajorVersion() < 3)
5146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005147 context->handleError(InvalidEnum()
5148 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005149 return false;
5150 }
5151 if (pureInteger)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005154 return false;
5155 }
5156 if (size != 4)
5157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005158 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5159 "UNSIGNED_INT_2_10_10_10_REV and "
5160 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005161 return false;
5162 }
5163 break;
5164
5165 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005167 return false;
5168 }
5169
5170 return true;
5171}
5172
Geoff Lang76e65652017-03-27 14:58:02 -04005173// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5174// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5175// specified clear value and the type of a buffer that is being cleared generates an
5176// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005177bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005178 GLint drawbuffer,
5179 const GLenum *validComponentTypes,
5180 size_t validComponentTypeCount)
5181{
5182 const FramebufferAttachment *attachment =
5183 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5184 if (attachment)
5185 {
5186 GLenum componentType = attachment->getFormat().info->componentType;
5187 const GLenum *end = validComponentTypes + validComponentTypeCount;
5188 if (std::find(validComponentTypes, end, componentType) == end)
5189 {
5190 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005191 InvalidOperation()
5192 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005193 return false;
5194 }
5195 }
5196
5197 return true;
5198}
5199
Jamie Madill5b772312018-03-08 20:28:32 -05005200bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005201{
5202 if (!ValidateRobustEntryPoint(context, dataSize))
5203 {
5204 return false;
5205 }
5206
Jamie Madill43da7c42018-08-01 11:34:49 -04005207 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005208 if (pixelUnpackBuffer == nullptr)
5209 {
5210 if (dataSize < imageSize)
5211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005212 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005213 }
5214 }
5215 return true;
5216}
5217
Jamie Madill5b772312018-03-08 20:28:32 -05005218bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005219 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005220 GLenum pname,
5221 bool pointerVersion,
5222 GLsizei *numParams)
5223{
5224 if (numParams)
5225 {
5226 *numParams = 0;
5227 }
5228
Corentin Walleze4477002017-12-01 14:39:58 -05005229 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5236 if (!buffer)
5237 {
5238 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242
5243 const Extensions &extensions = context->getExtensions();
5244
5245 switch (pname)
5246 {
5247 case GL_BUFFER_USAGE:
5248 case GL_BUFFER_SIZE:
5249 break;
5250
5251 case GL_BUFFER_ACCESS_OES:
5252 if (!extensions.mapBuffer)
5253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005254 context->handleError(InvalidEnum()
5255 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258 break;
5259
5260 case GL_BUFFER_MAPPED:
5261 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5262 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5263 !extensions.mapBufferRange)
5264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005265 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5266 "GL_OES_mapbuffer or "
5267 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270 break;
5271
5272 case GL_BUFFER_MAP_POINTER:
5273 if (!pointerVersion)
5274 {
5275 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005276 InvalidEnum()
5277 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280 break;
5281
5282 case GL_BUFFER_ACCESS_FLAGS:
5283 case GL_BUFFER_MAP_OFFSET:
5284 case GL_BUFFER_MAP_LENGTH:
5285 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005287 context->handleError(InvalidEnum()
5288 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291 break;
5292
5293 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005294 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005295 return false;
5296 }
5297
5298 // All buffer parameter queries return one value.
5299 if (numParams)
5300 {
5301 *numParams = 1;
5302 }
5303
5304 return true;
5305}
5306
5307bool ValidateGetRenderbufferParameterivBase(Context *context,
5308 GLenum target,
5309 GLenum pname,
5310 GLsizei *length)
5311{
5312 if (length)
5313 {
5314 *length = 0;
5315 }
5316
5317 if (target != GL_RENDERBUFFER)
5318 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005319 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5324 if (renderbuffer == nullptr)
5325 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 return false;
5328 }
5329
5330 switch (pname)
5331 {
5332 case GL_RENDERBUFFER_WIDTH:
5333 case GL_RENDERBUFFER_HEIGHT:
5334 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5335 case GL_RENDERBUFFER_RED_SIZE:
5336 case GL_RENDERBUFFER_GREEN_SIZE:
5337 case GL_RENDERBUFFER_BLUE_SIZE:
5338 case GL_RENDERBUFFER_ALPHA_SIZE:
5339 case GL_RENDERBUFFER_DEPTH_SIZE:
5340 case GL_RENDERBUFFER_STENCIL_SIZE:
5341 break;
5342
5343 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5344 if (!context->getExtensions().framebufferMultisample)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349 break;
5350
5351 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005352 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005353 return false;
5354 }
5355
5356 if (length)
5357 {
5358 *length = 1;
5359 }
5360 return true;
5361}
5362
5363bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5364{
5365 if (length)
5366 {
5367 *length = 0;
5368 }
5369
5370 if (GetValidShader(context, shader) == nullptr)
5371 {
5372 return false;
5373 }
5374
5375 switch (pname)
5376 {
5377 case GL_SHADER_TYPE:
5378 case GL_DELETE_STATUS:
5379 case GL_COMPILE_STATUS:
5380 case GL_INFO_LOG_LENGTH:
5381 case GL_SHADER_SOURCE_LENGTH:
5382 break;
5383
5384 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5385 if (!context->getExtensions().translatedShaderSource)
5386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 return false;
5389 }
5390 break;
5391
Jamie Madill44a6fbf2018-10-02 13:38:56 -04005392 case GL_COMPLETION_STATUS_KHR:
5393 if (!context->getExtensions().parallelShaderCompile)
5394 {
5395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
5396 return false;
5397 }
5398 break;
5399
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
5404
5405 if (length)
5406 {
5407 *length = 1;
5408 }
5409 return true;
5410}
5411
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005412bool ValidateGetTexParameterBase(Context *context,
5413 TextureType target,
5414 GLenum pname,
5415 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005416{
5417 if (length)
5418 {
5419 *length = 0;
5420 }
5421
5422 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5423 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005425 return false;
5426 }
5427
5428 if (context->getTargetTexture(target) == nullptr)
5429 {
5430 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 return false;
5433 }
5434
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005435 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5436 {
5437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5438 return false;
5439 }
5440
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 switch (pname)
5442 {
5443 case GL_TEXTURE_MAG_FILTER:
5444 case GL_TEXTURE_MIN_FILTER:
5445 case GL_TEXTURE_WRAP_S:
5446 case GL_TEXTURE_WRAP_T:
5447 break;
5448
5449 case GL_TEXTURE_USAGE_ANGLE:
5450 if (!context->getExtensions().textureUsage)
5451 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455 break;
5456
5457 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005458 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 break;
5463
5464 case GL_TEXTURE_IMMUTABLE_FORMAT:
5465 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470 break;
5471
5472 case GL_TEXTURE_WRAP_R:
5473 case GL_TEXTURE_IMMUTABLE_LEVELS:
5474 case GL_TEXTURE_SWIZZLE_R:
5475 case GL_TEXTURE_SWIZZLE_G:
5476 case GL_TEXTURE_SWIZZLE_B:
5477 case GL_TEXTURE_SWIZZLE_A:
5478 case GL_TEXTURE_BASE_LEVEL:
5479 case GL_TEXTURE_MAX_LEVEL:
5480 case GL_TEXTURE_MIN_LOD:
5481 case GL_TEXTURE_MAX_LOD:
5482 case GL_TEXTURE_COMPARE_MODE:
5483 case GL_TEXTURE_COMPARE_FUNC:
5484 if (context->getClientMajorVersion() < 3)
5485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005486 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489 break;
5490
5491 case GL_TEXTURE_SRGB_DECODE_EXT:
5492 if (!context->getExtensions().textureSRGBDecode)
5493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005494 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
5497 break;
5498
Yunchao Hebacaa712018-01-30 14:01:39 +08005499 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5500 if (context->getClientVersion() < Version(3, 1))
5501 {
5502 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5503 return false;
5504 }
5505 break;
5506
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005507 case GL_GENERATE_MIPMAP:
5508 case GL_TEXTURE_CROP_RECT_OES:
5509 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5510 // after GL_OES_draw_texture functionality implemented
5511 if (context->getClientMajorVersion() > 1)
5512 {
5513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5514 return false;
5515 }
5516 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 return false;
5520 }
5521
5522 if (length)
5523 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005524 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005525 }
5526 return true;
5527}
5528
5529bool ValidateGetVertexAttribBase(Context *context,
5530 GLuint index,
5531 GLenum pname,
5532 GLsizei *length,
5533 bool pointer,
5534 bool pureIntegerEntryPoint)
5535{
5536 if (length)
5537 {
5538 *length = 0;
5539 }
5540
5541 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005543 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005544 return false;
5545 }
5546
5547 if (index >= context->getCaps().maxVertexAttributes)
5548 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005549 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005550 return false;
5551 }
5552
5553 if (pointer)
5554 {
5555 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5556 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 return false;
5559 }
5560 }
5561 else
5562 {
5563 switch (pname)
5564 {
5565 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5566 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5567 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5568 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5569 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5570 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5571 case GL_CURRENT_VERTEX_ATTRIB:
5572 break;
5573
5574 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5575 static_assert(
5576 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5577 "ANGLE extension enums not equal to GL enums.");
5578 if (context->getClientMajorVersion() < 3 &&
5579 !context->getExtensions().instancedArrays)
5580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005581 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5582 "requires OpenGL ES 3.0 or "
5583 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005584 return false;
5585 }
5586 break;
5587
5588 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5589 if (context->getClientMajorVersion() < 3)
5590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005591 context->handleError(
5592 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595 break;
5596
5597 case GL_VERTEX_ATTRIB_BINDING:
5598 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5599 if (context->getClientVersion() < ES_3_1)
5600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005601 context->handleError(InvalidEnum()
5602 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005603 return false;
5604 }
5605 break;
5606
5607 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 return false;
5610 }
5611 }
5612
5613 if (length)
5614 {
5615 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5616 {
5617 *length = 4;
5618 }
5619 else
5620 {
5621 *length = 1;
5622 }
5623 }
5624
5625 return true;
5626}
5627
Jamie Madill4928b7c2017-06-20 12:57:39 -04005628bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 GLint x,
5630 GLint y,
5631 GLsizei width,
5632 GLsizei height,
5633 GLenum format,
5634 GLenum type,
5635 GLsizei bufSize,
5636 GLsizei *length,
5637 GLsizei *columns,
5638 GLsizei *rows,
5639 void *pixels)
5640{
5641 if (length != nullptr)
5642 {
5643 *length = 0;
5644 }
5645 if (rows != nullptr)
5646 {
5647 *rows = 0;
5648 }
5649 if (columns != nullptr)
5650 {
5651 *columns = 0;
5652 }
5653
5654 if (width < 0 || height < 0)
5655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005657 return false;
5658 }
5659
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005660 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005661
Jamie Madill427064d2018-04-13 16:20:34 -04005662 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005664 return false;
5665 }
5666
Jamie Madille98b1b52018-03-08 09:47:23 -05005667 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005669 return false;
5670 }
5671
Jamie Madill690c8eb2018-03-12 15:20:03 -04005672 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 ASSERT(framebuffer);
5674
5675 if (framebuffer->getReadBufferState() == GL_NONE)
5676 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005678 return false;
5679 }
5680
5681 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5682 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5683 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5684 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5685 // situation is an application error that would lead to a crash in ANGLE.
5686 if (readBuffer == nullptr)
5687 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005689 return false;
5690 }
5691
Martin Radev28031682017-07-28 14:47:56 +03005692 // ANGLE_multiview, Revision 1:
5693 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005694 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5695 // in the current read framebuffer is more than one.
5696 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005697 {
5698 context->handleError(InvalidFramebufferOperation()
5699 << "Attempting to read from a multi-view framebuffer.");
5700 return false;
5701 }
5702
Geoff Lang280ba992017-04-18 16:30:58 -04005703 if (context->getExtensions().webglCompatibility)
5704 {
5705 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5706 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5707 // and type before validating the combination of format and type. However, the
5708 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5709 // verifies that GL_INVALID_OPERATION is generated.
5710 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5711 // dEQP/WebGL.
5712 if (!ValidReadPixelsFormatEnum(context, format))
5713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005715 return false;
5716 }
5717
5718 if (!ValidReadPixelsTypeEnum(context, type))
5719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005721 return false;
5722 }
5723 }
5724
Jamie Madill690c8eb2018-03-12 15:20:03 -04005725 GLenum currentFormat = GL_NONE;
5726 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5727
5728 GLenum currentType = GL_NONE;
5729 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5730
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5732
5733 bool validFormatTypeCombination =
5734 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5735
5736 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005739 return false;
5740 }
5741
5742 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005743 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005744 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5745 {
5746 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005747 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 return false;
5749 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005750 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5751 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5752 {
5753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5754 return false;
5755 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005756
5757 // .. the data would be packed to the buffer object such that the memory writes required
5758 // would exceed the data store size.
5759 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005760 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 const auto &pack = context->getGLState().getPackState();
5762
Jamie Madillca2ff382018-07-11 09:01:17 -04005763 GLuint endByte = 0;
5764 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 return false;
5768 }
5769
Jamie Madillbe849e42017-05-02 15:49:00 -04005770 if (bufSize >= 0)
5771 {
5772 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5773 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005775 return false;
5776 }
5777 }
5778
5779 if (pixelPackBuffer != nullptr)
5780 {
5781 CheckedNumeric<size_t> checkedEndByte(endByte);
5782 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5783 checkedEndByte += checkedOffset;
5784
5785 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5786 {
5787 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 return false;
5790 }
5791 }
5792
5793 if (pixelPackBuffer == nullptr && length != nullptr)
5794 {
5795 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005798 return false;
5799 }
5800
5801 *length = static_cast<GLsizei>(endByte);
5802 }
5803
Geoff Langa953b522018-02-21 16:56:23 -05005804 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 angle::CheckedNumeric<int> clippedExtent(length);
5806 if (start < 0)
5807 {
5808 // "subtract" the area that is less than 0
5809 clippedExtent += start;
5810 }
5811
Geoff Langa953b522018-02-21 16:56:23 -05005812 angle::CheckedNumeric<int> readExtent = start;
5813 readExtent += length;
5814 if (!readExtent.IsValid())
5815 {
5816 return false;
5817 }
5818
5819 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 {
5821 // Subtract the region to the right of the read buffer
5822 clippedExtent -= (readExtent - bufferSize);
5823 }
5824
5825 if (!clippedExtent.IsValid())
5826 {
Geoff Langa953b522018-02-21 16:56:23 -05005827 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 }
5829
Geoff Langa953b522018-02-21 16:56:23 -05005830 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5831 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 };
5833
Geoff Langa953b522018-02-21 16:56:23 -05005834 GLsizei writtenColumns = 0;
5835 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5836 {
5837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5838 return false;
5839 }
5840
5841 GLsizei writtenRows = 0;
5842 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5843 {
5844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5845 return false;
5846 }
5847
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 if (columns != nullptr)
5849 {
Geoff Langa953b522018-02-21 16:56:23 -05005850 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 }
5852
5853 if (rows != nullptr)
5854 {
Geoff Langa953b522018-02-21 16:56:23 -05005855 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005856 }
5857
5858 return true;
5859}
5860
5861template <typename ParamType>
5862bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005863 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 GLenum pname,
5865 GLsizei bufSize,
5866 const ParamType *params)
5867{
5868 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005870 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 return false;
5872 }
5873
5874 if (context->getTargetTexture(target) == nullptr)
5875 {
5876 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005878 return false;
5879 }
5880
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005881 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005882 if (bufSize >= 0 && bufSize < minBufSize)
5883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 return false;
5886 }
5887
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005888 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5889 {
5890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5891 return false;
5892 }
5893
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 switch (pname)
5895 {
5896 case GL_TEXTURE_WRAP_R:
5897 case GL_TEXTURE_SWIZZLE_R:
5898 case GL_TEXTURE_SWIZZLE_G:
5899 case GL_TEXTURE_SWIZZLE_B:
5900 case GL_TEXTURE_SWIZZLE_A:
5901 case GL_TEXTURE_BASE_LEVEL:
5902 case GL_TEXTURE_MAX_LEVEL:
5903 case GL_TEXTURE_COMPARE_MODE:
5904 case GL_TEXTURE_COMPARE_FUNC:
5905 case GL_TEXTURE_MIN_LOD:
5906 case GL_TEXTURE_MAX_LOD:
5907 if (context->getClientMajorVersion() < 3)
5908 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005910 return false;
5911 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005912 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005914 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5915 "available without "
5916 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 return false;
5918 }
5919 break;
5920
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005921 case GL_GENERATE_MIPMAP:
5922 case GL_TEXTURE_CROP_RECT_OES:
5923 if (context->getClientMajorVersion() > 1)
5924 {
5925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5926 return false;
5927 }
5928 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 default:
5930 break;
5931 }
5932
Olli Etuahod310a432018-08-24 15:40:23 +03005933 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005934 {
5935 switch (pname)
5936 {
5937 case GL_TEXTURE_MIN_FILTER:
5938 case GL_TEXTURE_MAG_FILTER:
5939 case GL_TEXTURE_WRAP_S:
5940 case GL_TEXTURE_WRAP_T:
5941 case GL_TEXTURE_WRAP_R:
5942 case GL_TEXTURE_MIN_LOD:
5943 case GL_TEXTURE_MAX_LOD:
5944 case GL_TEXTURE_COMPARE_MODE:
5945 case GL_TEXTURE_COMPARE_FUNC:
5946 context->handleError(InvalidEnum()
5947 << "Invalid parameter for 2D multisampled textures.");
5948 return false;
5949 }
5950 }
5951
Jamie Madillbe849e42017-05-02 15:49:00 -04005952 switch (pname)
5953 {
5954 case GL_TEXTURE_WRAP_S:
5955 case GL_TEXTURE_WRAP_T:
5956 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005957 {
5958 bool restrictedWrapModes =
5959 target == TextureType::External || target == TextureType::Rectangle;
5960 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005961 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005962 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005963 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005964 }
5965 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005966
5967 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005968 {
5969 bool restrictedMinFilter =
5970 target == TextureType::External || target == TextureType::Rectangle;
5971 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005972 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005973 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005974 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005975 }
5976 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005977
5978 case GL_TEXTURE_MAG_FILTER:
5979 if (!ValidateTextureMagFilterValue(context, params))
5980 {
5981 return false;
5982 }
5983 break;
5984
5985 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005986 if (!context->getExtensions().textureUsage)
5987 {
5988 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5989 return false;
5990 }
5991
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 switch (ConvertToGLenum(params[0]))
5993 {
5994 case GL_NONE:
5995 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5996 break;
5997
5998 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
6002 break;
6003
6004 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006005 {
6006 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6007 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006008 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006009 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006011 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6012 }
6013 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006014
6015 case GL_TEXTURE_MIN_LOD:
6016 case GL_TEXTURE_MAX_LOD:
6017 // any value is permissible
6018 break;
6019
6020 case GL_TEXTURE_COMPARE_MODE:
6021 if (!ValidateTextureCompareModeValue(context, params))
6022 {
6023 return false;
6024 }
6025 break;
6026
6027 case GL_TEXTURE_COMPARE_FUNC:
6028 if (!ValidateTextureCompareFuncValue(context, params))
6029 {
6030 return false;
6031 }
6032 break;
6033
6034 case GL_TEXTURE_SWIZZLE_R:
6035 case GL_TEXTURE_SWIZZLE_G:
6036 case GL_TEXTURE_SWIZZLE_B:
6037 case GL_TEXTURE_SWIZZLE_A:
6038 switch (ConvertToGLenum(params[0]))
6039 {
6040 case GL_RED:
6041 case GL_GREEN:
6042 case GL_BLUE:
6043 case GL_ALPHA:
6044 case GL_ZERO:
6045 case GL_ONE:
6046 break;
6047
6048 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006049 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006050 return false;
6051 }
6052 break;
6053
6054 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006055 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006057 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006058 return false;
6059 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006060 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006062 context->handleError(InvalidOperation()
6063 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006064 return false;
6065 }
Olli Etuahod310a432018-08-24 15:40:23 +03006066 if ((target == TextureType::_2DMultisample ||
6067 target == TextureType::_2DMultisampleArray) &&
6068 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006069 {
6070 context->handleError(InvalidOperation()
6071 << "Base level must be 0 for multisampled textures.");
6072 return false;
6073 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006074 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006075 {
6076 context->handleError(InvalidOperation()
6077 << "Base level must be 0 for rectangle textures.");
6078 return false;
6079 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 break;
6081
6082 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006083 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006084 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006085 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006086 return false;
6087 }
6088 break;
6089
6090 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6091 if (context->getClientVersion() < Version(3, 1))
6092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006094 return false;
6095 }
6096 switch (ConvertToGLenum(params[0]))
6097 {
6098 case GL_DEPTH_COMPONENT:
6099 case GL_STENCIL_INDEX:
6100 break;
6101
6102 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006104 return false;
6105 }
6106 break;
6107
6108 case GL_TEXTURE_SRGB_DECODE_EXT:
6109 if (!ValidateTextureSRGBDecodeValue(context, params))
6110 {
6111 return false;
6112 }
6113 break;
6114
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006115 case GL_GENERATE_MIPMAP:
6116 case GL_TEXTURE_CROP_RECT_OES:
6117 if (context->getClientMajorVersion() > 1)
6118 {
6119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6120 return false;
6121 }
6122 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006123 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006125 return false;
6126 }
6127
6128 return true;
6129}
6130
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006131template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6132template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006133
Jamie Madill5b772312018-03-08 20:28:32 -05006134bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006135{
6136 if (index >= MAX_VERTEX_ATTRIBS)
6137 {
6138 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6139 return false;
6140 }
6141
6142 return true;
6143}
6144
6145bool ValidateGetActiveUniformBlockivBase(Context *context,
6146 GLuint program,
6147 GLuint uniformBlockIndex,
6148 GLenum pname,
6149 GLsizei *length)
6150{
6151 if (length)
6152 {
6153 *length = 0;
6154 }
6155
6156 if (context->getClientMajorVersion() < 3)
6157 {
6158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6159 return false;
6160 }
6161
6162 Program *programObject = GetValidProgram(context, program);
6163 if (!programObject)
6164 {
6165 return false;
6166 }
6167
6168 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6169 {
6170 context->handleError(InvalidValue()
6171 << "uniformBlockIndex exceeds active uniform block count.");
6172 return false;
6173 }
6174
6175 switch (pname)
6176 {
6177 case GL_UNIFORM_BLOCK_BINDING:
6178 case GL_UNIFORM_BLOCK_DATA_SIZE:
6179 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6180 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6181 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6182 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6183 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6184 break;
6185
6186 default:
6187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6188 return false;
6189 }
6190
6191 if (length)
6192 {
6193 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6194 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006195 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006196 programObject->getUniformBlockByIndex(uniformBlockIndex);
6197 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6198 }
6199 else
6200 {
6201 *length = 1;
6202 }
6203 }
6204
6205 return true;
6206}
6207
Jamie Madill9696d072017-08-26 23:19:57 -04006208template <typename ParamType>
6209bool ValidateSamplerParameterBase(Context *context,
6210 GLuint sampler,
6211 GLenum pname,
6212 GLsizei bufSize,
6213 ParamType *params)
6214{
6215 if (context->getClientMajorVersion() < 3)
6216 {
6217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6218 return false;
6219 }
6220
6221 if (!context->isSampler(sampler))
6222 {
6223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6224 return false;
6225 }
6226
6227 const GLsizei minBufSize = 1;
6228 if (bufSize >= 0 && bufSize < minBufSize)
6229 {
6230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6231 return false;
6232 }
6233
6234 switch (pname)
6235 {
6236 case GL_TEXTURE_WRAP_S:
6237 case GL_TEXTURE_WRAP_T:
6238 case GL_TEXTURE_WRAP_R:
6239 if (!ValidateTextureWrapModeValue(context, params, false))
6240 {
6241 return false;
6242 }
6243 break;
6244
6245 case GL_TEXTURE_MIN_FILTER:
6246 if (!ValidateTextureMinFilterValue(context, params, false))
6247 {
6248 return false;
6249 }
6250 break;
6251
6252 case GL_TEXTURE_MAG_FILTER:
6253 if (!ValidateTextureMagFilterValue(context, params))
6254 {
6255 return false;
6256 }
6257 break;
6258
6259 case GL_TEXTURE_MIN_LOD:
6260 case GL_TEXTURE_MAX_LOD:
6261 // any value is permissible
6262 break;
6263
6264 case GL_TEXTURE_COMPARE_MODE:
6265 if (!ValidateTextureCompareModeValue(context, params))
6266 {
6267 return false;
6268 }
6269 break;
6270
6271 case GL_TEXTURE_COMPARE_FUNC:
6272 if (!ValidateTextureCompareFuncValue(context, params))
6273 {
6274 return false;
6275 }
6276 break;
6277
6278 case GL_TEXTURE_SRGB_DECODE_EXT:
6279 if (!ValidateTextureSRGBDecodeValue(context, params))
6280 {
6281 return false;
6282 }
6283 break;
6284
Luc Ferron1b1a8642018-01-23 15:12:01 -05006285 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6286 {
6287 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6288 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6289 {
6290 return false;
6291 }
6292 }
6293 break;
6294
Jamie Madill9696d072017-08-26 23:19:57 -04006295 default:
6296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6297 return false;
6298 }
6299
6300 return true;
6301}
6302
6303template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6304template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6305
6306bool ValidateGetSamplerParameterBase(Context *context,
6307 GLuint sampler,
6308 GLenum pname,
6309 GLsizei *length)
6310{
6311 if (length)
6312 {
6313 *length = 0;
6314 }
6315
6316 if (context->getClientMajorVersion() < 3)
6317 {
6318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6319 return false;
6320 }
6321
6322 if (!context->isSampler(sampler))
6323 {
6324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6325 return false;
6326 }
6327
6328 switch (pname)
6329 {
6330 case GL_TEXTURE_WRAP_S:
6331 case GL_TEXTURE_WRAP_T:
6332 case GL_TEXTURE_WRAP_R:
6333 case GL_TEXTURE_MIN_FILTER:
6334 case GL_TEXTURE_MAG_FILTER:
6335 case GL_TEXTURE_MIN_LOD:
6336 case GL_TEXTURE_MAX_LOD:
6337 case GL_TEXTURE_COMPARE_MODE:
6338 case GL_TEXTURE_COMPARE_FUNC:
6339 break;
6340
Luc Ferron1b1a8642018-01-23 15:12:01 -05006341 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6342 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6343 {
6344 return false;
6345 }
6346 break;
6347
Jamie Madill9696d072017-08-26 23:19:57 -04006348 case GL_TEXTURE_SRGB_DECODE_EXT:
6349 if (!context->getExtensions().textureSRGBDecode)
6350 {
6351 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6352 return false;
6353 }
6354 break;
6355
6356 default:
6357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6358 return false;
6359 }
6360
6361 if (length)
6362 {
6363 *length = 1;
6364 }
6365 return true;
6366}
6367
6368bool ValidateGetInternalFormativBase(Context *context,
6369 GLenum target,
6370 GLenum internalformat,
6371 GLenum pname,
6372 GLsizei bufSize,
6373 GLsizei *numParams)
6374{
6375 if (numParams)
6376 {
6377 *numParams = 0;
6378 }
6379
6380 if (context->getClientMajorVersion() < 3)
6381 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006383 return false;
6384 }
6385
6386 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006387 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006388 {
6389 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6390 return false;
6391 }
6392
6393 switch (target)
6394 {
6395 case GL_RENDERBUFFER:
6396 break;
6397
6398 case GL_TEXTURE_2D_MULTISAMPLE:
6399 if (context->getClientVersion() < ES_3_1)
6400 {
Olli Etuahod310a432018-08-24 15:40:23 +03006401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006402 return false;
6403 }
6404 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006405 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6406 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006407 {
6408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6409 return false;
6410 }
6411 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006412 default:
6413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6414 return false;
6415 }
6416
6417 if (bufSize < 0)
6418 {
6419 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6420 return false;
6421 }
6422
6423 GLsizei maxWriteParams = 0;
6424 switch (pname)
6425 {
6426 case GL_NUM_SAMPLE_COUNTS:
6427 maxWriteParams = 1;
6428 break;
6429
6430 case GL_SAMPLES:
6431 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6432 break;
6433
6434 default:
6435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6436 return false;
6437 }
6438
6439 if (numParams)
6440 {
6441 // glGetInternalFormativ will not overflow bufSize
6442 *numParams = std::min(bufSize, maxWriteParams);
6443 }
6444
6445 return true;
6446}
6447
Jamie Madille98b1b52018-03-08 09:47:23 -05006448bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6449{
Jamie Madill427064d2018-04-13 16:20:34 -04006450 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006451 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006452 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006453 return false;
6454 }
6455 return true;
6456}
6457
Lingfeng Yang038dd532018-03-29 17:31:52 -07006458bool ValidateMultitextureUnit(Context *context, GLenum texture)
6459{
6460 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6461 {
6462 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6463 return false;
6464 }
6465 return true;
6466}
6467
Olli Etuahod310a432018-08-24 15:40:23 +03006468bool ValidateTexStorageMultisample(Context *context,
6469 TextureType target,
6470 GLsizei samples,
6471 GLint internalFormat,
6472 GLsizei width,
6473 GLsizei height)
6474{
6475 const Caps &caps = context->getCaps();
6476 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6477 static_cast<GLuint>(height) > caps.max2DTextureSize)
6478 {
6479 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6480 return false;
6481 }
6482
6483 if (samples == 0)
6484 {
6485 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6486 return false;
6487 }
6488
6489 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6490 if (!formatCaps.textureAttachment)
6491 {
6492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6493 return false;
6494 }
6495
6496 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6497 // is one of the unsized base internalformats listed in table 8.11.
6498 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6499 if (formatInfo.internalFormat == GL_NONE)
6500 {
6501 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6502 return false;
6503 }
6504
6505 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6506 {
6507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6508 return false;
6509 }
6510
6511 Texture *texture = context->getTargetTexture(target);
6512 if (!texture || texture->id() == 0)
6513 {
6514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6515 return false;
6516 }
6517
6518 if (texture->getImmutableFormat())
6519 {
6520 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6521 return false;
6522 }
6523 return true;
6524}
6525
Jamie Madillc29968b2016-01-20 11:17:23 -05006526} // namespace gl