blob: 9e93caee9135f77edbdb73eecb19522aa7792ba7 [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{
388 const Program *program = context->getGLState().getProgram();
389 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();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400400 const Program *program = context->getGLState().getProgram();
401 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
658 Program *program = state.getProgram();
659
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 Madill5b772312018-03-08 20:28:32 -05001014Program *GetValidProgram(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
Dian Xiang769769a2015-09-09 15:20:08 -07001021 Program *validProgram = context->getProgram(id);
1022
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 Madill5b772312018-03-08 20:28:32 -05001038Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001039{
1040 // See ValidProgram for spec details.
1041
1042 Shader *validShader = context->getShader(id);
1043
1044 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001045 {
Dian Xiang769769a2015-09-09 15:20:08 -07001046 if (context->getProgram(id))
1047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001049 }
1050 else
1051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001052 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001053 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001054 }
Dian Xiang769769a2015-09-09 15:20:08 -07001055
1056 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001057}
1058
Jamie Madill43da7c42018-08-01 11:34:49 -04001059bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001060{
Geoff Langfa125c92017-10-24 13:01:46 -04001061 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001062 {
Geoff Langfa125c92017-10-24 13:01:46 -04001063 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1064 {
1065 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1066 return false;
1067 }
Jamie Madillb4472272014-07-03 10:38:55 -04001068
Geoff Langfa125c92017-10-24 13:01:46 -04001069 // Color attachment 0 is validated below because it is always valid
1070 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001071 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001072 {
Geoff Langfa125c92017-10-24 13:01:46 -04001073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001074 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001075 }
1076 }
1077 else
1078 {
1079 switch (attachment)
1080 {
Geoff Langfa125c92017-10-24 13:01:46 -04001081 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001082 case GL_DEPTH_ATTACHMENT:
1083 case GL_STENCIL_ATTACHMENT:
1084 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001085
He Yunchaoced53ae2016-11-29 15:00:51 +08001086 case GL_DEPTH_STENCIL_ATTACHMENT:
1087 if (!context->getExtensions().webglCompatibility &&
1088 context->getClientMajorVersion() < 3)
1089 {
Geoff Langfa125c92017-10-24 13:01:46 -04001090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 return false;
1092 }
1093 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001094
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100
1101 return true;
1102}
1103
Jamie Madill5b772312018-03-08 20:28:32 -05001104bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 GLenum target,
1106 GLsizei samples,
1107 GLenum internalformat,
1108 GLsizei width,
1109 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110{
1111 switch (target)
1112 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001113 case GL_RENDERBUFFER:
1114 break;
1115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119
1120 if (width < 0 || height < 0 || samples < 0)
1121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001122 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001123 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 }
1125
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001126 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1127 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1128
1129 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001130 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001132 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001133 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 }
1135
1136 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1137 // 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 -08001138 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001139 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001140 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001143 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 }
1145
Geoff Langaae65a42014-05-26 12:43:44 -04001146 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001152 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 if (handle == 0)
1154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 return true;
1160}
1161
Jamie Madill43da7c42018-08-01 11:34:49 -04001162bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001163 GLenum target,
1164 GLenum attachment,
1165 GLenum renderbuffertarget,
1166 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167{
Geoff Lange8afa902017-09-27 15:00:43 -04001168 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001172 }
1173
Jamie Madill43da7c42018-08-01 11:34:49 -04001174 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001175
Jamie Madill84115c92015-04-23 15:00:07 -04001176 ASSERT(framebuffer);
1177 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001181 }
1182
Jamie Madillb4472272014-07-03 10:38:55 -04001183 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001184 {
Jamie Madillb4472272014-07-03 10:38:55 -04001185 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001186 }
1187
Jamie Madillab9d82c2014-01-21 16:38:14 -05001188 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1189 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1190 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1191 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1192 if (renderbuffer != 0)
1193 {
1194 if (!context->getRenderbuffer(renderbuffer))
1195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001197 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001198 }
1199 }
1200
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 return true;
1202}
1203
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001204bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001205 GLint srcX0,
1206 GLint srcY0,
1207 GLint srcX1,
1208 GLint srcY1,
1209 GLint dstX0,
1210 GLint dstY0,
1211 GLint dstX1,
1212 GLint dstY1,
1213 GLbitfield mask,
1214 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215{
1216 switch (filter)
1217 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 case GL_NEAREST:
1219 break;
1220 case GL_LINEAR:
1221 break;
1222 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
1227 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1228 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001229 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001231 }
1232
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1234 // color buffer, leaving only nearest being unfiltered from above
1235 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1236 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 }
1240
Jamie Madill7f232932018-09-12 11:03:06 -04001241 const auto &glState = context->getGLState();
1242 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1243 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001244
1245 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001247 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
Jamie Madill427064d2018-04-13 16:20:34 -04001251 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001252 {
Jamie Madill48faf802014-11-06 15:27:22 -05001253 return false;
1254 }
1255
Jamie Madill427064d2018-04-13 16:20:34 -04001256 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001257 {
Jamie Madill48faf802014-11-06 15:27:22 -05001258 return false;
1259 }
1260
Qin Jiajiaaef92162018-02-27 13:51:44 +08001261 if (readFramebuffer->id() == drawFramebuffer->id())
1262 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001264 return false;
1265 }
1266
Jamie Madille98b1b52018-03-08 09:47:23 -05001267 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 {
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001272 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1273 // always run it in order to avoid triggering driver bugs.
1274 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1275 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001276 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001277 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1278 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001279 }
1280
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1282
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 if (mask & GL_COLOR_BUFFER_BIT)
1284 {
Jamie Madill7f232932018-09-12 11:03:06 -04001285 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1286 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287
He Yunchao66a41a22016-12-15 16:45:05 +08001288 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001290 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291
Geoff Langa15472a2015-08-11 11:48:03 -04001292 for (size_t drawbufferIdx = 0;
1293 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 {
Geoff Langa15472a2015-08-11 11:48:03 -04001295 const FramebufferAttachment *attachment =
1296 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1297 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001299 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300
Geoff Langb2f3d052013-08-13 12:49:27 -04001301 // The GL ES 3.0.2 spec (pg 193) states that:
1302 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001303 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1304 // as well
1305 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1306 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001307 // Changes with EXT_color_buffer_float:
1308 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001309 GLenum readComponentType = readFormat.info->componentType;
1310 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001311 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001312 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001313 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001314 drawComponentType == GL_SIGNED_NORMALIZED);
1315
1316 if (extensions.colorBufferFloat)
1317 {
1318 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1319 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1320
1321 if (readFixedOrFloat != drawFixedOrFloat)
1322 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001323 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1324 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001325 return false;
1326 }
1327 }
1328 else if (readFixedPoint != drawFixedPoint)
1329 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001330 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1331 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001332 return false;
1333 }
1334
1335 if (readComponentType == GL_UNSIGNED_INT &&
1336 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1339 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001340 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 }
1342
Jamie Madill6163c752015-12-07 16:32:59 -05001343 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001345 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1346 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 }
1349
Jamie Madilla3944d42016-07-22 22:13:26 -04001350 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001351 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001353 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1354 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001355 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 }
Geoff Lange4915782017-04-12 15:19:07 -04001357
1358 if (context->getExtensions().webglCompatibility &&
1359 *readColorBuffer == *attachment)
1360 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001361 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001362 return false;
1363 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
1365 }
1366
Jamie Madilla3944d42016-07-22 22:13:26 -04001367 if ((readFormat.info->componentType == GL_INT ||
1368 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1369 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
He Yunchao66a41a22016-12-15 16:45:05 +08001375 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1376 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1377 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1378 // situation is an application error that would lead to a crash in ANGLE.
1379 else if (drawFramebuffer->hasEnabledDrawBuffer())
1380 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001381 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001382 return false;
1383 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
1385
He Yunchaoced53ae2016-11-29 15:00:51 +08001386 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001387 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1388 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001390 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001392 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001393 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001394 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001395 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001397 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Kenneth Russell69382852017-07-21 16:38:44 -04001399 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001401 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1402 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001406 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001408 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1409 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
Geoff Lange4915782017-04-12 15:19:07 -04001412
1413 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1414 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001416 return false;
1417 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
He Yunchao66a41a22016-12-15 16:45:05 +08001419 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1420 else if (drawBuffer)
1421 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001423 return false;
1424 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
1426 }
1427
Martin Radeva3ed4572017-07-27 18:29:37 +03001428 // ANGLE_multiview, Revision 1:
1429 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001430 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1431 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1432 // views in the current read framebuffer is more than one.
1433 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001434 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001435 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001436 return false;
1437 }
1438 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1439 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001440 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001441 return false;
1442 }
1443
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 return true;
1445}
1446
Jamie Madill4928b7c2017-06-20 12:57:39 -04001447bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001448 GLint x,
1449 GLint y,
1450 GLsizei width,
1451 GLsizei height,
1452 GLenum format,
1453 GLenum type,
1454 GLsizei bufSize,
1455 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001456 GLsizei *columns,
1457 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001458 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001459{
1460 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001462 return false;
1463 }
1464
Brandon Jonesd1049182018-03-28 10:02:20 -07001465 GLsizei writeLength = 0;
1466 GLsizei writeColumns = 0;
1467 GLsizei writeRows = 0;
1468
1469 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1470 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001471 {
Geoff Langb1196682014-07-23 13:47:29 -04001472 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001473 }
1474
Brandon Jonesd1049182018-03-28 10:02:20 -07001475 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001476 {
Geoff Langb1196682014-07-23 13:47:29 -04001477 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001478 }
1479
Brandon Jonesd1049182018-03-28 10:02:20 -07001480 SetRobustLengthParam(length, writeLength);
1481 SetRobustLengthParam(columns, writeColumns);
1482 SetRobustLengthParam(rows, writeRows);
1483
Jamie Madillc29968b2016-01-20 11:17:23 -05001484 return true;
1485}
1486
1487bool ValidateReadnPixelsEXT(Context *context,
1488 GLint x,
1489 GLint y,
1490 GLsizei width,
1491 GLsizei height,
1492 GLenum format,
1493 GLenum type,
1494 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001495 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001496{
1497 if (bufSize < 0)
1498 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001499 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001500 return false;
1501 }
1502
Geoff Lang62fce5b2016-09-30 10:46:35 -04001503 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001504 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505}
Jamie Madill26e91952014-03-05 15:01:27 -05001506
Jamie Madill4928b7c2017-06-20 12:57:39 -04001507bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001508 GLint x,
1509 GLint y,
1510 GLsizei width,
1511 GLsizei height,
1512 GLenum format,
1513 GLenum type,
1514 GLsizei bufSize,
1515 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001516 GLsizei *columns,
1517 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001518 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001519{
Brandon Jonesd1049182018-03-28 10:02:20 -07001520 GLsizei writeLength = 0;
1521 GLsizei writeColumns = 0;
1522 GLsizei writeRows = 0;
1523
Geoff Lang62fce5b2016-09-30 10:46:35 -04001524 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001525 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001526 return false;
1527 }
1528
Brandon Jonesd1049182018-03-28 10:02:20 -07001529 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1530 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001531 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001532 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001533 }
1534
Brandon Jonesd1049182018-03-28 10:02:20 -07001535 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001536 {
1537 return false;
1538 }
1539
Brandon Jonesd1049182018-03-28 10:02:20 -07001540 SetRobustLengthParam(length, writeLength);
1541 SetRobustLengthParam(columns, writeColumns);
1542 SetRobustLengthParam(rows, writeRows);
1543
Geoff Lang62fce5b2016-09-30 10:46:35 -04001544 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001545}
1546
Jamie Madill43da7c42018-08-01 11:34:49 -04001547bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001548{
1549 if (!context->getExtensions().occlusionQueryBoolean &&
1550 !context->getExtensions().disjointTimerQuery)
1551 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001553 return false;
1554 }
1555
Olli Etuaho41997e72016-03-10 13:38:39 +02001556 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001557}
1558
Jamie Madill43da7c42018-08-01 11:34:49 -04001559bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001560{
1561 if (!context->getExtensions().occlusionQueryBoolean &&
1562 !context->getExtensions().disjointTimerQuery)
1563 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001565 return false;
1566 }
1567
Olli Etuaho41997e72016-03-10 13:38:39 +02001568 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001569}
1570
Jamie Madill43da7c42018-08-01 11:34:49 -04001571bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001572{
1573 if (!context->getExtensions().occlusionQueryBoolean &&
1574 !context->getExtensions().disjointTimerQuery)
1575 {
1576 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1577 return false;
1578 }
1579
1580 return true;
1581}
1582
Jamie Madill43da7c42018-08-01 11:34:49 -04001583bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001584{
1585 if (!ValidQueryType(context, target))
1586 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001589 }
1590
1591 if (id == 0)
1592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001593 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001594 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001595 }
1596
1597 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1598 // of zero, if the active query object name for <target> is non-zero (for the
1599 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1600 // the active query for either target is non-zero), if <id> is the name of an
1601 // existing query object whose type does not match <target>, or if <id> is the
1602 // active query object name for any query type, the error INVALID_OPERATION is
1603 // generated.
1604
1605 // Ensure no other queries are active
1606 // NOTE: If other queries than occlusion are supported, we will need to check
1607 // separately that:
1608 // a) The query ID passed is not the current active query for any target/type
1609 // b) There are no active queries for the requested target (and in the case
1610 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1611 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001612
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001613 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001616 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001617 }
1618
1619 Query *queryObject = context->getQuery(id, true, target);
1620
1621 // check that name was obtained with glGenQueries
1622 if (!queryObject)
1623 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001626 }
1627
1628 // check for type mismatch
1629 if (queryObject->getType() != target)
1630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001632 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001633 }
1634
1635 return true;
1636}
1637
Jamie Madill43da7c42018-08-01 11:34:49 -04001638bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639{
1640 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001641 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644 return false;
1645 }
1646
1647 return ValidateBeginQueryBase(context, target, id);
1648}
1649
Jamie Madill43da7c42018-08-01 11:34:49 -04001650bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001651{
1652 if (!ValidQueryType(context, target))
1653 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001654 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001656 }
1657
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001658 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001659
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001662 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001663 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001664 }
1665
Jamie Madill45c785d2014-05-13 14:09:34 -04001666 return true;
1667}
1668
Jamie Madill43da7c42018-08-01 11:34:49 -04001669bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670{
1671 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001672 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 return false;
1676 }
1677
1678 return ValidateEndQueryBase(context, target);
1679}
1680
Corentin Wallezad3ae902018-03-09 13:40:42 -05001681bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001682{
1683 if (!context->getExtensions().disjointTimerQuery)
1684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001685 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
Corentin Wallezad3ae902018-03-09 13:40:42 -05001689 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 return false;
1693 }
1694
1695 Query *queryObject = context->getQuery(id, true, target);
1696 if (queryObject == nullptr)
1697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001702 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 return false;
1706 }
1707
1708 return true;
1709}
1710
Corentin Wallezad3ae902018-03-09 13:40:42 -05001711bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712{
Geoff Lang2186c382016-10-14 10:54:54 -04001713 if (numParams)
1714 {
1715 *numParams = 0;
1716 }
1717
Corentin Wallezad3ae902018-03-09 13:40:42 -05001718 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
1724 switch (pname)
1725 {
1726 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001727 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 return false;
1731 }
1732 break;
1733 case GL_QUERY_COUNTER_BITS_EXT:
1734 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001735 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 return false;
1739 }
1740 break;
1741 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743 return false;
1744 }
1745
Geoff Lang2186c382016-10-14 10:54:54 -04001746 if (numParams)
1747 {
1748 // All queries return only one value
1749 *numParams = 1;
1750 }
1751
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return true;
1753}
1754
Corentin Wallezad3ae902018-03-09 13:40:42 -05001755bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756{
1757 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001758 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001760 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 return false;
1762 }
1763
Geoff Lang2186c382016-10-14 10:54:54 -04001764 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765}
1766
Geoff Lang2186c382016-10-14 10:54:54 -04001767bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001768 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001769 GLenum pname,
1770 GLsizei bufSize,
1771 GLsizei *length,
1772 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773{
Geoff Lang2186c382016-10-14 10:54:54 -04001774 if (!ValidateRobustEntryPoint(context, bufSize))
1775 {
1776 return false;
1777 }
1778
Brandon Jonesd1049182018-03-28 10:02:20 -07001779 GLsizei numParams = 0;
1780
1781 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001782 {
1783 return false;
1784 }
1785
Brandon Jonesd1049182018-03-28 10:02:20 -07001786 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001787 {
1788 return false;
1789 }
1790
Brandon Jonesd1049182018-03-28 10:02:20 -07001791 SetRobustLengthParam(length, numParams);
1792
Geoff Lang2186c382016-10-14 10:54:54 -04001793 return true;
1794}
1795
1796bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1797{
1798 if (numParams)
1799 {
1800 *numParams = 0;
1801 }
1802
Corentin Wallezad3ae902018-03-09 13:40:42 -05001803 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804
1805 if (!queryObject)
1806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001811 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return false;
1815 }
1816
1817 switch (pname)
1818 {
1819 case GL_QUERY_RESULT_EXT:
1820 case GL_QUERY_RESULT_AVAILABLE_EXT:
1821 break;
1822
1823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827
Geoff Lang2186c382016-10-14 10:54:54 -04001828 if (numParams)
1829 {
1830 *numParams = 1;
1831 }
1832
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return true;
1834}
1835
1836bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1837{
1838 if (!context->getExtensions().disjointTimerQuery)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
Geoff Lang2186c382016-10-14 10:54:54 -04001843 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1844}
1845
1846bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1847 GLuint id,
1848 GLenum pname,
1849 GLsizei bufSize,
1850 GLsizei *length,
1851 GLint *params)
1852{
1853 if (!context->getExtensions().disjointTimerQuery)
1854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001856 return false;
1857 }
1858
1859 if (!ValidateRobustEntryPoint(context, bufSize))
1860 {
1861 return false;
1862 }
1863
Brandon Jonesd1049182018-03-28 10:02:20 -07001864 GLsizei numParams = 0;
1865
1866 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001867 {
1868 return false;
1869 }
1870
Brandon Jonesd1049182018-03-28 10:02:20 -07001871 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001872 {
1873 return false;
1874 }
1875
Brandon Jonesd1049182018-03-28 10:02:20 -07001876 SetRobustLengthParam(length, numParams);
1877
Geoff Lang2186c382016-10-14 10:54:54 -04001878 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879}
1880
1881bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1882{
1883 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001884 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001885 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001887 return false;
1888 }
Geoff Lang2186c382016-10-14 10:54:54 -04001889 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1890}
1891
1892bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1893 GLuint id,
1894 GLenum pname,
1895 GLsizei bufSize,
1896 GLsizei *length,
1897 GLuint *params)
1898{
1899 if (!context->getExtensions().disjointTimerQuery &&
1900 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1901 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001903 return false;
1904 }
1905
1906 if (!ValidateRobustEntryPoint(context, bufSize))
1907 {
1908 return false;
1909 }
1910
Brandon Jonesd1049182018-03-28 10:02:20 -07001911 GLsizei numParams = 0;
1912
1913 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001914 {
1915 return false;
1916 }
1917
Brandon Jonesd1049182018-03-28 10:02:20 -07001918 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001919 {
1920 return false;
1921 }
1922
Brandon Jonesd1049182018-03-28 10:02:20 -07001923 SetRobustLengthParam(length, numParams);
1924
Geoff Lang2186c382016-10-14 10:54:54 -04001925 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926}
1927
1928bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1929{
1930 if (!context->getExtensions().disjointTimerQuery)
1931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return false;
1934 }
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1936}
1937
1938bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1939 GLuint id,
1940 GLenum pname,
1941 GLsizei bufSize,
1942 GLsizei *length,
1943 GLint64 *params)
1944{
1945 if (!context->getExtensions().disjointTimerQuery)
1946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001948 return false;
1949 }
1950
1951 if (!ValidateRobustEntryPoint(context, bufSize))
1952 {
1953 return false;
1954 }
1955
Brandon Jonesd1049182018-03-28 10:02:20 -07001956 GLsizei numParams = 0;
1957
1958 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001959 {
1960 return false;
1961 }
1962
Brandon Jonesd1049182018-03-28 10:02:20 -07001963 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001964 {
1965 return false;
1966 }
1967
Brandon Jonesd1049182018-03-28 10:02:20 -07001968 SetRobustLengthParam(length, numParams);
1969
Geoff Lang2186c382016-10-14 10:54:54 -04001970 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971}
1972
1973bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1974{
1975 if (!context->getExtensions().disjointTimerQuery)
1976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978 return false;
1979 }
Geoff Lang2186c382016-10-14 10:54:54 -04001980 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1981}
1982
1983bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1984 GLuint id,
1985 GLenum pname,
1986 GLsizei bufSize,
1987 GLsizei *length,
1988 GLuint64 *params)
1989{
1990 if (!context->getExtensions().disjointTimerQuery)
1991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001993 return false;
1994 }
1995
1996 if (!ValidateRobustEntryPoint(context, bufSize))
1997 {
1998 return false;
1999 }
2000
Brandon Jonesd1049182018-03-28 10:02:20 -07002001 GLsizei numParams = 0;
2002
2003 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002004 {
2005 return false;
2006 }
2007
Brandon Jonesd1049182018-03-28 10:02:20 -07002008 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002009 {
2010 return false;
2011 }
2012
Brandon Jonesd1049182018-03-28 10:02:20 -07002013 SetRobustLengthParam(length, numParams);
2014
Geoff Lang2186c382016-10-14 10:54:54 -04002015 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016}
2017
Jamie Madill5b772312018-03-08 20:28:32 -05002018bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002019 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002020 GLint location,
2021 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002022 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002023{
Jiajia Qin5451d532017-11-16 17:16:34 +08002024 // TODO(Jiajia): Add image uniform check in future.
2025 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002026 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002027 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002028 return false;
2029 }
2030
Jiajia Qin5451d532017-11-16 17:16:34 +08002031 if (!program)
2032 {
2033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2034 return false;
2035 }
2036
2037 if (!program->isLinked())
2038 {
2039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2040 return false;
2041 }
2042
2043 if (location == -1)
2044 {
2045 // Silently ignore the uniform command
2046 return false;
2047 }
2048
2049 const auto &uniformLocations = program->getUniformLocations();
2050 size_t castedLocation = static_cast<size_t>(location);
2051 if (castedLocation >= uniformLocations.size())
2052 {
2053 context->handleError(InvalidOperation() << "Invalid uniform location");
2054 return false;
2055 }
2056
2057 const auto &uniformLocation = uniformLocations[castedLocation];
2058 if (uniformLocation.ignored)
2059 {
2060 // Silently ignore the uniform command
2061 return false;
2062 }
2063
2064 if (!uniformLocation.used())
2065 {
2066 context->handleError(InvalidOperation());
2067 return false;
2068 }
2069
2070 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2071
2072 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002073 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002074 {
2075 context->handleError(InvalidOperation());
2076 return false;
2077 }
2078
2079 *uniformOut = &uniform;
2080 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002081}
2082
Jamie Madill5b772312018-03-08 20:28:32 -05002083bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002084 GLenum uniformType,
2085 GLsizei count,
2086 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002087{
Jiajia Qin5451d532017-11-16 17:16:34 +08002088 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2089 // It is compatible with INT or BOOL.
2090 // Do these cheap tests first, for a little extra speed.
2091 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002092 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002093 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002094 }
2095
Jiajia Qin5451d532017-11-16 17:16:34 +08002096 if (IsSamplerType(uniformType))
2097 {
2098 // Check that the values are in range.
2099 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2100 for (GLsizei i = 0; i < count; ++i)
2101 {
2102 if (value[i] < 0 || value[i] >= max)
2103 {
2104 context->handleError(InvalidValue() << "sampler uniform value out of range");
2105 return false;
2106 }
2107 }
2108 return true;
2109 }
2110
2111 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2112 return false;
2113}
2114
Jamie Madill5b772312018-03-08 20:28:32 -05002115bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002116{
2117 // Check that the value type is compatible with uniform type.
2118 // Do the cheaper test first, for a little extra speed.
2119 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2120 {
2121 return true;
2122 }
2123
2124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2125 return false;
2126}
2127
Jamie Madill5b772312018-03-08 20:28:32 -05002128bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002129{
2130 // Check that the value type is compatible with uniform type.
2131 if (valueType == uniformType)
2132 {
2133 return true;
2134 }
2135
2136 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2137 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002138}
2139
Jamie Madill5b772312018-03-08 20:28:32 -05002140bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002141{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002142 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002143 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002144 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2145 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002146}
2147
Jamie Madill5b772312018-03-08 20:28:32 -05002148bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002149{
2150 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002151 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002152 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2153 ValidateUniform1ivValue(context, uniform->type, count, value);
2154}
2155
Jamie Madill5b772312018-03-08 20:28:32 -05002156bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002157 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002158 GLint location,
2159 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160 GLboolean transpose)
2161{
Geoff Lang92019432017-11-20 13:09:34 -05002162 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002164 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002165 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002166 }
2167
Jamie Madill62d31cb2015-09-11 13:25:51 -04002168 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002169 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002170 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2171 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002172}
2173
Jamie Madill5b772312018-03-08 20:28:32 -05002174bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002175{
2176 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002180 }
2181
Jamie Madill0af26e12015-03-05 19:54:33 -05002182 const Caps &caps = context->getCaps();
2183
Jamie Madill893ab082014-05-16 16:56:10 -04002184 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2185 {
2186 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2187
Jamie Madill0af26e12015-03-05 19:54:33 -05002188 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002190 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002191 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002192 }
2193 }
2194
2195 switch (pname)
2196 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002197 case GL_TEXTURE_BINDING_2D:
2198 case GL_TEXTURE_BINDING_CUBE_MAP:
2199 case GL_TEXTURE_BINDING_3D:
2200 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002201 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002202 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002203 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002204 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002205 {
2206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2207 return false;
2208 }
2209 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002210 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2211 if (!context->getExtensions().textureRectangle)
2212 {
2213 context->handleError(InvalidEnum()
2214 << "ANGLE_texture_rectangle extension not present");
2215 return false;
2216 }
2217 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002218 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2219 if (!context->getExtensions().eglStreamConsumerExternal &&
2220 !context->getExtensions().eglImageExternal)
2221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2223 "nor GL_OES_EGL_image_external "
2224 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002225 return false;
2226 }
2227 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002228
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2230 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002231 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002232 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2233 ASSERT(readFramebuffer);
2234
Jamie Madill427064d2018-04-13 16:20:34 -04002235 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002236 {
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002238 }
2239
Jamie Madille98b1b52018-03-08 09:47:23 -05002240 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002241 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002243 return false;
2244 }
2245
Jamie Madille98b1b52018-03-08 09:47:23 -05002246 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002247 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002249 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002251 }
2252 }
2253 break;
2254
He Yunchaoced53ae2016-11-29 15:00:51 +08002255 default:
2256 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002257 }
2258
2259 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002260 if (*numParams == 0)
2261 {
2262 return false;
2263 }
2264
2265 return true;
2266}
2267
Brandon Jonesd1049182018-03-28 10:02:20 -07002268bool ValidateGetBooleanvRobustANGLE(Context *context,
2269 GLenum pname,
2270 GLsizei bufSize,
2271 GLsizei *length,
2272 GLboolean *params)
2273{
2274 GLenum nativeType;
2275 unsigned int numParams = 0;
2276
2277 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2278 {
2279 return false;
2280 }
2281
2282 SetRobustLengthParam(length, numParams);
2283
2284 return true;
2285}
2286
2287bool ValidateGetFloatvRobustANGLE(Context *context,
2288 GLenum pname,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLfloat *params)
2292{
2293 GLenum nativeType;
2294 unsigned int numParams = 0;
2295
2296 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2297 {
2298 return false;
2299 }
2300
2301 SetRobustLengthParam(length, numParams);
2302
2303 return true;
2304}
2305
2306bool ValidateGetIntegervRobustANGLE(Context *context,
2307 GLenum pname,
2308 GLsizei bufSize,
2309 GLsizei *length,
2310 GLint *data)
2311{
2312 GLenum nativeType;
2313 unsigned int numParams = 0;
2314
2315 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2316 {
2317 return false;
2318 }
2319
2320 SetRobustLengthParam(length, numParams);
2321
2322 return true;
2323}
2324
2325bool ValidateGetInteger64vRobustANGLE(Context *context,
2326 GLenum pname,
2327 GLsizei bufSize,
2328 GLsizei *length,
2329 GLint64 *data)
2330{
2331 GLenum nativeType;
2332 unsigned int numParams = 0;
2333
2334 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2335 {
2336 return false;
2337 }
2338
2339 if (nativeType == GL_INT_64_ANGLEX)
2340 {
2341 CastStateValues(context, nativeType, pname, numParams, data);
2342 return false;
2343 }
2344
2345 SetRobustLengthParam(length, numParams);
2346 return true;
2347}
2348
Jamie Madill5b772312018-03-08 20:28:32 -05002349bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002350 GLenum pname,
2351 GLsizei bufSize,
2352 GLenum *nativeType,
2353 unsigned int *numParams)
2354{
2355 if (!ValidateRobustEntryPoint(context, bufSize))
2356 {
2357 return false;
2358 }
2359
2360 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2361 {
2362 return false;
2363 }
2364
2365 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002366 {
2367 return false;
2368 }
2369
2370 return true;
2371}
2372
Jamie Madill5b772312018-03-08 20:28:32 -05002373bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002374 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002375 GLint level,
2376 GLenum internalformat,
2377 bool isSubImage,
2378 GLint xoffset,
2379 GLint yoffset,
2380 GLint zoffset,
2381 GLint x,
2382 GLint y,
2383 GLsizei width,
2384 GLsizei height,
2385 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002386 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002387{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002388 TextureType texType = TextureTargetToType(target);
2389
Brandon Jones6cad5662017-06-14 13:25:13 -07002390 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002392 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2393 return false;
2394 }
2395
2396 if (width < 0 || height < 0)
2397 {
2398 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
He Yunchaoced53ae2016-11-29 15:00:51 +08002402 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2403 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002405 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002406 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 }
2408
2409 if (border != 0)
2410 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002411 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 }
2414
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002415 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002417 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002419 }
2420
Jamie Madill43da7c42018-08-01 11:34:49 -04002421 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002422 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002423 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 {
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 }
2427
Jamie Madille98b1b52018-03-08 09:47:23 -05002428 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 {
Geoff Langb1196682014-07-23 13:47:29 -04002430 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002431 }
2432
Martin Radev138064f2016-07-15 12:03:41 +03002433 if (readFramebuffer->getReadBufferState() == GL_NONE)
2434 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002436 return false;
2437 }
2438
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002439 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2440 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002441 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002442 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002443 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2444 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002445 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002446 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002447 return false;
2448 }
2449
Martin Radev04e2c3b2017-07-27 16:54:35 +03002450 // ANGLE_multiview spec, Revision 1:
2451 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2452 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002453 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2454 // framebuffer is more than one.
2455 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002456 {
2457 context->handleError(InvalidFramebufferOperation()
2458 << "The active read framebuffer object has multiview attachments.");
2459 return false;
2460 }
2461
Jamie Madill43da7c42018-08-01 11:34:49 -04002462 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002463
Geoff Langaae65a42014-05-26 12:43:44 -04002464 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002465 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002466 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002467 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002468 maxDimension = caps.max2DTextureSize;
2469 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002470
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002471 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002472 maxDimension = caps.maxCubeMapTextureSize;
2473 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002474
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002475 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002476 maxDimension = caps.maxRectangleTextureSize;
2477 break;
2478
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002479 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002480 maxDimension = caps.max2DTextureSize;
2481 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002482
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002483 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 maxDimension = caps.max3DTextureSize;
2485 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002486
He Yunchaoced53ae2016-11-29 15:00:51 +08002487 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Jamie Madill43da7c42018-08-01 11:34:49 -04002492 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 if (!texture)
2494 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002496 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002497 }
2498
Geoff Lang69cce582015-09-17 13:20:36 -04002499 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002501 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002502 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 }
2504
Jamie Madill43da7c42018-08-01 11:34:49 -04002505 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002506 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002507 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002508
Geoff Lang966c9402017-04-18 12:38:27 -04002509 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002512 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 }
2514
2515 if (isSubImage)
2516 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002517 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2518 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2519 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002525 else
2526 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002527 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002529 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002531 }
2532
Geoff Langeb66a6e2016-10-31 13:06:12 -04002533 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002534 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002536 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002537 }
2538
2539 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002540 if (static_cast<int>(width) > maxLevelDimension ||
2541 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002542 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002543 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002544 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002545 }
2546 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002547
Jamie Madill0c8abca2016-07-22 20:21:26 -04002548 if (textureFormatOut)
2549 {
2550 *textureFormatOut = texture->getFormat(target, level);
2551 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002552
2553 // Detect texture copying feedback loops for WebGL.
2554 if (context->getExtensions().webglCompatibility)
2555 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002556 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002557 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002559 return false;
2560 }
2561 }
2562
Jamie Madill560a8d82014-05-21 13:06:20 -04002563 return true;
2564}
2565
Jamie Madillb42162f2018-08-20 12:58:37 -04002566// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2567// completeness check.
2568const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002569{
2570 const Extensions &extensions = context->getExtensions();
Jamie Madill7f232932018-09-12 11:03:06 -04002571 const State &state = context->getGLState();
Jamie Madille7d80f32018-08-08 15:49:23 -04002572
2573 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2574 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2575 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
Jamie Madilld84b6732018-09-06 15:54:35 -04002576 VertexArray *vertexArray = state.getVertexArray();
2577 ASSERT(vertexArray);
2578
2579 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002580 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002581 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002582 }
2583
2584 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2585 // Section 6.10 of the WebGL 1.0 spec.
2586 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002587 ASSERT(framebuffer);
2588
Jamie Madille7d80f32018-08-08 15:49:23 -04002589 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2590 {
2591 ASSERT(framebuffer);
2592 const FramebufferAttachment *dsAttachment =
2593 framebuffer->getStencilOrDepthStencilAttachment();
2594 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2595 ASSERT(stencilBits <= 8);
2596
2597 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2598 if (depthStencilState.stencilTest && stencilBits > 0)
2599 {
2600 GLuint maxStencilValue = (1 << stencilBits) - 1;
2601
2602 bool differentRefs =
2603 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2604 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2605 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2606 (depthStencilState.stencilBackWritemask & maxStencilValue);
2607 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2608 (depthStencilState.stencilBackMask & maxStencilValue);
2609
2610 if (differentRefs || differentWritemasks || differentMasks)
2611 {
2612 if (!extensions.webglCompatibility)
2613 {
2614 WARN() << "This ANGLE implementation does not support separate front/back "
2615 "stencil writemasks, reference values, or stencil mask values.";
2616 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002617 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002618 }
2619 }
2620 }
2621
2622 if (!framebuffer->isComplete(context))
2623 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002624 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2625 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002626 }
2627
2628 if (context->getStateCache().hasAnyEnabledClientAttrib())
2629 {
2630 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2631 {
2632 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2633 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2634 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2635 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002636 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002637 }
2638
2639 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2640 {
2641 // This is an application error that would normally result in a crash, but we catch it
2642 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002643 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002644 }
2645 }
2646
2647 // If we are running GLES1, there is no current program.
2648 if (context->getClientVersion() >= Version(2, 0))
2649 {
2650 Program *program = state.getProgram();
2651 if (!program)
2652 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002653 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002654 }
2655
2656 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2657 // vertex shader stage or fragment shader stage is a undefined behaviour.
2658 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2659 // produce undefined result.
2660 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2661 !program->hasLinkedShaderStage(ShaderType::Fragment))
2662 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002663 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002664 }
2665
2666 if (!program->validateSamplers(nullptr, context->getCaps()))
2667 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002668 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002669 }
2670
2671 if (extensions.multiview)
2672 {
2673 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2674 const int framebufferNumViews = framebuffer->getNumViews();
2675 if (framebufferNumViews != programNumViews)
2676 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002677 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002678 }
2679
2680 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2681 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2682 framebufferNumViews > 1)
2683 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002684 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002685 }
2686
2687 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2688 state.isQueryActive(QueryType::TimeElapsed))
2689 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002690 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002691 }
2692 }
2693
2694 // Uniform buffer validation
2695 for (unsigned int uniformBlockIndex = 0;
2696 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2697 {
2698 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Jamie Madill7f232932018-09-12 11:03:06 -04002699 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Jamie Madille7d80f32018-08-08 15:49:23 -04002700 const OffsetBindingPointer<Buffer> &uniformBuffer =
2701 state.getIndexedUniformBuffer(blockBinding);
2702
2703 if (uniformBuffer.get() == nullptr)
2704 {
2705 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002706 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002707 }
2708
2709 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2710 if (uniformBufferSize < uniformBlock.dataSize)
2711 {
2712 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002713 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002714 }
2715
2716 if (extensions.webglCompatibility &&
2717 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2718 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002719 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002720 }
2721 }
2722
2723 // Do some additonal WebGL-specific validation
2724 if (extensions.webglCompatibility)
2725 {
2726 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2727 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2728 transformFeedbackObject->buffersBoundForOtherUse())
2729 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002730 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002731 }
2732
2733 // Detect rendering feedback loops for WebGL.
2734 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2735 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002736 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002737 }
2738
2739 // Detect that the vertex shader input types match the attribute types
2740 if (!ValidateVertexShaderAttributeTypeMatch(context))
2741 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002742 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002743 }
2744
2745 // Detect that the color buffer types match the fragment shader output types
2746 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2747 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002748 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002749 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002750
2751 const VertexArray *vao = context->getGLState().getVertexArray();
2752 if (vao->hasTransformFeedbackBindingConflict(context))
2753 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002754 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002755 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002756 }
2757 }
2758
Jamie Madillb42162f2018-08-20 12:58:37 -04002759 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002760}
2761
Jamie Madill16e28fd2018-09-12 11:03:05 -04002762bool ValidateDrawMode(Context *context, PrimitiveMode mode)
Jamie Madill250d33f2014-06-06 17:09:03 -04002763{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002764 const Extensions &extensions = context->getExtensions();
2765
Jamie Madill1aeb1312014-06-20 13:21:25 -04002766 switch (mode)
2767 {
Jamie Madill493f9572018-05-24 19:52:15 -04002768 case PrimitiveMode::Points:
2769 case PrimitiveMode::Lines:
2770 case PrimitiveMode::LineLoop:
2771 case PrimitiveMode::LineStrip:
2772 case PrimitiveMode::Triangles:
2773 case PrimitiveMode::TriangleStrip:
2774 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002775 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002776
Jamie Madill493f9572018-05-24 19:52:15 -04002777 case PrimitiveMode::LinesAdjacency:
2778 case PrimitiveMode::LineStripAdjacency:
2779 case PrimitiveMode::TrianglesAdjacency:
2780 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002781 if (!extensions.geometryShader)
2782 {
2783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2784 return false;
2785 }
2786 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002790 }
2791
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002792 // If we are running GLES1, there is no current program.
2793 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002794 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002795 const State &state = context->getGLState();
2796
Jamie Madill43da7c42018-08-01 11:34:49 -04002797 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002798 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002799
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002800 // Do geometry shader specific validations
2801 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002802 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002803 if (!IsCompatibleDrawModeWithGeometryShader(
2804 mode, program->getGeometryShaderInputPrimitiveType()))
2805 {
2806 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2807 IncompatibleDrawModeAgainstGeometryShader);
2808 return false;
2809 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002810 }
2811 }
2812
Jamie Madill9fdaa492018-02-16 10:52:11 -05002813 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002814}
2815
Jamie Madill16e28fd2018-09-12 11:03:05 -04002816bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
2817{
2818 if (!context->getStateCache().isValidDrawMode(mode))
2819 {
2820 return ValidateDrawMode(context, mode);
2821 }
2822
2823 if (count < 0)
2824 {
2825 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2826 return false;
2827 }
2828
2829 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2830 if (drawStatesError)
2831 {
2832 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2833
2834 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2835 // Incomplete.
2836 GLenum errorCode =
2837 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2838 : GL_INVALID_OPERATION);
2839 context->handleError(Error(errorCode, errorMessage));
2840 return false;
2841 }
2842
2843 return true;
2844}
2845
Jamie Madill5b772312018-03-08 20:28:32 -05002846bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002847 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002848 GLint first,
2849 GLsizei count,
2850 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002851{
Jamie Madillfd716582014-06-06 17:09:04 -04002852 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002854 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002856 }
2857
Jamie Madill16e28fd2018-09-12 11:03:05 -04002858 if (count < 0)
2859 {
2860 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
2861 return false;
2862 }
2863
Jamie Madill7f232932018-09-12 11:03:06 -04002864 const State &state = context->getGLState();
2865 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002866 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002867 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002868 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002869 if (!ValidateTransformFeedbackPrimitiveMode(context,
2870 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002871 {
James Darpinian30b604d2018-03-12 17:26:57 -07002872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2873 return false;
2874 }
2875
2876 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2877 {
2878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2879 return false;
2880 }
Jamie Madillfd716582014-06-06 17:09:04 -04002881 }
2882
Jamie Madill16e28fd2018-09-12 11:03:05 -04002883 if (!context->getStateCache().isValidDrawMode(mode))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002884 {
Jamie Madill16e28fd2018-09-12 11:03:05 -04002885 return ValidateDrawMode(context, mode);
2886 }
2887
2888 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2889 if (drawStatesError)
2890 {
2891 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2892
2893 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2894 // Incomplete.
2895 GLenum errorCode =
2896 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2897 : GL_INVALID_OPERATION);
2898 context->handleError(Error(errorCode, errorMessage));
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002899 return false;
2900 }
2901
Corentin Wallez71168a02016-12-19 15:11:18 -08002902 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002903 // - first < 0 has been checked as an error condition.
2904 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002905 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002906 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002907 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002908 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002909 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2910 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2911 {
2912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2913 return false;
2914 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002915
Jamie Madill2da53562018-08-01 11:34:47 -04002916 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002917 {
2918 return false;
2919 }
Jamie Madillfd716582014-06-06 17:09:04 -04002920 }
2921
2922 return true;
2923}
2924
He Yunchaoced53ae2016-11-29 15:00:51 +08002925bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002926 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002927 GLint first,
2928 GLsizei count,
2929 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002930{
Geoff Lang63c5a592017-09-27 14:08:16 -04002931 if (!context->getExtensions().instancedArrays)
2932 {
2933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2934 return false;
2935 }
2936
Corentin Wallez170efbf2017-05-02 13:45:01 -04002937 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002938 {
2939 return false;
2940 }
2941
Corentin Wallez0dc97812017-06-22 14:38:44 -04002942 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002943}
2944
Jamie Madill493f9572018-05-24 19:52:15 -04002945bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002946{
Jamie Madill250d33f2014-06-06 17:09:03 -04002947 switch (type)
2948 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002949 case GL_UNSIGNED_BYTE:
2950 case GL_UNSIGNED_SHORT:
2951 break;
2952 case GL_UNSIGNED_INT:
2953 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002956 return false;
2957 }
2958 break;
2959 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002961 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002962 }
2963
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002964 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002965
Jamie Madill43da7c42018-08-01 11:34:49 -04002966 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002967 if (curTransformFeedback && curTransformFeedback->isActive() &&
2968 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002970 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2971 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2972 if (context->getExtensions().geometryShader)
2973 {
2974 if (!ValidateTransformFeedbackPrimitiveMode(
2975 context, curTransformFeedback->getPrimitiveMode(), mode))
2976 {
2977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2978 return false;
2979 }
2980 }
2981 else
2982 {
2983 // It is an invalid operation to call DrawElements, DrawRangeElements or
2984 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2985 // 86)
2986 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2987 UnsupportedDrawModeForTransformFeedback);
2988 return false;
2989 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002990 }
2991
Jiajia Qind9671222016-11-29 16:30:31 +08002992 return true;
2993}
2994
Jamie Madill5b772312018-03-08 20:28:32 -05002995bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002996 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002997 GLsizei count,
2998 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002999 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003000 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003001{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003002 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003003 return false;
3004
3005 const State &state = context->getGLState();
3006
Corentin Wallez170efbf2017-05-02 13:45:01 -04003007 if (!ValidateDrawBase(context, mode, count))
3008 {
3009 return false;
3010 }
3011
Jamie Madill43da7c42018-08-01 11:34:49 -04003012 const VertexArray *vao = state.getVertexArray();
3013 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003014
Jamie Madill43da7c42018-08-01 11:34:49 -04003015 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003016
3017 if (context->getExtensions().webglCompatibility)
3018 {
3019 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3020 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3021 {
3022 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3023 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3024 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003026 return false;
3027 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003028
3029 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3030 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3031 // error is generated.
3032 if (reinterpret_cast<intptr_t>(indices) < 0)
3033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003034 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003035 return false;
3036 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003037 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003038 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3039 {
3040 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3041 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3042 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3043 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3044 return false;
3045 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003046
3047 if (context->getExtensions().webglCompatibility ||
3048 !context->getGLState().areClientArraysEnabled())
3049 {
Brandon Jones2a018152018-06-08 15:59:26 -07003050 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003051 {
3052 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003053 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3054 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003056 return false;
3057 }
3058 }
3059
Jamie Madill9fdaa492018-02-16 10:52:11 -05003060 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003061 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003062 // This is an application error that would normally result in a crash, but we catch it and
3063 // return an error
3064 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3065 return false;
3066 }
3067
3068 if (count > 0 && elementArrayBuffer)
3069 {
3070 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3071 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3072 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3073 constexpr uint64_t kMaxTypeSize = 8;
3074 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3075 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3076 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3077
3078 uint64_t typeSize = typeBytes;
3079 uint64_t elementCount = static_cast<uint64_t>(count);
3080 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3081
3082 // Doing the multiplication here is overflow-safe
3083 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3084
3085 // The offset can be any value, check for overflows
3086 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3087 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003088 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3090 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003091 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003092
3093 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3094 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003095 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3097 return false;
3098 }
3099
3100 ASSERT(isPow2(typeSize) && typeSize > 0);
3101 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3102 {
3103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003104 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003105 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003106
3107 if (context->getExtensions().webglCompatibility &&
3108 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3109 {
3110 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3111 ElementArrayBufferBoundForTransformFeedback);
3112 return false;
3113 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003114 }
3115
Jamie Madill2da53562018-08-01 11:34:47 -04003116 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003117 {
3118 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003119 const DrawCallParams &params = context->getParams<DrawCallParams>();
3120 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3121 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003122
3123 // If we use an index greater than our maximum supported index range, return an error.
3124 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3125 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003126 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003127 {
3128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3129 return false;
3130 }
3131
Jamie Madill2da53562018-08-01 11:34:47 -04003132 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003133 {
3134 return false;
3135 }
3136
3137 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003138 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003139 }
3140
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003141 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003142}
3143
Jamie Madill5b772312018-03-08 20:28:32 -05003144bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003145 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003146 GLsizei count,
3147 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003148 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003149 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003150{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003151 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003152}
3153
Geoff Lang3edfe032015-09-04 16:38:24 -04003154bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003155 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -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)
Geoff Lang87a93302014-09-16 13:29:43 -04003160{
Geoff Lang63c5a592017-09-27 14:08:16 -04003161 if (!context->getExtensions().instancedArrays)
3162 {
3163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3164 return false;
3165 }
3166
Corentin Wallez170efbf2017-05-02 13:45:01 -04003167 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003168 {
3169 return false;
3170 }
3171
Corentin Wallez0dc97812017-06-22 14:38:44 -04003172 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003173}
3174
He Yunchaoced53ae2016-11-29 15:00:51 +08003175bool ValidateFramebufferTextureBase(Context *context,
3176 GLenum target,
3177 GLenum attachment,
3178 GLuint texture,
3179 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003180{
Geoff Lange8afa902017-09-27 15:00:43 -04003181 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003185 }
3186
3187 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003188 {
3189 return false;
3190 }
3191
Jamie Madill55ec3b12014-07-03 10:38:57 -04003192 if (texture != 0)
3193 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003194 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003195
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003196 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003198 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003199 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003200 }
3201
3202 if (level < 0)
3203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003204 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003205 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003206 }
3207 }
3208
Jamie Madill43da7c42018-08-01 11:34:49 -04003209 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003210 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003211
Jamie Madill84115c92015-04-23 15:00:07 -04003212 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003215 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003216 }
3217
3218 return true;
3219}
3220
Geoff Langb1196682014-07-23 13:47:29 -04003221bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003222{
3223 if (program == 0)
3224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003225 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003227 }
3228
Jamie Madill43da7c42018-08-01 11:34:49 -04003229 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003230 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003231 {
3232 return false;
3233 }
3234
Jamie Madill0063c512014-08-25 15:47:53 -04003235 if (!programObject || !programObject->isLinked())
3236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003238 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003239 }
3240
Geoff Lang7dd2e102014-11-10 15:19:26 -05003241 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003243 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003244 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003245 }
3246
Jamie Madill0063c512014-08-25 15:47:53 -04003247 return true;
3248}
3249
Geoff Langf41d0ee2016-10-07 13:04:23 -04003250static bool ValidateSizedGetUniform(Context *context,
3251 GLuint program,
3252 GLint location,
3253 GLsizei bufSize,
3254 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003255{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003256 if (length)
3257 {
3258 *length = 0;
3259 }
3260
Jamie Madill78f41802014-08-25 15:47:55 -04003261 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003262 {
Jamie Madill78f41802014-08-25 15:47:55 -04003263 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003264 }
3265
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266 if (bufSize < 0)
3267 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003268 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003269 return false;
3270 }
3271
Jamie Madill43da7c42018-08-01 11:34:49 -04003272 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003273 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003274
Jamie Madill78f41802014-08-25 15:47:55 -04003275 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003276 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003277 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003278 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003279 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003281 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003282 }
3283
Geoff Langf41d0ee2016-10-07 13:04:23 -04003284 if (length)
3285 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003286 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003287 }
3288
Jamie Madill0063c512014-08-25 15:47:53 -04003289 return true;
3290}
3291
He Yunchaoced53ae2016-11-29 15:00:51 +08003292bool ValidateGetnUniformfvEXT(Context *context,
3293 GLuint program,
3294 GLint location,
3295 GLsizei bufSize,
3296 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003297{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003298 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003299}
3300
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003301bool ValidateGetnUniformfvRobustANGLE(Context *context,
3302 GLuint program,
3303 GLint location,
3304 GLsizei bufSize,
3305 GLsizei *length,
3306 GLfloat *params)
3307{
3308 UNIMPLEMENTED();
3309 return false;
3310}
3311
He Yunchaoced53ae2016-11-29 15:00:51 +08003312bool ValidateGetnUniformivEXT(Context *context,
3313 GLuint program,
3314 GLint location,
3315 GLsizei bufSize,
3316 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003317{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003318 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3319}
3320
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003321bool ValidateGetnUniformivRobustANGLE(Context *context,
3322 GLuint program,
3323 GLint location,
3324 GLsizei bufSize,
3325 GLsizei *length,
3326 GLint *params)
3327{
3328 UNIMPLEMENTED();
3329 return false;
3330}
3331
3332bool ValidateGetnUniformuivRobustANGLE(Context *context,
3333 GLuint program,
3334 GLint location,
3335 GLsizei bufSize,
3336 GLsizei *length,
3337 GLuint *params)
3338{
3339 UNIMPLEMENTED();
3340 return false;
3341}
3342
Geoff Langf41d0ee2016-10-07 13:04:23 -04003343bool ValidateGetUniformfvRobustANGLE(Context *context,
3344 GLuint program,
3345 GLint location,
3346 GLsizei bufSize,
3347 GLsizei *length,
3348 GLfloat *params)
3349{
3350 if (!ValidateRobustEntryPoint(context, bufSize))
3351 {
3352 return false;
3353 }
3354
Brandon Jonesd1049182018-03-28 10:02:20 -07003355 GLsizei writeLength = 0;
3356
Geoff Langf41d0ee2016-10-07 13:04:23 -04003357 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003358 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3359 {
3360 return false;
3361 }
3362
3363 SetRobustLengthParam(length, writeLength);
3364
3365 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003366}
3367
3368bool ValidateGetUniformivRobustANGLE(Context *context,
3369 GLuint program,
3370 GLint location,
3371 GLsizei bufSize,
3372 GLsizei *length,
3373 GLint *params)
3374{
3375 if (!ValidateRobustEntryPoint(context, bufSize))
3376 {
3377 return false;
3378 }
3379
Brandon Jonesd1049182018-03-28 10:02:20 -07003380 GLsizei writeLength = 0;
3381
Geoff Langf41d0ee2016-10-07 13:04:23 -04003382 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003383 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3384 {
3385 return false;
3386 }
3387
3388 SetRobustLengthParam(length, writeLength);
3389
3390 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003391}
3392
3393bool ValidateGetUniformuivRobustANGLE(Context *context,
3394 GLuint program,
3395 GLint location,
3396 GLsizei bufSize,
3397 GLsizei *length,
3398 GLuint *params)
3399{
3400 if (!ValidateRobustEntryPoint(context, bufSize))
3401 {
3402 return false;
3403 }
3404
3405 if (context->getClientMajorVersion() < 3)
3406 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003407 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003408 return false;
3409 }
3410
Brandon Jonesd1049182018-03-28 10:02:20 -07003411 GLsizei writeLength = 0;
3412
Geoff Langf41d0ee2016-10-07 13:04:23 -04003413 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003414 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3415 {
3416 return false;
3417 }
3418
3419 SetRobustLengthParam(length, writeLength);
3420
3421 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003422}
3423
He Yunchaoced53ae2016-11-29 15:00:51 +08003424bool ValidateDiscardFramebufferBase(Context *context,
3425 GLenum target,
3426 GLsizei numAttachments,
3427 const GLenum *attachments,
3428 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003429{
3430 if (numAttachments < 0)
3431 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003432 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003433 return false;
3434 }
3435
3436 for (GLsizei i = 0; i < numAttachments; ++i)
3437 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003438 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003439 {
3440 if (defaultFramebuffer)
3441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003443 return false;
3444 }
3445
3446 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 context->handleError(InvalidOperation() << "Requested color attachment is "
3449 "greater than the maximum supported "
3450 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003451 return false;
3452 }
3453 }
3454 else
3455 {
3456 switch (attachments[i])
3457 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003458 case GL_DEPTH_ATTACHMENT:
3459 case GL_STENCIL_ATTACHMENT:
3460 case GL_DEPTH_STENCIL_ATTACHMENT:
3461 if (defaultFramebuffer)
3462 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003463 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3464 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003465 return false;
3466 }
3467 break;
3468 case GL_COLOR:
3469 case GL_DEPTH:
3470 case GL_STENCIL:
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 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003479 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003480 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003481 }
3482 }
3483 }
3484
3485 return true;
3486}
3487
Austin Kinross6ee1e782015-05-29 17:05:37 -07003488bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3489{
Jamie Madill007530e2017-12-28 14:27:04 -05003490 if (!context->getExtensions().debugMarker)
3491 {
3492 // The debug marker calls should not set error state
3493 // However, it seems reasonable to set an error state if the extension is not enabled
3494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3495 return false;
3496 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003497
Jamie Madill007530e2017-12-28 14:27:04 -05003498 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003499 if (length < 0)
3500 {
3501 return false;
3502 }
3503
3504 if (marker == nullptr)
3505 {
3506 return false;
3507 }
3508
3509 return true;
3510}
3511
3512bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3513{
Jamie Madill007530e2017-12-28 14:27:04 -05003514 if (!context->getExtensions().debugMarker)
3515 {
3516 // The debug marker calls should not set error state
3517 // However, it seems reasonable to set an error state if the extension is not enabled
3518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3519 return false;
3520 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003521
Jamie Madill007530e2017-12-28 14:27:04 -05003522 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003523 if (length < 0)
3524 {
3525 return false;
3526 }
3527
3528 if (length > 0 && marker == nullptr)
3529 {
3530 return false;
3531 }
3532
3533 return true;
3534}
3535
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003536bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003537{
Geoff Langa8406172015-07-21 16:53:39 -04003538 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003541 return false;
3542 }
3543
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003544 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003545 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003546 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003547 if (!context->getExtensions().eglImage)
3548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003549 context->handleError(InvalidEnum()
3550 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003551 }
3552 break;
3553
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003554 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003555 if (!context->getExtensions().eglImageExternal)
3556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3558 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003559 }
Geoff Langa8406172015-07-21 16:53:39 -04003560 break;
3561
3562 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003563 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003564 return false;
3565 }
3566
Rafael Cintron05a449a2018-06-20 18:08:04 -07003567 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003568
Jamie Madill61e16b42017-06-19 11:13:23 -04003569 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003570 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003573 return false;
3574 }
3575
Jamie Madill007530e2017-12-28 14:27:04 -05003576 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003578 context->handleError(InvalidOperation()
3579 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003580 return false;
3581 }
3582
Yuly Novikov2eb54072018-08-22 16:41:26 -04003583 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidOperation()
3586 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
Geoff Langdcab33b2015-07-21 13:03:16 -04003590 return true;
3591}
3592
3593bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003594 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003595 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003596{
Geoff Langa8406172015-07-21 16:53:39 -04003597 if (!context->getExtensions().eglImage)
3598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003600 return false;
3601 }
3602
3603 switch (target)
3604 {
3605 case GL_RENDERBUFFER:
3606 break;
3607
3608 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003610 return false;
3611 }
3612
Rafael Cintron05a449a2018-06-20 18:08:04 -07003613 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003614
Jamie Madill61e16b42017-06-19 11:13:23 -04003615 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003616 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003619 return false;
3620 }
3621
Yuly Novikov2eb54072018-08-22 16:41:26 -04003622 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidOperation()
3625 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003626 return false;
3627 }
3628
Geoff Langdcab33b2015-07-21 13:03:16 -04003629 return true;
3630}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003631
3632bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3633{
Geoff Lang36167ab2015-12-07 10:27:14 -05003634 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003635 {
3636 // The default VAO should always exist
3637 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003638 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003639 return false;
3640 }
3641
3642 return true;
3643}
3644
Geoff Langc5629752015-12-07 16:29:04 -05003645bool ValidateProgramBinaryBase(Context *context,
3646 GLuint program,
3647 GLenum binaryFormat,
3648 const void *binary,
3649 GLint length)
3650{
3651 Program *programObject = GetValidProgram(context, program);
3652 if (programObject == nullptr)
3653 {
3654 return false;
3655 }
3656
3657 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3658 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3659 programBinaryFormats.end())
3660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003661 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003662 return false;
3663 }
3664
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003665 if (context->hasActiveTransformFeedback(program))
3666 {
3667 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3669 "is associated with an active transform "
3670 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003671 return false;
3672 }
3673
Geoff Langc5629752015-12-07 16:29:04 -05003674 return true;
3675}
3676
3677bool ValidateGetProgramBinaryBase(Context *context,
3678 GLuint program,
3679 GLsizei bufSize,
3680 GLsizei *length,
3681 GLenum *binaryFormat,
3682 void *binary)
3683{
3684 Program *programObject = GetValidProgram(context, program);
3685 if (programObject == nullptr)
3686 {
3687 return false;
3688 }
3689
3690 if (!programObject->isLinked())
3691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003693 return false;
3694 }
3695
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003696 if (context->getCaps().programBinaryFormats.empty())
3697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003698 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003699 return false;
3700 }
3701
Geoff Langc5629752015-12-07 16:29:04 -05003702 return true;
3703}
Jamie Madillc29968b2016-01-20 11:17:23 -05003704
Jamie Madill5b772312018-03-08 20:28:32 -05003705bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003706{
3707 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003708 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003709 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003710 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3711 return false;
3712 }
3713 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3714 {
3715 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 return false;
3717 }
3718
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003719 ASSERT(context->getGLState().getDrawFramebuffer());
3720 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003721 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3722
3723 // This should come first before the check for the default frame buffer
3724 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3725 // rather than INVALID_OPERATION
3726 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3727 {
3728 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3729
3730 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003731 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3732 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003733 {
3734 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003735 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3736 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3737 // 3.1 is still a bit ambiguous about the error, but future specs are
3738 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003740 return false;
3741 }
3742 else if (bufs[colorAttachment] >= maxColorAttachment)
3743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003744 context->handleError(InvalidOperation()
3745 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003746 return false;
3747 }
3748 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3749 frameBufferId != 0)
3750 {
3751 // INVALID_OPERATION-GL is bound to buffer and ith argument
3752 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidOperation()
3754 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003755 return false;
3756 }
3757 }
3758
3759 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3760 // and n is not 1 or bufs is bound to value other than BACK and NONE
3761 if (frameBufferId == 0)
3762 {
3763 if (n != 1)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation()
3766 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003767 return false;
3768 }
3769
3770 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(
3773 InvalidOperation()
3774 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003775 return false;
3776 }
3777 }
3778
3779 return true;
3780}
3781
Geoff Lang496c02d2016-10-20 11:38:11 -07003782bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003783 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003784 GLenum pname,
3785 GLsizei *length,
3786 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003787{
Geoff Lang496c02d2016-10-20 11:38:11 -07003788 if (length)
3789 {
3790 *length = 0;
3791 }
3792
3793 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3794 {
3795 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 InvalidOperation()
3797 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003798 return false;
3799 }
3800
Corentin Walleze4477002017-12-01 14:39:58 -05003801 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003802 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003803 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 return false;
3805 }
3806
Geoff Lang496c02d2016-10-20 11:38:11 -07003807 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003809 case GL_BUFFER_MAP_POINTER:
3810 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003811
Geoff Lang496c02d2016-10-20 11:38:11 -07003812 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003813 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003814 return false;
3815 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003816
3817 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3818 // target bound to zero generate an INVALID_OPERATION error."
3819 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003820 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003822 context->handleError(InvalidOperation()
3823 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 return false;
3825 }
3826
Geoff Lang496c02d2016-10-20 11:38:11 -07003827 if (length)
3828 {
3829 *length = 1;
3830 }
3831
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return true;
3833}
3834
Corentin Wallez336129f2017-10-17 15:55:40 -04003835bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003836{
Corentin Walleze4477002017-12-01 14:39:58 -05003837 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003840 return false;
3841 }
3842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003843 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003844
3845 if (buffer == nullptr || !buffer->isMapped())
3846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003847 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003848 return false;
3849 }
3850
3851 return true;
3852}
3853
3854bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003855 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 GLintptr offset,
3857 GLsizeiptr length,
3858 GLbitfield access)
3859{
Corentin Walleze4477002017-12-01 14:39:58 -05003860 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return false;
3864 }
3865
Brandon Jones6cad5662017-06-14 13:25:13 -07003866 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003868 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3869 return false;
3870 }
3871
3872 if (length < 0)
3873 {
3874 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003875 return false;
3876 }
3877
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003878 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003879
3880 if (!buffer)
3881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003882 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 return false;
3884 }
3885
3886 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003887 CheckedNumeric<size_t> checkedOffset(offset);
3888 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003889
Jamie Madille2e406c2016-06-02 13:04:10 -04003890 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 // Check for invalid bits in the mask
3897 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3898 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3899 GL_MAP_UNSYNCHRONIZED_BIT;
3900
3901 if (access & ~(allAccessBits))
3902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(InvalidValue()
3904 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 return false;
3906 }
3907
3908 if (length == 0)
3909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003911 return false;
3912 }
3913
3914 if (buffer->isMapped())
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003917 return false;
3918 }
3919
3920 // Check for invalid bit combinations
3921 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation()
3924 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003925 return false;
3926 }
3927
3928 GLbitfield writeOnlyBits =
3929 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3930
3931 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidOperation()
3934 << "Invalid access bits when mapping buffer for reading: 0x"
3935 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
3939 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(
3942 InvalidOperation()
3943 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003944 return false;
3945 }
Geoff Lang79f71042017-08-14 16:43:43 -04003946
3947 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003948}
3949
3950bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003951 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 GLintptr offset,
3953 GLsizeiptr length)
3954{
Brandon Jones6cad5662017-06-14 13:25:13 -07003955 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3958 return false;
3959 }
3960
3961 if (length < 0)
3962 {
3963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003964 return false;
3965 }
3966
Corentin Walleze4477002017-12-01 14:39:58 -05003967 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 return false;
3971 }
3972
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003973 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003974
3975 if (buffer == nullptr)
3976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003977 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003978 return false;
3979 }
3980
3981 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003983 context->handleError(InvalidOperation()
3984 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003985 return false;
3986 }
3987
3988 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003989 CheckedNumeric<size_t> checkedOffset(offset);
3990 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003991
Jamie Madille2e406c2016-06-02 13:04:10 -04003992 if (!checkedSize.IsValid() ||
3993 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003995 context->handleError(InvalidValue()
3996 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003997 return false;
3998 }
3999
4000 return true;
4001}
4002
Olli Etuaho41997e72016-03-10 13:38:39 +02004003bool ValidateGenOrDelete(Context *context, GLint n)
4004{
4005 if (n < 0)
4006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004008 return false;
4009 }
4010 return true;
4011}
4012
Jamie Madill5b772312018-03-08 20:28:32 -05004013bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004014{
4015 if (!context->getExtensions().robustClientMemory)
4016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004017 context->handleError(InvalidOperation()
4018 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 return false;
4020 }
4021
4022 if (bufSize < 0)
4023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004024 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004025 return false;
4026 }
4027
4028 return true;
4029}
4030
Jamie Madill5b772312018-03-08 20:28:32 -05004031bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004032{
4033 if (bufSize < numParams)
4034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004035 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4036 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004037 return false;
4038 }
4039
4040 return true;
4041}
4042
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004043bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004044 GLenum target,
4045 GLenum attachment,
4046 GLenum pname,
4047 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004048{
Geoff Lange8afa902017-09-27 15:00:43 -04004049 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004051 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 return false;
4053 }
4054
4055 int clientVersion = context->getClientMajorVersion();
4056
4057 switch (pname)
4058 {
4059 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4061 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4062 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4063 break;
4064
Martin Radeve5285d22017-07-14 16:23:53 +03004065 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4066 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4069 if (clientVersion < 3 || !context->getExtensions().multiview)
4070 {
4071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4072 return false;
4073 }
4074 break;
4075
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4077 if (clientVersion < 3 && !context->getExtensions().sRGB)
4078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 return false;
4081 }
4082 break;
4083
4084 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4085 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4086 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4087 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4088 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4089 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4090 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4091 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4092 if (clientVersion < 3)
4093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004094 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004095 return false;
4096 }
4097 break;
4098
Jiawei Shaoa8802472018-05-28 11:17:47 +08004099 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4100 if (!context->getExtensions().geometryShader)
4101 {
4102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4103 return false;
4104 }
4105 break;
4106
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004108 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004109 return false;
4110 }
4111
4112 // Determine if the attachment is a valid enum
4113 switch (attachment)
4114 {
4115 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 case GL_DEPTH:
4117 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 if (clientVersion < 3)
4119 {
Geoff Langfa125c92017-10-24 13:01:46 -04004120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004125 case GL_DEPTH_STENCIL_ATTACHMENT:
4126 if (clientVersion < 3 && !context->isWebGL1())
4127 {
4128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4129 return false;
4130 }
4131 break;
4132
Geoff Langfa125c92017-10-24 13:01:46 -04004133 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 case GL_DEPTH_ATTACHMENT:
4135 case GL_STENCIL_ATTACHMENT:
4136 break;
4137
4138 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004139 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4140 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4142 {
Geoff Langfa125c92017-10-24 13:01:46 -04004143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 return false;
4145 }
4146 break;
4147 }
4148
4149 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4150 ASSERT(framebuffer);
4151
4152 if (framebuffer->id() == 0)
4153 {
4154 if (clientVersion < 3)
4155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159
4160 switch (attachment)
4161 {
4162 case GL_BACK:
4163 case GL_DEPTH:
4164 case GL_STENCIL:
4165 break;
4166
4167 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 }
4172 else
4173 {
4174 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4175 {
4176 // Valid attachment query
4177 }
4178 else
4179 {
4180 switch (attachment)
4181 {
4182 case GL_DEPTH_ATTACHMENT:
4183 case GL_STENCIL_ATTACHMENT:
4184 break;
4185
4186 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004187 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004189 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 return false;
4191 }
4192 break;
4193
4194 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 return false;
4197 }
4198 }
4199 }
4200
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004201 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 if (attachmentObject)
4203 {
4204 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4205 attachmentObject->type() == GL_TEXTURE ||
4206 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4207
4208 switch (pname)
4209 {
4210 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4211 if (attachmentObject->type() != GL_RENDERBUFFER &&
4212 attachmentObject->type() != GL_TEXTURE)
4213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004214 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217 break;
4218
4219 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4220 if (attachmentObject->type() != GL_TEXTURE)
4221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004223 return false;
4224 }
4225 break;
4226
4227 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4228 if (attachmentObject->type() != GL_TEXTURE)
4229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004230 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004231 return false;
4232 }
4233 break;
4234
4235 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4236 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4237 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004239 return false;
4240 }
4241 break;
4242
4243 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4244 if (attachmentObject->type() != GL_TEXTURE)
4245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004246 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004247 return false;
4248 }
4249 break;
4250
4251 default:
4252 break;
4253 }
4254 }
4255 else
4256 {
4257 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4258 // is NONE, then querying any other pname will generate INVALID_ENUM.
4259
4260 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4261 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4262 // INVALID_OPERATION for all other pnames
4263
4264 switch (pname)
4265 {
4266 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4267 break;
4268
4269 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4270 if (clientVersion < 3)
4271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004272 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004273 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return false;
4275 }
4276 break;
4277
4278 default:
4279 if (clientVersion < 3)
4280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004281 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004282 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004283 return false;
4284 }
4285 else
4286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004287 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004288 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004289 return false;
4290 }
4291 }
4292 }
4293
Martin Radeve5285d22017-07-14 16:23:53 +03004294 if (numParams)
4295 {
4296 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4297 {
4298 // Only when the viewport offsets are queried we can have a varying number of output
4299 // parameters.
4300 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4301 *numParams = numViews * 2;
4302 }
4303 else
4304 {
4305 // For all other queries we can have only one output parameter.
4306 *numParams = 1;
4307 }
4308 }
4309
Geoff Langff5b2d52016-09-07 11:32:23 -04004310 return true;
4311}
4312
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004313bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 GLenum target,
4315 GLenum attachment,
4316 GLenum pname,
4317 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004318 GLsizei *length,
4319 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004320{
4321 if (!ValidateRobustEntryPoint(context, bufSize))
4322 {
4323 return false;
4324 }
4325
Brandon Jonesd1049182018-03-28 10:02:20 -07004326 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004327 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004328 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004329 {
4330 return false;
4331 }
4332
Brandon Jonesd1049182018-03-28 10:02:20 -07004333 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004334 {
4335 return false;
4336 }
4337
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 SetRobustLengthParam(length, numParams);
4339
Geoff Langff5b2d52016-09-07 11:32:23 -04004340 return true;
4341}
4342
Jamie Madill5b772312018-03-08 20:28:32 -05004343bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004344 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004345 GLenum pname,
4346 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004347 GLsizei *length,
4348 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004349{
4350 if (!ValidateRobustEntryPoint(context, bufSize))
4351 {
4352 return false;
4353 }
4354
Brandon Jonesd1049182018-03-28 10:02:20 -07004355 GLsizei numParams = 0;
4356
4357 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004358 {
4359 return false;
4360 }
4361
Brandon Jonesd1049182018-03-28 10:02:20 -07004362 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004363 {
4364 return false;
4365 }
4366
Brandon Jonesd1049182018-03-28 10:02:20 -07004367 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004368 return true;
4369}
4370
Jamie Madill5b772312018-03-08 20:28:32 -05004371bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004372 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004373 GLenum pname,
4374 GLsizei bufSize,
4375 GLsizei *length,
4376 GLint64 *params)
4377{
Brandon Jonesd1049182018-03-28 10:02:20 -07004378 GLsizei numParams = 0;
4379
Geoff Langebebe1c2016-10-14 12:01:31 -04004380 if (!ValidateRobustEntryPoint(context, bufSize))
4381 {
4382 return false;
4383 }
4384
Brandon Jonesd1049182018-03-28 10:02:20 -07004385 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004386 {
4387 return false;
4388 }
4389
Brandon Jonesd1049182018-03-28 10:02:20 -07004390 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004391 {
4392 return false;
4393 }
4394
Brandon Jonesd1049182018-03-28 10:02:20 -07004395 SetRobustLengthParam(length, numParams);
4396
Geoff Langff5b2d52016-09-07 11:32:23 -04004397 return true;
4398}
4399
Jamie Madill5b772312018-03-08 20:28:32 -05004400bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004401{
4402 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004403 if (numParams)
4404 {
4405 *numParams = 1;
4406 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004407
4408 Program *programObject = GetValidProgram(context, program);
4409 if (!programObject)
4410 {
4411 return false;
4412 }
4413
4414 switch (pname)
4415 {
4416 case GL_DELETE_STATUS:
4417 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004418 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004419 case GL_VALIDATE_STATUS:
4420 case GL_INFO_LOG_LENGTH:
4421 case GL_ATTACHED_SHADERS:
4422 case GL_ACTIVE_ATTRIBUTES:
4423 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4424 case GL_ACTIVE_UNIFORMS:
4425 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4426 break;
4427
4428 case GL_PROGRAM_BINARY_LENGTH:
4429 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004431 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4432 "requires GL_OES_get_program_binary or "
4433 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004434 return false;
4435 }
4436 break;
4437
4438 case GL_ACTIVE_UNIFORM_BLOCKS:
4439 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4440 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4441 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4442 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4443 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4444 if (context->getClientMajorVersion() < 3)
4445 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004447 return false;
4448 }
4449 break;
4450
Yunchao He61afff12017-03-14 15:34:03 +08004451 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004452 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004453 if (context->getClientVersion() < Version(3, 1))
4454 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004455 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004456 return false;
4457 }
4458 break;
4459
Jiawei Shao6ae51612018-02-23 14:03:25 +08004460 case GL_COMPUTE_WORK_GROUP_SIZE:
4461 if (context->getClientVersion() < Version(3, 1))
4462 {
4463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4464 return false;
4465 }
4466
4467 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4468 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4469 // program which has not been linked successfully, or which does not contain objects to
4470 // form a compute shader.
4471 if (!programObject->isLinked())
4472 {
4473 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4474 return false;
4475 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004476 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004477 {
4478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4479 return false;
4480 }
4481 break;
4482
Jiawei Shao447bfac2018-03-14 14:23:40 +08004483 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4484 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4485 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4486 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4487 if (!context->getExtensions().geometryShader)
4488 {
4489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4490 return false;
4491 }
4492
4493 // [EXT_geometry_shader] Chapter 7.12
4494 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4495 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4496 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4497 // successfully, or which does not contain objects to form a geometry shader.
4498 if (!programObject->isLinked())
4499 {
4500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4501 return false;
4502 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004503 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004504 {
4505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4506 return false;
4507 }
4508 break;
4509
Geoff Langff5b2d52016-09-07 11:32:23 -04004510 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004512 return false;
4513 }
4514
4515 return true;
4516}
4517
4518bool ValidateGetProgramivRobustANGLE(Context *context,
4519 GLuint program,
4520 GLenum pname,
4521 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004522 GLsizei *length,
4523 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004524{
4525 if (!ValidateRobustEntryPoint(context, bufSize))
4526 {
4527 return false;
4528 }
4529
Brandon Jonesd1049182018-03-28 10:02:20 -07004530 GLsizei numParams = 0;
4531
4532 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004533 {
4534 return false;
4535 }
4536
Brandon Jonesd1049182018-03-28 10:02:20 -07004537 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004538 {
4539 return false;
4540 }
4541
Brandon Jonesd1049182018-03-28 10:02:20 -07004542 SetRobustLengthParam(length, numParams);
4543
Geoff Langff5b2d52016-09-07 11:32:23 -04004544 return true;
4545}
4546
Geoff Lang740d9022016-10-07 11:20:52 -04004547bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4548 GLenum target,
4549 GLenum pname,
4550 GLsizei bufSize,
4551 GLsizei *length,
4552 GLint *params)
4553{
4554 if (!ValidateRobustEntryPoint(context, bufSize))
4555 {
4556 return false;
4557 }
4558
Brandon Jonesd1049182018-03-28 10:02:20 -07004559 GLsizei numParams = 0;
4560
4561 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004562 {
4563 return false;
4564 }
4565
Brandon Jonesd1049182018-03-28 10:02:20 -07004566 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004567 {
4568 return false;
4569 }
4570
Brandon Jonesd1049182018-03-28 10:02:20 -07004571 SetRobustLengthParam(length, numParams);
4572
Geoff Lang740d9022016-10-07 11:20:52 -04004573 return true;
4574}
4575
Geoff Langd7d0ed32016-10-07 11:33:51 -04004576bool ValidateGetShaderivRobustANGLE(Context *context,
4577 GLuint shader,
4578 GLenum pname,
4579 GLsizei bufSize,
4580 GLsizei *length,
4581 GLint *params)
4582{
4583 if (!ValidateRobustEntryPoint(context, bufSize))
4584 {
4585 return false;
4586 }
4587
Brandon Jonesd1049182018-03-28 10:02:20 -07004588 GLsizei numParams = 0;
4589
4590 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004591 {
4592 return false;
4593 }
4594
Brandon Jonesd1049182018-03-28 10:02:20 -07004595 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004596 {
4597 return false;
4598 }
4599
Brandon Jonesd1049182018-03-28 10:02:20 -07004600 SetRobustLengthParam(length, numParams);
4601
Geoff Langd7d0ed32016-10-07 11:33:51 -04004602 return true;
4603}
4604
Geoff Langc1984ed2016-10-07 12:41:00 -04004605bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004606 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004607 GLenum pname,
4608 GLsizei bufSize,
4609 GLsizei *length,
4610 GLfloat *params)
4611{
4612 if (!ValidateRobustEntryPoint(context, bufSize))
4613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 GLsizei numParams = 0;
4618
4619 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004620 {
4621 return false;
4622 }
4623
Brandon Jonesd1049182018-03-28 10:02:20 -07004624 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004625 {
4626 return false;
4627 }
4628
Brandon Jonesd1049182018-03-28 10:02:20 -07004629 SetRobustLengthParam(length, numParams);
4630
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 return true;
4632}
4633
Geoff Langc1984ed2016-10-07 12:41:00 -04004634bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004635 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004636 GLenum pname,
4637 GLsizei bufSize,
4638 GLsizei *length,
4639 GLint *params)
4640{
Brandon Jonesd1049182018-03-28 10:02:20 -07004641
Geoff Langc1984ed2016-10-07 12:41:00 -04004642 if (!ValidateRobustEntryPoint(context, bufSize))
4643 {
4644 return false;
4645 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004646 GLsizei numParams = 0;
4647 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 {
4649 return false;
4650 }
4651
Brandon Jonesd1049182018-03-28 10:02:20 -07004652 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004653 {
4654 return false;
4655 }
4656
Brandon Jonesd1049182018-03-28 10:02:20 -07004657 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004658 return true;
4659}
4660
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004661bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4662 TextureType target,
4663 GLenum pname,
4664 GLsizei bufSize,
4665 GLsizei *length,
4666 GLint *params)
4667{
4668 UNIMPLEMENTED();
4669 return false;
4670}
4671
4672bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4673 TextureType target,
4674 GLenum pname,
4675 GLsizei bufSize,
4676 GLsizei *length,
4677 GLuint *params)
4678{
4679 UNIMPLEMENTED();
4680 return false;
4681}
4682
Geoff Langc1984ed2016-10-07 12:41:00 -04004683bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004684 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004685 GLenum pname,
4686 GLsizei bufSize,
4687 const GLfloat *params)
4688{
4689 if (!ValidateRobustEntryPoint(context, bufSize))
4690 {
4691 return false;
4692 }
4693
4694 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4695}
4696
Geoff Langc1984ed2016-10-07 12:41:00 -04004697bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004698 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004699 GLenum pname,
4700 GLsizei bufSize,
4701 const GLint *params)
4702{
4703 if (!ValidateRobustEntryPoint(context, bufSize))
4704 {
4705 return false;
4706 }
4707
4708 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4709}
4710
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004711bool ValidateTexParameterIivRobustANGLE(Context *context,
4712 TextureType target,
4713 GLenum pname,
4714 GLsizei bufSize,
4715 const GLint *params)
4716{
4717 UNIMPLEMENTED();
4718 return false;
4719}
4720
4721bool ValidateTexParameterIuivRobustANGLE(Context *context,
4722 TextureType target,
4723 GLenum pname,
4724 GLsizei bufSize,
4725 const GLuint *params)
4726{
4727 UNIMPLEMENTED();
4728 return false;
4729}
4730
Geoff Langc1984ed2016-10-07 12:41:00 -04004731bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4732 GLuint sampler,
4733 GLenum pname,
4734 GLuint bufSize,
4735 GLsizei *length,
4736 GLfloat *params)
4737{
4738 if (!ValidateRobustEntryPoint(context, bufSize))
4739 {
4740 return false;
4741 }
4742
Brandon Jonesd1049182018-03-28 10:02:20 -07004743 GLsizei numParams = 0;
4744
4745 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004746 {
4747 return false;
4748 }
4749
Brandon Jonesd1049182018-03-28 10:02:20 -07004750 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004751 {
4752 return false;
4753 }
4754
Brandon Jonesd1049182018-03-28 10:02:20 -07004755 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004756 return true;
4757}
4758
Geoff Langc1984ed2016-10-07 12:41:00 -04004759bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4760 GLuint sampler,
4761 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004762 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004763 GLsizei *length,
4764 GLint *params)
4765{
4766 if (!ValidateRobustEntryPoint(context, bufSize))
4767 {
4768 return false;
4769 }
4770
Brandon Jonesd1049182018-03-28 10:02:20 -07004771 GLsizei numParams = 0;
4772
4773 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004774 {
4775 return false;
4776 }
4777
Brandon Jonesd1049182018-03-28 10:02:20 -07004778 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004779 {
4780 return false;
4781 }
4782
Brandon Jonesd1049182018-03-28 10:02:20 -07004783 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004784 return true;
4785}
4786
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004787bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4788 GLuint sampler,
4789 GLenum pname,
4790 GLsizei bufSize,
4791 GLsizei *length,
4792 GLint *params)
4793{
4794 UNIMPLEMENTED();
4795 return false;
4796}
4797
4798bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4799 GLuint sampler,
4800 GLenum pname,
4801 GLsizei bufSize,
4802 GLsizei *length,
4803 GLuint *params)
4804{
4805 UNIMPLEMENTED();
4806 return false;
4807}
4808
Geoff Langc1984ed2016-10-07 12:41:00 -04004809bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4810 GLuint sampler,
4811 GLenum pname,
4812 GLsizei bufSize,
4813 const GLfloat *params)
4814{
4815 if (!ValidateRobustEntryPoint(context, bufSize))
4816 {
4817 return false;
4818 }
4819
4820 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4821}
4822
Geoff Langc1984ed2016-10-07 12:41:00 -04004823bool ValidateSamplerParameterivRobustANGLE(Context *context,
4824 GLuint sampler,
4825 GLenum pname,
4826 GLsizei bufSize,
4827 const GLint *params)
4828{
4829 if (!ValidateRobustEntryPoint(context, bufSize))
4830 {
4831 return false;
4832 }
4833
4834 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4835}
4836
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004837bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4838 GLuint sampler,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 const GLint *param)
4842{
4843 UNIMPLEMENTED();
4844 return false;
4845}
4846
4847bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4848 GLuint sampler,
4849 GLenum pname,
4850 GLsizei bufSize,
4851 const GLuint *param)
4852{
4853 UNIMPLEMENTED();
4854 return false;
4855}
4856
Geoff Lang0b031062016-10-13 14:30:04 -04004857bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4858 GLuint index,
4859 GLenum pname,
4860 GLsizei bufSize,
4861 GLsizei *length,
4862 GLfloat *params)
4863{
4864 if (!ValidateRobustEntryPoint(context, bufSize))
4865 {
4866 return false;
4867 }
4868
Brandon Jonesd1049182018-03-28 10:02:20 -07004869 GLsizei writeLength = 0;
4870
4871 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004872 {
4873 return false;
4874 }
4875
Brandon Jonesd1049182018-03-28 10:02:20 -07004876 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004877 {
4878 return false;
4879 }
4880
Brandon Jonesd1049182018-03-28 10:02:20 -07004881 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004882 return true;
4883}
4884
Geoff Lang0b031062016-10-13 14:30:04 -04004885bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4886 GLuint index,
4887 GLenum pname,
4888 GLsizei bufSize,
4889 GLsizei *length,
4890 GLint *params)
4891{
4892 if (!ValidateRobustEntryPoint(context, bufSize))
4893 {
4894 return false;
4895 }
4896
Brandon Jonesd1049182018-03-28 10:02:20 -07004897 GLsizei writeLength = 0;
4898
4899 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004900 {
4901 return false;
4902 }
4903
Brandon Jonesd1049182018-03-28 10:02:20 -07004904 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004905 {
4906 return false;
4907 }
4908
Brandon Jonesd1049182018-03-28 10:02:20 -07004909 SetRobustLengthParam(length, writeLength);
4910
Geoff Lang0b031062016-10-13 14:30:04 -04004911 return true;
4912}
4913
Geoff Lang0b031062016-10-13 14:30:04 -04004914bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4915 GLuint index,
4916 GLenum pname,
4917 GLsizei bufSize,
4918 GLsizei *length,
4919 void **pointer)
4920{
4921 if (!ValidateRobustEntryPoint(context, bufSize))
4922 {
4923 return false;
4924 }
4925
Brandon Jonesd1049182018-03-28 10:02:20 -07004926 GLsizei writeLength = 0;
4927
4928 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004929 {
4930 return false;
4931 }
4932
Brandon Jonesd1049182018-03-28 10:02:20 -07004933 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004934 {
4935 return false;
4936 }
4937
Brandon Jonesd1049182018-03-28 10:02:20 -07004938 SetRobustLengthParam(length, writeLength);
4939
Geoff Lang0b031062016-10-13 14:30:04 -04004940 return true;
4941}
4942
Geoff Lang0b031062016-10-13 14:30:04 -04004943bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4944 GLuint index,
4945 GLenum pname,
4946 GLsizei bufSize,
4947 GLsizei *length,
4948 GLint *params)
4949{
4950 if (!ValidateRobustEntryPoint(context, bufSize))
4951 {
4952 return false;
4953 }
4954
Brandon Jonesd1049182018-03-28 10:02:20 -07004955 GLsizei writeLength = 0;
4956
4957 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004958 {
4959 return false;
4960 }
4961
Brandon Jonesd1049182018-03-28 10:02:20 -07004962 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004963 {
4964 return false;
4965 }
4966
Brandon Jonesd1049182018-03-28 10:02:20 -07004967 SetRobustLengthParam(length, writeLength);
4968
Geoff Lang0b031062016-10-13 14:30:04 -04004969 return true;
4970}
4971
Geoff Lang0b031062016-10-13 14:30:04 -04004972bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4973 GLuint index,
4974 GLenum pname,
4975 GLsizei bufSize,
4976 GLsizei *length,
4977 GLuint *params)
4978{
4979 if (!ValidateRobustEntryPoint(context, bufSize))
4980 {
4981 return false;
4982 }
4983
Brandon Jonesd1049182018-03-28 10:02:20 -07004984 GLsizei writeLength = 0;
4985
4986 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004987 {
4988 return false;
4989 }
4990
Brandon Jonesd1049182018-03-28 10:02:20 -07004991 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004992 {
4993 return false;
4994 }
4995
Brandon Jonesd1049182018-03-28 10:02:20 -07004996 SetRobustLengthParam(length, writeLength);
4997
Geoff Lang0b031062016-10-13 14:30:04 -04004998 return true;
4999}
5000
Geoff Lang6899b872016-10-14 11:30:13 -04005001bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5002 GLuint program,
5003 GLuint uniformBlockIndex,
5004 GLenum pname,
5005 GLsizei bufSize,
5006 GLsizei *length,
5007 GLint *params)
5008{
5009 if (!ValidateRobustEntryPoint(context, bufSize))
5010 {
5011 return false;
5012 }
5013
Brandon Jonesd1049182018-03-28 10:02:20 -07005014 GLsizei writeLength = 0;
5015
5016 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5017 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005018 {
5019 return false;
5020 }
5021
Brandon Jonesd1049182018-03-28 10:02:20 -07005022 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005023 {
5024 return false;
5025 }
5026
Brandon Jonesd1049182018-03-28 10:02:20 -07005027 SetRobustLengthParam(length, writeLength);
5028
Geoff Lang6899b872016-10-14 11:30:13 -04005029 return true;
5030}
5031
Brandon Jones416aaf92018-04-10 08:10:16 -07005032bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005033 GLenum target,
5034 GLenum internalformat,
5035 GLenum pname,
5036 GLsizei bufSize,
5037 GLsizei *length,
5038 GLint *params)
5039{
5040 if (!ValidateRobustEntryPoint(context, bufSize))
5041 {
5042 return false;
5043 }
5044
Brandon Jonesd1049182018-03-28 10:02:20 -07005045 GLsizei numParams = 0;
5046
5047 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5048 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005049 {
5050 return false;
5051 }
5052
Brandon Jonesd1049182018-03-28 10:02:20 -07005053 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005054 {
5055 return false;
5056 }
5057
Brandon Jonesd1049182018-03-28 10:02:20 -07005058 SetRobustLengthParam(length, numParams);
5059
Geoff Lang0a9661f2016-10-20 10:59:20 -07005060 return true;
5061}
5062
Jamie Madill5b772312018-03-08 20:28:32 -05005063bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005064 GLuint attribIndex,
5065 GLint size,
5066 GLenum type,
5067 GLboolean pureInteger)
5068{
5069 const Caps &caps = context->getCaps();
5070 if (attribIndex >= caps.maxVertexAttributes)
5071 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005072 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005073 return false;
5074 }
5075
5076 if (size < 1 || size > 4)
5077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005078 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005079 return false;
Shao80957d92017-02-20 21:25:59 +08005080 }
5081
5082 switch (type)
5083 {
5084 case GL_BYTE:
5085 case GL_UNSIGNED_BYTE:
5086 case GL_SHORT:
5087 case GL_UNSIGNED_SHORT:
5088 break;
5089
5090 case GL_INT:
5091 case GL_UNSIGNED_INT:
5092 if (context->getClientMajorVersion() < 3)
5093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 context->handleError(InvalidEnum()
5095 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005096 return false;
5097 }
5098 break;
5099
5100 case GL_FIXED:
5101 case GL_FLOAT:
5102 if (pureInteger)
5103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005105 return false;
5106 }
5107 break;
5108
5109 case GL_HALF_FLOAT:
5110 if (context->getClientMajorVersion() < 3)
5111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005112 context->handleError(InvalidEnum()
5113 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005114 return false;
5115 }
5116 if (pureInteger)
5117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005119 return false;
5120 }
5121 break;
5122
5123 case GL_INT_2_10_10_10_REV:
5124 case GL_UNSIGNED_INT_2_10_10_10_REV:
5125 if (context->getClientMajorVersion() < 3)
5126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005127 context->handleError(InvalidEnum()
5128 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005129 return false;
5130 }
5131 if (pureInteger)
5132 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005133 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005134 return false;
5135 }
5136 if (size != 4)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5139 "UNSIGNED_INT_2_10_10_10_REV and "
5140 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005141 return false;
5142 }
5143 break;
5144
5145 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005147 return false;
5148 }
5149
5150 return true;
5151}
5152
Geoff Lang76e65652017-03-27 14:58:02 -04005153// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5154// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5155// specified clear value and the type of a buffer that is being cleared generates an
5156// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005157bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005158 GLint drawbuffer,
5159 const GLenum *validComponentTypes,
5160 size_t validComponentTypeCount)
5161{
5162 const FramebufferAttachment *attachment =
5163 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5164 if (attachment)
5165 {
5166 GLenum componentType = attachment->getFormat().info->componentType;
5167 const GLenum *end = validComponentTypes + validComponentTypeCount;
5168 if (std::find(validComponentTypes, end, componentType) == end)
5169 {
5170 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005171 InvalidOperation()
5172 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005173 return false;
5174 }
5175 }
5176
5177 return true;
5178}
5179
Jamie Madill5b772312018-03-08 20:28:32 -05005180bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005181{
5182 if (!ValidateRobustEntryPoint(context, dataSize))
5183 {
5184 return false;
5185 }
5186
Jamie Madill43da7c42018-08-01 11:34:49 -04005187 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005188 if (pixelUnpackBuffer == nullptr)
5189 {
5190 if (dataSize < imageSize)
5191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005192 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005193 }
5194 }
5195 return true;
5196}
5197
Jamie Madill5b772312018-03-08 20:28:32 -05005198bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005199 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005200 GLenum pname,
5201 bool pointerVersion,
5202 GLsizei *numParams)
5203{
5204 if (numParams)
5205 {
5206 *numParams = 0;
5207 }
5208
Corentin Walleze4477002017-12-01 14:39:58 -05005209 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214
5215 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5216 if (!buffer)
5217 {
5218 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005220 return false;
5221 }
5222
5223 const Extensions &extensions = context->getExtensions();
5224
5225 switch (pname)
5226 {
5227 case GL_BUFFER_USAGE:
5228 case GL_BUFFER_SIZE:
5229 break;
5230
5231 case GL_BUFFER_ACCESS_OES:
5232 if (!extensions.mapBuffer)
5233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005234 context->handleError(InvalidEnum()
5235 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238 break;
5239
5240 case GL_BUFFER_MAPPED:
5241 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5242 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5243 !extensions.mapBufferRange)
5244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005245 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5246 "GL_OES_mapbuffer or "
5247 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 return false;
5249 }
5250 break;
5251
5252 case GL_BUFFER_MAP_POINTER:
5253 if (!pointerVersion)
5254 {
5255 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005256 InvalidEnum()
5257 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005258 return false;
5259 }
5260 break;
5261
5262 case GL_BUFFER_ACCESS_FLAGS:
5263 case GL_BUFFER_MAP_OFFSET:
5264 case GL_BUFFER_MAP_LENGTH:
5265 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005267 context->handleError(InvalidEnum()
5268 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
5271 break;
5272
5273 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005275 return false;
5276 }
5277
5278 // All buffer parameter queries return one value.
5279 if (numParams)
5280 {
5281 *numParams = 1;
5282 }
5283
5284 return true;
5285}
5286
5287bool ValidateGetRenderbufferParameterivBase(Context *context,
5288 GLenum target,
5289 GLenum pname,
5290 GLsizei *length)
5291{
5292 if (length)
5293 {
5294 *length = 0;
5295 }
5296
5297 if (target != GL_RENDERBUFFER)
5298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5304 if (renderbuffer == nullptr)
5305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 return false;
5308 }
5309
5310 switch (pname)
5311 {
5312 case GL_RENDERBUFFER_WIDTH:
5313 case GL_RENDERBUFFER_HEIGHT:
5314 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5315 case GL_RENDERBUFFER_RED_SIZE:
5316 case GL_RENDERBUFFER_GREEN_SIZE:
5317 case GL_RENDERBUFFER_BLUE_SIZE:
5318 case GL_RENDERBUFFER_ALPHA_SIZE:
5319 case GL_RENDERBUFFER_DEPTH_SIZE:
5320 case GL_RENDERBUFFER_STENCIL_SIZE:
5321 break;
5322
5323 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5324 if (!context->getExtensions().framebufferMultisample)
5325 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005326 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 return false;
5328 }
5329 break;
5330
5331 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335
5336 if (length)
5337 {
5338 *length = 1;
5339 }
5340 return true;
5341}
5342
5343bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5344{
5345 if (length)
5346 {
5347 *length = 0;
5348 }
5349
5350 if (GetValidShader(context, shader) == nullptr)
5351 {
5352 return false;
5353 }
5354
5355 switch (pname)
5356 {
5357 case GL_SHADER_TYPE:
5358 case GL_DELETE_STATUS:
5359 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005360 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 case GL_INFO_LOG_LENGTH:
5362 case GL_SHADER_SOURCE_LENGTH:
5363 break;
5364
5365 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5366 if (!context->getExtensions().translatedShaderSource)
5367 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 return false;
5370 }
5371 break;
5372
5373 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005375 return false;
5376 }
5377
5378 if (length)
5379 {
5380 *length = 1;
5381 }
5382 return true;
5383}
5384
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005385bool ValidateGetTexParameterBase(Context *context,
5386 TextureType target,
5387 GLenum pname,
5388 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005389{
5390 if (length)
5391 {
5392 *length = 0;
5393 }
5394
5395 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005398 return false;
5399 }
5400
5401 if (context->getTargetTexture(target) == nullptr)
5402 {
5403 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 return false;
5406 }
5407
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005408 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5409 {
5410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5411 return false;
5412 }
5413
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 switch (pname)
5415 {
5416 case GL_TEXTURE_MAG_FILTER:
5417 case GL_TEXTURE_MIN_FILTER:
5418 case GL_TEXTURE_WRAP_S:
5419 case GL_TEXTURE_WRAP_T:
5420 break;
5421
5422 case GL_TEXTURE_USAGE_ANGLE:
5423 if (!context->getExtensions().textureUsage)
5424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 return false;
5427 }
5428 break;
5429
5430 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005431 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005433 return false;
5434 }
5435 break;
5436
5437 case GL_TEXTURE_IMMUTABLE_FORMAT:
5438 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005440 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443 break;
5444
5445 case GL_TEXTURE_WRAP_R:
5446 case GL_TEXTURE_IMMUTABLE_LEVELS:
5447 case GL_TEXTURE_SWIZZLE_R:
5448 case GL_TEXTURE_SWIZZLE_G:
5449 case GL_TEXTURE_SWIZZLE_B:
5450 case GL_TEXTURE_SWIZZLE_A:
5451 case GL_TEXTURE_BASE_LEVEL:
5452 case GL_TEXTURE_MAX_LEVEL:
5453 case GL_TEXTURE_MIN_LOD:
5454 case GL_TEXTURE_MAX_LOD:
5455 case GL_TEXTURE_COMPARE_MODE:
5456 case GL_TEXTURE_COMPARE_FUNC:
5457 if (context->getClientMajorVersion() < 3)
5458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005459 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 break;
5463
5464 case GL_TEXTURE_SRGB_DECODE_EXT:
5465 if (!context->getExtensions().textureSRGBDecode)
5466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005467 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470 break;
5471
Yunchao Hebacaa712018-01-30 14:01:39 +08005472 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5473 if (context->getClientVersion() < Version(3, 1))
5474 {
5475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5476 return false;
5477 }
5478 break;
5479
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005480 case GL_GENERATE_MIPMAP:
5481 case GL_TEXTURE_CROP_RECT_OES:
5482 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5483 // after GL_OES_draw_texture functionality implemented
5484 if (context->getClientMajorVersion() > 1)
5485 {
5486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5487 return false;
5488 }
5489 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005490 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494
5495 if (length)
5496 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005497 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 }
5499 return true;
5500}
5501
5502bool ValidateGetVertexAttribBase(Context *context,
5503 GLuint index,
5504 GLenum pname,
5505 GLsizei *length,
5506 bool pointer,
5507 bool pureIntegerEntryPoint)
5508{
5509 if (length)
5510 {
5511 *length = 0;
5512 }
5513
5514 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005516 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519
5520 if (index >= context->getCaps().maxVertexAttributes)
5521 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005522 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525
5526 if (pointer)
5527 {
5528 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005530 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005531 return false;
5532 }
5533 }
5534 else
5535 {
5536 switch (pname)
5537 {
5538 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5539 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5540 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5541 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5542 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5543 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5544 case GL_CURRENT_VERTEX_ATTRIB:
5545 break;
5546
5547 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5548 static_assert(
5549 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5550 "ANGLE extension enums not equal to GL enums.");
5551 if (context->getClientMajorVersion() < 3 &&
5552 !context->getExtensions().instancedArrays)
5553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005554 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5555 "requires OpenGL ES 3.0 or "
5556 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559 break;
5560
5561 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5562 if (context->getClientMajorVersion() < 3)
5563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005564 context->handleError(
5565 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568 break;
5569
5570 case GL_VERTEX_ATTRIB_BINDING:
5571 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5572 if (context->getClientVersion() < ES_3_1)
5573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005574 context->handleError(InvalidEnum()
5575 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005576 return false;
5577 }
5578 break;
5579
5580 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005582 return false;
5583 }
5584 }
5585
5586 if (length)
5587 {
5588 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5589 {
5590 *length = 4;
5591 }
5592 else
5593 {
5594 *length = 1;
5595 }
5596 }
5597
5598 return true;
5599}
5600
Jamie Madill4928b7c2017-06-20 12:57:39 -04005601bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005602 GLint x,
5603 GLint y,
5604 GLsizei width,
5605 GLsizei height,
5606 GLenum format,
5607 GLenum type,
5608 GLsizei bufSize,
5609 GLsizei *length,
5610 GLsizei *columns,
5611 GLsizei *rows,
5612 void *pixels)
5613{
5614 if (length != nullptr)
5615 {
5616 *length = 0;
5617 }
5618 if (rows != nullptr)
5619 {
5620 *rows = 0;
5621 }
5622 if (columns != nullptr)
5623 {
5624 *columns = 0;
5625 }
5626
5627 if (width < 0 || height < 0)
5628 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005629 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005630 return false;
5631 }
5632
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005633 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005634
Jamie Madill427064d2018-04-13 16:20:34 -04005635 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005636 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639
Jamie Madille98b1b52018-03-08 09:47:23 -05005640 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005641 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 return false;
5643 }
5644
Jamie Madill690c8eb2018-03-12 15:20:03 -04005645 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005646 ASSERT(framebuffer);
5647
5648 if (framebuffer->getReadBufferState() == GL_NONE)
5649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 return false;
5652 }
5653
5654 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5655 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5656 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5657 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5658 // situation is an application error that would lead to a crash in ANGLE.
5659 if (readBuffer == nullptr)
5660 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005662 return false;
5663 }
5664
Martin Radev28031682017-07-28 14:47:56 +03005665 // ANGLE_multiview, Revision 1:
5666 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005667 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5668 // in the current read framebuffer is more than one.
5669 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005670 {
5671 context->handleError(InvalidFramebufferOperation()
5672 << "Attempting to read from a multi-view framebuffer.");
5673 return false;
5674 }
5675
Geoff Lang280ba992017-04-18 16:30:58 -04005676 if (context->getExtensions().webglCompatibility)
5677 {
5678 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5679 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5680 // and type before validating the combination of format and type. However, the
5681 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5682 // verifies that GL_INVALID_OPERATION is generated.
5683 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5684 // dEQP/WebGL.
5685 if (!ValidReadPixelsFormatEnum(context, format))
5686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005687 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005688 return false;
5689 }
5690
5691 if (!ValidReadPixelsTypeEnum(context, type))
5692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005694 return false;
5695 }
5696 }
5697
Jamie Madill690c8eb2018-03-12 15:20:03 -04005698 GLenum currentFormat = GL_NONE;
5699 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5700
5701 GLenum currentType = GL_NONE;
5702 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5703
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5705
5706 bool validFormatTypeCombination =
5707 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5708
5709 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714
5715 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005716 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5718 {
5719 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005720 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 return false;
5722 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005723 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5724 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5725 {
5726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5727 return false;
5728 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005729
5730 // .. the data would be packed to the buffer object such that the memory writes required
5731 // would exceed the data store size.
5732 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005733 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 const auto &pack = context->getGLState().getPackState();
5735
Jamie Madillca2ff382018-07-11 09:01:17 -04005736 GLuint endByte = 0;
5737 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005738 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005740 return false;
5741 }
5742
Jamie Madillbe849e42017-05-02 15:49:00 -04005743 if (bufSize >= 0)
5744 {
5745 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5746 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 return false;
5749 }
5750 }
5751
5752 if (pixelPackBuffer != nullptr)
5753 {
5754 CheckedNumeric<size_t> checkedEndByte(endByte);
5755 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5756 checkedEndByte += checkedOffset;
5757
5758 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5759 {
5760 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005762 return false;
5763 }
5764 }
5765
5766 if (pixelPackBuffer == nullptr && length != nullptr)
5767 {
5768 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5769 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 return false;
5772 }
5773
5774 *length = static_cast<GLsizei>(endByte);
5775 }
5776
Geoff Langa953b522018-02-21 16:56:23 -05005777 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005778 angle::CheckedNumeric<int> clippedExtent(length);
5779 if (start < 0)
5780 {
5781 // "subtract" the area that is less than 0
5782 clippedExtent += start;
5783 }
5784
Geoff Langa953b522018-02-21 16:56:23 -05005785 angle::CheckedNumeric<int> readExtent = start;
5786 readExtent += length;
5787 if (!readExtent.IsValid())
5788 {
5789 return false;
5790 }
5791
5792 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 {
5794 // Subtract the region to the right of the read buffer
5795 clippedExtent -= (readExtent - bufferSize);
5796 }
5797
5798 if (!clippedExtent.IsValid())
5799 {
Geoff Langa953b522018-02-21 16:56:23 -05005800 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 }
5802
Geoff Langa953b522018-02-21 16:56:23 -05005803 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5804 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 };
5806
Geoff Langa953b522018-02-21 16:56:23 -05005807 GLsizei writtenColumns = 0;
5808 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5809 {
5810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5811 return false;
5812 }
5813
5814 GLsizei writtenRows = 0;
5815 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5816 {
5817 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5818 return false;
5819 }
5820
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 if (columns != nullptr)
5822 {
Geoff Langa953b522018-02-21 16:56:23 -05005823 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005824 }
5825
5826 if (rows != nullptr)
5827 {
Geoff Langa953b522018-02-21 16:56:23 -05005828 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 }
5830
5831 return true;
5832}
5833
5834template <typename ParamType>
5835bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005836 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 GLenum pname,
5838 GLsizei bufSize,
5839 const ParamType *params)
5840{
5841 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5842 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005843 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005844 return false;
5845 }
5846
5847 if (context->getTargetTexture(target) == nullptr)
5848 {
5849 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 return false;
5852 }
5853
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005854 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 if (bufSize >= 0 && bufSize < minBufSize)
5856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 return false;
5859 }
5860
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005861 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5862 {
5863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5864 return false;
5865 }
5866
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 switch (pname)
5868 {
5869 case GL_TEXTURE_WRAP_R:
5870 case GL_TEXTURE_SWIZZLE_R:
5871 case GL_TEXTURE_SWIZZLE_G:
5872 case GL_TEXTURE_SWIZZLE_B:
5873 case GL_TEXTURE_SWIZZLE_A:
5874 case GL_TEXTURE_BASE_LEVEL:
5875 case GL_TEXTURE_MAX_LEVEL:
5876 case GL_TEXTURE_COMPARE_MODE:
5877 case GL_TEXTURE_COMPARE_FUNC:
5878 case GL_TEXTURE_MIN_LOD:
5879 case GL_TEXTURE_MAX_LOD:
5880 if (context->getClientMajorVersion() < 3)
5881 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005883 return false;
5884 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005885 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005887 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5888 "available without "
5889 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 return false;
5891 }
5892 break;
5893
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005894 case GL_GENERATE_MIPMAP:
5895 case GL_TEXTURE_CROP_RECT_OES:
5896 if (context->getClientMajorVersion() > 1)
5897 {
5898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5899 return false;
5900 }
5901 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005902 default:
5903 break;
5904 }
5905
Olli Etuahod310a432018-08-24 15:40:23 +03005906 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005907 {
5908 switch (pname)
5909 {
5910 case GL_TEXTURE_MIN_FILTER:
5911 case GL_TEXTURE_MAG_FILTER:
5912 case GL_TEXTURE_WRAP_S:
5913 case GL_TEXTURE_WRAP_T:
5914 case GL_TEXTURE_WRAP_R:
5915 case GL_TEXTURE_MIN_LOD:
5916 case GL_TEXTURE_MAX_LOD:
5917 case GL_TEXTURE_COMPARE_MODE:
5918 case GL_TEXTURE_COMPARE_FUNC:
5919 context->handleError(InvalidEnum()
5920 << "Invalid parameter for 2D multisampled textures.");
5921 return false;
5922 }
5923 }
5924
Jamie Madillbe849e42017-05-02 15:49:00 -04005925 switch (pname)
5926 {
5927 case GL_TEXTURE_WRAP_S:
5928 case GL_TEXTURE_WRAP_T:
5929 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005930 {
5931 bool restrictedWrapModes =
5932 target == TextureType::External || target == TextureType::Rectangle;
5933 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005935 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005937 }
5938 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005939
5940 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005941 {
5942 bool restrictedMinFilter =
5943 target == TextureType::External || target == TextureType::Rectangle;
5944 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005945 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005946 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005947 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005948 }
5949 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005950
5951 case GL_TEXTURE_MAG_FILTER:
5952 if (!ValidateTextureMagFilterValue(context, params))
5953 {
5954 return false;
5955 }
5956 break;
5957
5958 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005959 if (!context->getExtensions().textureUsage)
5960 {
5961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5962 return false;
5963 }
5964
Jamie Madillbe849e42017-05-02 15:49:00 -04005965 switch (ConvertToGLenum(params[0]))
5966 {
5967 case GL_NONE:
5968 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5969 break;
5970
5971 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005973 return false;
5974 }
5975 break;
5976
5977 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005978 {
5979 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5980 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005981 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005982 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005984 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5985 }
5986 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005987
5988 case GL_TEXTURE_MIN_LOD:
5989 case GL_TEXTURE_MAX_LOD:
5990 // any value is permissible
5991 break;
5992
5993 case GL_TEXTURE_COMPARE_MODE:
5994 if (!ValidateTextureCompareModeValue(context, params))
5995 {
5996 return false;
5997 }
5998 break;
5999
6000 case GL_TEXTURE_COMPARE_FUNC:
6001 if (!ValidateTextureCompareFuncValue(context, params))
6002 {
6003 return false;
6004 }
6005 break;
6006
6007 case GL_TEXTURE_SWIZZLE_R:
6008 case GL_TEXTURE_SWIZZLE_G:
6009 case GL_TEXTURE_SWIZZLE_B:
6010 case GL_TEXTURE_SWIZZLE_A:
6011 switch (ConvertToGLenum(params[0]))
6012 {
6013 case GL_RED:
6014 case GL_GREEN:
6015 case GL_BLUE:
6016 case GL_ALPHA:
6017 case GL_ZERO:
6018 case GL_ONE:
6019 break;
6020
6021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 return false;
6024 }
6025 break;
6026
6027 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006028 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006030 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006031 return false;
6032 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006033 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006035 context->handleError(InvalidOperation()
6036 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006037 return false;
6038 }
Olli Etuahod310a432018-08-24 15:40:23 +03006039 if ((target == TextureType::_2DMultisample ||
6040 target == TextureType::_2DMultisampleArray) &&
6041 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006042 {
6043 context->handleError(InvalidOperation()
6044 << "Base level must be 0 for multisampled textures.");
6045 return false;
6046 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006047 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006048 {
6049 context->handleError(InvalidOperation()
6050 << "Base level must be 0 for rectangle textures.");
6051 return false;
6052 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006053 break;
6054
6055 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006056 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006058 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006059 return false;
6060 }
6061 break;
6062
6063 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6064 if (context->getClientVersion() < Version(3, 1))
6065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006067 return false;
6068 }
6069 switch (ConvertToGLenum(params[0]))
6070 {
6071 case GL_DEPTH_COMPONENT:
6072 case GL_STENCIL_INDEX:
6073 break;
6074
6075 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 return false;
6078 }
6079 break;
6080
6081 case GL_TEXTURE_SRGB_DECODE_EXT:
6082 if (!ValidateTextureSRGBDecodeValue(context, params))
6083 {
6084 return false;
6085 }
6086 break;
6087
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006088 case GL_GENERATE_MIPMAP:
6089 case GL_TEXTURE_CROP_RECT_OES:
6090 if (context->getClientMajorVersion() > 1)
6091 {
6092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6093 return false;
6094 }
6095 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006096 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006098 return false;
6099 }
6100
6101 return true;
6102}
6103
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006104template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6105template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006106
Jamie Madill5b772312018-03-08 20:28:32 -05006107bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006108{
6109 if (index >= MAX_VERTEX_ATTRIBS)
6110 {
6111 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6112 return false;
6113 }
6114
6115 return true;
6116}
6117
6118bool ValidateGetActiveUniformBlockivBase(Context *context,
6119 GLuint program,
6120 GLuint uniformBlockIndex,
6121 GLenum pname,
6122 GLsizei *length)
6123{
6124 if (length)
6125 {
6126 *length = 0;
6127 }
6128
6129 if (context->getClientMajorVersion() < 3)
6130 {
6131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6132 return false;
6133 }
6134
6135 Program *programObject = GetValidProgram(context, program);
6136 if (!programObject)
6137 {
6138 return false;
6139 }
6140
6141 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6142 {
6143 context->handleError(InvalidValue()
6144 << "uniformBlockIndex exceeds active uniform block count.");
6145 return false;
6146 }
6147
6148 switch (pname)
6149 {
6150 case GL_UNIFORM_BLOCK_BINDING:
6151 case GL_UNIFORM_BLOCK_DATA_SIZE:
6152 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6153 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6154 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6155 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6156 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6157 break;
6158
6159 default:
6160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6161 return false;
6162 }
6163
6164 if (length)
6165 {
6166 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6167 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006168 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006169 programObject->getUniformBlockByIndex(uniformBlockIndex);
6170 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6171 }
6172 else
6173 {
6174 *length = 1;
6175 }
6176 }
6177
6178 return true;
6179}
6180
Jamie Madill9696d072017-08-26 23:19:57 -04006181template <typename ParamType>
6182bool ValidateSamplerParameterBase(Context *context,
6183 GLuint sampler,
6184 GLenum pname,
6185 GLsizei bufSize,
6186 ParamType *params)
6187{
6188 if (context->getClientMajorVersion() < 3)
6189 {
6190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6191 return false;
6192 }
6193
6194 if (!context->isSampler(sampler))
6195 {
6196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6197 return false;
6198 }
6199
6200 const GLsizei minBufSize = 1;
6201 if (bufSize >= 0 && bufSize < minBufSize)
6202 {
6203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6204 return false;
6205 }
6206
6207 switch (pname)
6208 {
6209 case GL_TEXTURE_WRAP_S:
6210 case GL_TEXTURE_WRAP_T:
6211 case GL_TEXTURE_WRAP_R:
6212 if (!ValidateTextureWrapModeValue(context, params, false))
6213 {
6214 return false;
6215 }
6216 break;
6217
6218 case GL_TEXTURE_MIN_FILTER:
6219 if (!ValidateTextureMinFilterValue(context, params, false))
6220 {
6221 return false;
6222 }
6223 break;
6224
6225 case GL_TEXTURE_MAG_FILTER:
6226 if (!ValidateTextureMagFilterValue(context, params))
6227 {
6228 return false;
6229 }
6230 break;
6231
6232 case GL_TEXTURE_MIN_LOD:
6233 case GL_TEXTURE_MAX_LOD:
6234 // any value is permissible
6235 break;
6236
6237 case GL_TEXTURE_COMPARE_MODE:
6238 if (!ValidateTextureCompareModeValue(context, params))
6239 {
6240 return false;
6241 }
6242 break;
6243
6244 case GL_TEXTURE_COMPARE_FUNC:
6245 if (!ValidateTextureCompareFuncValue(context, params))
6246 {
6247 return false;
6248 }
6249 break;
6250
6251 case GL_TEXTURE_SRGB_DECODE_EXT:
6252 if (!ValidateTextureSRGBDecodeValue(context, params))
6253 {
6254 return false;
6255 }
6256 break;
6257
Luc Ferron1b1a8642018-01-23 15:12:01 -05006258 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6259 {
6260 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6261 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6262 {
6263 return false;
6264 }
6265 }
6266 break;
6267
Jamie Madill9696d072017-08-26 23:19:57 -04006268 default:
6269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6270 return false;
6271 }
6272
6273 return true;
6274}
6275
6276template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6277template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6278
6279bool ValidateGetSamplerParameterBase(Context *context,
6280 GLuint sampler,
6281 GLenum pname,
6282 GLsizei *length)
6283{
6284 if (length)
6285 {
6286 *length = 0;
6287 }
6288
6289 if (context->getClientMajorVersion() < 3)
6290 {
6291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6292 return false;
6293 }
6294
6295 if (!context->isSampler(sampler))
6296 {
6297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6298 return false;
6299 }
6300
6301 switch (pname)
6302 {
6303 case GL_TEXTURE_WRAP_S:
6304 case GL_TEXTURE_WRAP_T:
6305 case GL_TEXTURE_WRAP_R:
6306 case GL_TEXTURE_MIN_FILTER:
6307 case GL_TEXTURE_MAG_FILTER:
6308 case GL_TEXTURE_MIN_LOD:
6309 case GL_TEXTURE_MAX_LOD:
6310 case GL_TEXTURE_COMPARE_MODE:
6311 case GL_TEXTURE_COMPARE_FUNC:
6312 break;
6313
Luc Ferron1b1a8642018-01-23 15:12:01 -05006314 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6315 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6316 {
6317 return false;
6318 }
6319 break;
6320
Jamie Madill9696d072017-08-26 23:19:57 -04006321 case GL_TEXTURE_SRGB_DECODE_EXT:
6322 if (!context->getExtensions().textureSRGBDecode)
6323 {
6324 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6325 return false;
6326 }
6327 break;
6328
6329 default:
6330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6331 return false;
6332 }
6333
6334 if (length)
6335 {
6336 *length = 1;
6337 }
6338 return true;
6339}
6340
6341bool ValidateGetInternalFormativBase(Context *context,
6342 GLenum target,
6343 GLenum internalformat,
6344 GLenum pname,
6345 GLsizei bufSize,
6346 GLsizei *numParams)
6347{
6348 if (numParams)
6349 {
6350 *numParams = 0;
6351 }
6352
6353 if (context->getClientMajorVersion() < 3)
6354 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006355 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006356 return false;
6357 }
6358
6359 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006360 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006361 {
6362 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6363 return false;
6364 }
6365
6366 switch (target)
6367 {
6368 case GL_RENDERBUFFER:
6369 break;
6370
6371 case GL_TEXTURE_2D_MULTISAMPLE:
6372 if (context->getClientVersion() < ES_3_1)
6373 {
Olli Etuahod310a432018-08-24 15:40:23 +03006374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006375 return false;
6376 }
6377 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006378 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6379 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006380 {
6381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6382 return false;
6383 }
6384 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006385 default:
6386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6387 return false;
6388 }
6389
6390 if (bufSize < 0)
6391 {
6392 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6393 return false;
6394 }
6395
6396 GLsizei maxWriteParams = 0;
6397 switch (pname)
6398 {
6399 case GL_NUM_SAMPLE_COUNTS:
6400 maxWriteParams = 1;
6401 break;
6402
6403 case GL_SAMPLES:
6404 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6405 break;
6406
6407 default:
6408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6409 return false;
6410 }
6411
6412 if (numParams)
6413 {
6414 // glGetInternalFormativ will not overflow bufSize
6415 *numParams = std::min(bufSize, maxWriteParams);
6416 }
6417
6418 return true;
6419}
6420
Jamie Madille98b1b52018-03-08 09:47:23 -05006421bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6422{
Jamie Madill427064d2018-04-13 16:20:34 -04006423 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006424 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006426 return false;
6427 }
6428 return true;
6429}
6430
Lingfeng Yang038dd532018-03-29 17:31:52 -07006431bool ValidateMultitextureUnit(Context *context, GLenum texture)
6432{
6433 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6434 {
6435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6436 return false;
6437 }
6438 return true;
6439}
6440
Olli Etuahod310a432018-08-24 15:40:23 +03006441bool ValidateTexStorageMultisample(Context *context,
6442 TextureType target,
6443 GLsizei samples,
6444 GLint internalFormat,
6445 GLsizei width,
6446 GLsizei height)
6447{
6448 const Caps &caps = context->getCaps();
6449 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6450 static_cast<GLuint>(height) > caps.max2DTextureSize)
6451 {
6452 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6453 return false;
6454 }
6455
6456 if (samples == 0)
6457 {
6458 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6459 return false;
6460 }
6461
6462 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6463 if (!formatCaps.textureAttachment)
6464 {
6465 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6466 return false;
6467 }
6468
6469 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6470 // is one of the unsized base internalformats listed in table 8.11.
6471 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6472 if (formatInfo.internalFormat == GL_NONE)
6473 {
6474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6475 return false;
6476 }
6477
6478 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6479 {
6480 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6481 return false;
6482 }
6483
6484 Texture *texture = context->getTargetTexture(target);
6485 if (!texture || texture->id() == 0)
6486 {
6487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6488 return false;
6489 }
6490
6491 if (texture->getImmutableFormat())
6492 {
6493 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6494 return false;
6495 }
6496 return true;
6497}
6498
Jamie Madillc29968b2016-01-20 11:17:23 -05006499} // namespace gl