blob: ecf056cbecd1f14514b3bd2499b3f14ed5f47251 [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 Madill2da53562018-08-01 11:34:47 -040082bool ValidateDrawAttribs(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 Madilla2d1d2d2018-08-01 11:34:46 -040087 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
88 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040090 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -040091 }
James Darpiniane8a93c62018-01-04 18:02:24 -080092
Jamie Madill88602e62018-08-08 12:49:30 -040093 // An overflow can happen when adding the offset. Check against a special constant.
94 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow ||
96 context->getStateCache().getInstancedVertexElementLimit() ==
97 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040098 {
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
100 return false;
101 }
102
103 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
104 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill5b772312018-03-08 20:28:32 -0500109bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400110{
111 switch (type)
112 {
113 // Types referenced in Table 3.4 of the ES 2.0.25 spec
114 case GL_UNSIGNED_BYTE:
115 case GL_UNSIGNED_SHORT_4_4_4_4:
116 case GL_UNSIGNED_SHORT_5_5_5_1:
117 case GL_UNSIGNED_SHORT_5_6_5:
118 return context->getClientVersion() >= ES_2_0;
119
120 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
121 case GL_BYTE:
122 case GL_INT:
123 case GL_SHORT:
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_10F_11F_11F_REV:
126 case GL_UNSIGNED_INT_24_8:
127 case GL_UNSIGNED_INT_2_10_10_10_REV:
128 case GL_UNSIGNED_INT_5_9_9_9_REV:
129 case GL_UNSIGNED_SHORT:
130 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
131 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
132 return context->getClientVersion() >= ES_3_0;
133
134 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400135 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
136 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400137
138 case GL_HALF_FLOAT:
139 return context->getClientVersion() >= ES_3_0 ||
140 context->getExtensions().textureHalfFloat;
141
142 case GL_HALF_FLOAT_OES:
143 return context->getExtensions().colorBufferHalfFloat;
144
145 default:
146 return false;
147 }
148}
149
Jamie Madill5b772312018-03-08 20:28:32 -0500150bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400151{
152 switch (format)
153 {
154 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
155 case GL_RGBA:
156 case GL_RGB:
157 case GL_ALPHA:
158 return context->getClientVersion() >= ES_2_0;
159
160 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
161 case GL_RG:
162 case GL_RED:
163 case GL_RGBA_INTEGER:
164 case GL_RGB_INTEGER:
165 case GL_RG_INTEGER:
166 case GL_RED_INTEGER:
167 return context->getClientVersion() >= ES_3_0;
168
169 case GL_SRGB_ALPHA_EXT:
170 case GL_SRGB_EXT:
171 return context->getExtensions().sRGB;
172
173 case GL_BGRA_EXT:
174 return context->getExtensions().readFormatBGRA;
175
176 default:
177 return false;
178 }
179}
180
Jamie Madill5b772312018-03-08 20:28:32 -0500181bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400182 GLenum framebufferComponentType,
183 GLenum format,
184 GLenum type)
185{
186 switch (framebufferComponentType)
187 {
188 case GL_UNSIGNED_NORMALIZED:
189 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
190 // ReadPixels with BGRA even if the extension is not present
191 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
192 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
193 type == GL_UNSIGNED_BYTE);
194
195 case GL_SIGNED_NORMALIZED:
196 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
197
198 case GL_INT:
199 return (format == GL_RGBA_INTEGER && type == GL_INT);
200
201 case GL_UNSIGNED_INT:
202 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
203
204 case GL_FLOAT:
205 return (format == GL_RGBA && type == GL_FLOAT);
206
207 default:
208 UNREACHABLE();
209 return false;
210 }
211}
212
Geoff Langc1984ed2016-10-07 12:41:00 -0400213template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400214bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400215{
216 switch (ConvertToGLenum(params[0]))
217 {
218 case GL_CLAMP_TO_EDGE:
219 break;
220
221 case GL_REPEAT:
222 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400223 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400224 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400225 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400227 return false;
228 }
229 break;
230
231 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400233 return false;
234 }
235
236 return true;
237}
238
239template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400240bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400241{
242 switch (ConvertToGLenum(params[0]))
243 {
244 case GL_NEAREST:
245 case GL_LINEAR:
246 break;
247
248 case GL_NEAREST_MIPMAP_NEAREST:
249 case GL_LINEAR_MIPMAP_NEAREST:
250 case GL_NEAREST_MIPMAP_LINEAR:
251 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400252 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400253 {
254 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400256 return false;
257 }
258 break;
259
260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400262 return false;
263 }
264
265 return true;
266}
267
268template <typename ParamType>
269bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
270{
271 switch (ConvertToGLenum(params[0]))
272 {
273 case GL_NEAREST:
274 case GL_LINEAR:
275 break;
276
277 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
286bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
287{
288 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_NONE:
292 case GL_COMPARE_REF_TO_TEXTURE:
293 break;
294
295 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 return false;
298 }
299
300 return true;
301}
302
303template <typename ParamType>
304bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
305{
306 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
307 switch (ConvertToGLenum(params[0]))
308 {
309 case GL_LEQUAL:
310 case GL_GEQUAL:
311 case GL_LESS:
312 case GL_GREATER:
313 case GL_EQUAL:
314 case GL_NOTEQUAL:
315 case GL_ALWAYS:
316 case GL_NEVER:
317 break;
318
319 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400321 return false;
322 }
323
324 return true;
325}
326
327template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700328bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
329{
330 if (!context->getExtensions().textureSRGBDecode)
331 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700333 return false;
334 }
335
336 switch (ConvertToGLenum(params[0]))
337 {
338 case GL_DECODE_EXT:
339 case GL_SKIP_DECODE_EXT:
340 break;
341
342 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700344 return false;
345 }
346
347 return true;
348}
349
Luc Ferron1b1a8642018-01-23 15:12:01 -0500350bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
351{
352 if (!context->getExtensions().textureFilterAnisotropic)
353 {
354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
355 return false;
356 }
357
358 return true;
359}
360
361bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
362{
363 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
364 {
365 return false;
366 }
367
368 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
369
370 if (paramValue < 1 || paramValue > largest)
371 {
372 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
373 return false;
374 }
375
376 return true;
377}
378
Jamie Madill5b772312018-03-08 20:28:32 -0500379bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400380{
381 const Program *program = context->getGLState().getProgram();
382 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
383
Jamie Madille7d80f32018-08-08 15:49:23 -0400384 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
385 framebuffer->getDrawBufferTypeMask().to_ulong(),
386 program->getActiveOutputVariables().to_ulong(),
387 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400388}
389
Jamie Madill5b772312018-03-08 20:28:32 -0500390bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400391{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700392 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400393 const Program *program = context->getGLState().getProgram();
394 const VertexArray *vao = context->getGLState().getVertexArray();
395
Brandon Jonesc405ae72017-12-06 14:15:03 -0800396 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
397 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
398 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
399
400 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
401 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
402 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
403
Jamie Madille7d80f32018-08-08 15:49:23 -0400404 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
405 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
406 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400407}
408
Jamie Madill493f9572018-05-24 19:52:15 -0400409bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
410 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800411{
412 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400413 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800414 {
Jamie Madill493f9572018-05-24 19:52:15 -0400415 case PrimitiveMode::Points:
416 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
417 case PrimitiveMode::Lines:
418 case PrimitiveMode::LineStrip:
419 case PrimitiveMode::LineLoop:
420 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
421 case PrimitiveMode::LinesAdjacency:
422 case PrimitiveMode::LineStripAdjacency:
423 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
424 case PrimitiveMode::Triangles:
425 case PrimitiveMode::TriangleFan:
426 case PrimitiveMode::TriangleStrip:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
428 case PrimitiveMode::TrianglesAdjacency:
429 case PrimitiveMode::TriangleStripAdjacency:
430 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800431 default:
432 UNREACHABLE();
433 return false;
434 }
435}
436
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700437// GLES1 texture parameters are a small subset of the others
438bool IsValidGLES1TextureParameter(GLenum pname)
439{
440 switch (pname)
441 {
442 case GL_TEXTURE_MAG_FILTER:
443 case GL_TEXTURE_MIN_FILTER:
444 case GL_TEXTURE_WRAP_S:
445 case GL_TEXTURE_WRAP_T:
446 case GL_TEXTURE_WRAP_R:
447 case GL_GENERATE_MIPMAP:
448 case GL_TEXTURE_CROP_RECT_OES:
449 return true;
450 default:
451 return false;
452 }
453}
Geoff Langf41a7152016-09-19 15:11:17 -0400454} // anonymous namespace
455
Brandon Jonesd1049182018-03-28 10:02:20 -0700456void SetRobustLengthParam(GLsizei *length, GLsizei value)
457{
458 if (length)
459 {
460 *length = value;
461 }
462}
463
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500464bool IsETC2EACFormat(const GLenum format)
465{
466 // ES 3.1, Table 8.19
467 switch (format)
468 {
469 case GL_COMPRESSED_R11_EAC:
470 case GL_COMPRESSED_SIGNED_R11_EAC:
471 case GL_COMPRESSED_RG11_EAC:
472 case GL_COMPRESSED_SIGNED_RG11_EAC:
473 case GL_COMPRESSED_RGB8_ETC2:
474 case GL_COMPRESSED_SRGB8_ETC2:
475 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
476 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
477 case GL_COMPRESSED_RGBA8_ETC2_EAC:
478 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
479 return true;
480
481 default:
482 return false;
483 }
484}
485
Jamie Madill5b772312018-03-08 20:28:32 -0500486bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400487{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800488 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800490 case TextureType::_2D:
491 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800492 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400493
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800494 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400495 return context->getExtensions().textureRectangle;
496
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800497 case TextureType::_3D:
498 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800499 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500500
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400503
He Yunchaoced53ae2016-11-29 15:00:51 +0800504 default:
505 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500506 }
Jamie Madill35d15012013-10-07 10:46:37 -0400507}
508
Jamie Madill5b772312018-03-08 20:28:32 -0500509bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500510{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800511 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500512 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 case TextureType::_2D:
514 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500515 return true;
516
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800517 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400518 return context->getExtensions().textureRectangle;
519
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500520 default:
521 return false;
522 }
523}
524
Jamie Madill5b772312018-03-08 20:28:32 -0500525bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526{
527 switch (target)
528 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 case TextureType::_3D:
530 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300531 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500532
533 default:
534 return false;
535 }
536}
537
Ian Ewellbda75592016-04-18 17:25:54 -0400538// Most texture GL calls are not compatible with external textures, so we have a separate validation
539// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500540bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400541{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400543 (context->getExtensions().eglImageExternal ||
544 context->getExtensions().eglStreamConsumerExternal);
545}
546
Shannon Woods4dfed832014-03-17 20:03:39 -0400547// This function differs from ValidTextureTarget in that the target must be
548// usable as the destination of a 2D operation-- so a cube face is valid, but
549// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400550// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500551bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400552{
553 switch (target)
554 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 case TextureTarget::_2D:
556 case TextureTarget::CubeMapNegativeX:
557 case TextureTarget::CubeMapNegativeY:
558 case TextureTarget::CubeMapNegativeZ:
559 case TextureTarget::CubeMapPositiveX:
560 case TextureTarget::CubeMapPositiveY:
561 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800562 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400564 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800565 default:
566 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500567 }
568}
569
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800570bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400571 PrimitiveMode transformFeedbackPrimitiveMode,
572 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800573{
574 ASSERT(context);
575
576 if (!context->getExtensions().geometryShader)
577 {
578 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
579 // that does not match the current transform feedback object's draw mode (if transform
580 // feedback is active), (3.0.2, section 2.14, pg 86)
581 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
582 }
583
584 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400585 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800586 {
Jamie Madill493f9572018-05-24 19:52:15 -0400587 case PrimitiveMode::Points:
588 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
589 case PrimitiveMode::Lines:
590 case PrimitiveMode::LineStrip:
591 case PrimitiveMode::LineLoop:
592 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
593 case PrimitiveMode::Triangles:
594 case PrimitiveMode::TriangleFan:
595 case PrimitiveMode::TriangleStrip:
596 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800597 default:
598 UNREACHABLE();
599 return false;
600 }
601}
602
Jamie Madill5b772312018-03-08 20:28:32 -0500603bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400604 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400605 GLsizei count,
606 GLenum type,
607 const GLvoid *indices,
608 GLsizei primcount)
609{
610 if (primcount < 0)
611 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700612 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400613 return false;
614 }
615
616 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
617 {
618 return false;
619 }
620
Jamie Madill9fdaa492018-02-16 10:52:11 -0500621 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400622}
623
624bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400625 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 GLint first,
627 GLsizei count,
628 GLsizei primcount)
629{
630 if (primcount < 0)
631 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700632 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 return false;
634 }
635
636 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
637 {
638 return false;
639 }
640
Jamie Madill9fdaa492018-02-16 10:52:11 -0500641 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400642}
643
Jamie Madill5b772312018-03-08 20:28:32 -0500644bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400645{
646 // Verify there is at least one active attribute with a divisor of zero
647 const State &state = context->getGLState();
648
649 Program *program = state.getProgram();
650
651 const auto &attribs = state.getVertexArray()->getVertexAttributes();
652 const auto &bindings = state.getVertexArray()->getVertexBindings();
653 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
654 {
655 const VertexAttribute &attrib = attribs[attributeIndex];
656 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300657 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400658 {
659 return true;
660 }
661 }
662
Brandon Jonesafa75152017-07-21 13:11:29 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665}
666
Jamie Madill5b772312018-03-08 20:28:32 -0500667bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668{
669 switch (target)
670 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800671 case TextureType::_3D:
672 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800673 return true;
674 default:
675 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400676 }
677}
678
Jamie Madill5b772312018-03-08 20:28:32 -0500679bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800680{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800681 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800682 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800683 case TextureType::_2D:
684 case TextureType::_2DArray:
685 case TextureType::_2DMultisample:
686 case TextureType::CubeMap:
687 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800688 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800689 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400690 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800691 default:
692 return false;
693 }
694}
695
Jamie Madill5b772312018-03-08 20:28:32 -0500696bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500697{
He Yunchaoced53ae2016-11-29 15:00:51 +0800698 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
699 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400700 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500701
702 switch (target)
703 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 case GL_FRAMEBUFFER:
705 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400706
He Yunchaoced53ae2016-11-29 15:00:51 +0800707 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400709 return (context->getExtensions().framebufferBlit ||
710 context->getClientMajorVersion() >= 3);
711
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 default:
713 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500714 }
715}
716
Jamie Madill5b772312018-03-08 20:28:32 -0500717bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400718{
Jamie Madillc29968b2016-01-20 11:17:23 -0500719 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400720 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800721 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400722 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800723 case TextureType::_2D:
724 case TextureType::_2DArray:
725 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500726 maxDimension = caps.max2DTextureSize;
727 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800729 maxDimension = caps.maxCubeMapTextureSize;
730 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800731 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400732 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800733 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 maxDimension = caps.max3DTextureSize;
735 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 default:
737 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400738 }
739
Jamie Madill43da7c42018-08-01 11:34:49 -0400740 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400741}
742
Jamie Madill5b772312018-03-08 20:28:32 -0500743bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800744 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700745 GLint level,
746 GLsizei width,
747 GLsizei height,
748 GLsizei depth,
749 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400750{
Brandon Jones6cad5662017-06-14 13:25:13 -0700751 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400752 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700753 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400754 return false;
755 }
Austin Kinross08528e12015-10-07 16:24:40 -0700756 // TexSubImage parameters can be NPOT without textureNPOT extension,
757 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500758 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500759 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500760 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400761 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400762 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700763 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400764 return false;
765 }
766
767 if (!ValidMipLevel(context, target, level))
768 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400770 return false;
771 }
772
773 return true;
774}
775
Geoff Lang966c9402017-04-18 12:38:27 -0400776bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
777{
778 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
779 (size % blockSize == 0);
780}
781
Jamie Madill5b772312018-03-08 20:28:32 -0500782bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500783 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400784 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500785 GLsizei width,
786 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400787{
Jamie Madill43da7c42018-08-01 11:34:49 -0400788 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400789 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400790 {
791 return false;
792 }
793
Geoff Lang966c9402017-04-18 12:38:27 -0400794 if (width < 0 || height < 0)
795 {
796 return false;
797 }
798
799 if (CompressedTextureFormatRequiresExactSize(internalFormat))
800 {
801 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
802 // block size for level 0 but WebGL disallows this.
803 bool smallerThanBlockSizeAllowed =
804 level > 0 || !context->getExtensions().webglCompatibility;
805
806 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
807 smallerThanBlockSizeAllowed) ||
808 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
809 smallerThanBlockSizeAllowed))
810 {
811 return false;
812 }
813 }
814
815 return true;
816}
817
Jamie Madill5b772312018-03-08 20:28:32 -0500818bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLenum internalFormat,
820 GLint xoffset,
821 GLint yoffset,
822 GLsizei width,
823 GLsizei height,
824 size_t textureWidth,
825 size_t textureHeight)
826{
Jamie Madill43da7c42018-08-01 11:34:49 -0400827 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400828 if (!formatInfo.compressed)
829 {
830 return false;
831 }
832
Geoff Lang44ff5a72017-02-03 15:15:43 -0500833 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400834 {
835 return false;
836 }
837
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500838 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400839 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500840 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400841 yoffset % formatInfo.compressedBlockHeight != 0)
842 {
843 return false;
844 }
845
846 // Allowed to either have data that is a multiple of block size or is smaller than the block
847 // size but fills the entire mip
848 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
849 static_cast<size_t>(width) == textureWidth &&
850 static_cast<size_t>(height) == textureHeight;
851 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
852 (height % formatInfo.compressedBlockHeight) == 0;
853 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400854 {
855 return false;
856 }
857 }
858
Geoff Langd4f180b2013-09-24 13:57:44 -0400859 return true;
860}
861
Jamie Madill5b772312018-03-08 20:28:32 -0500862bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800863 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400864 GLsizei width,
865 GLsizei height,
866 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400867 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400868 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400869 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400870 GLsizei imageSize)
871{
Jamie Madill43da7c42018-08-01 11:34:49 -0400872 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400873 if (pixelUnpackBuffer == nullptr && imageSize < 0)
874 {
875 // Checks are not required
876 return true;
877 }
878
879 // ...the data would be unpacked from the buffer object such that the memory reads required
880 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400881 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400882 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400883 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 const auto &unpack = context->getGLState().getUnpackState();
885
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800886 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400887 GLuint endByte = 0;
888 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 return false;
892 }
893
Geoff Langff5b2d52016-09-07 11:32:23 -0400894 if (pixelUnpackBuffer)
895 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400896 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
898 checkedEndByte += checkedOffset;
899
900 if (!checkedEndByte.IsValid() ||
901 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
902 {
903 // Overflow past the end of the buffer
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 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800907 if (context->getExtensions().webglCompatibility &&
908 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
909 {
910 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
911 PixelUnpackBufferBoundForTransformFeedback);
912 return false;
913 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400914 }
915 else
916 {
917 ASSERT(imageSize >= 0);
918 if (pixels == nullptr && imageSize != 0)
919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500920 context->handleError(InvalidOperation()
921 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400922 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 }
924
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400925 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 return false;
929 }
930 }
931
932 return true;
933}
934
Corentin Wallezad3ae902018-03-09 13:40:42 -0500935bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500936{
Geoff Lang37dde692014-01-31 16:34:54 -0500937 switch (queryType)
938 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500939 case QueryType::AnySamples:
940 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400941 return context->getClientMajorVersion() >= 3 ||
942 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500943 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800944 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500945 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800946 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500947 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500949 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800950 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 default:
952 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500953 }
954}
955
Jamie Madill5b772312018-03-08 20:28:32 -0500956bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400957 GLenum type,
958 GLboolean normalized,
959 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400960 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400961 bool pureInteger)
962{
963 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
965 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
966 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
967 // parameter exceeds 255.
968 constexpr GLsizei kMaxWebGLStride = 255;
969 if (stride > kMaxWebGLStride)
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidValue()
972 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400973 return false;
974 }
975
976 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
977 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
978 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
979 // or an INVALID_OPERATION error is generated.
980 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
981 size_t typeSize = GetVertexFormatTypeSize(internalType);
982
983 ASSERT(isPow2(typeSize) && typeSize > 0);
984 size_t sizeMask = (typeSize - 1);
985 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
986 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 if ((stride & sizeMask) != 0)
992 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 return false;
995 }
996
997 return true;
998}
999
Jamie Madill5b772312018-03-08 20:28:32 -05001000Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001001{
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1003 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1004 // or program object and INVALID_OPERATION if the provided name identifies an object
1005 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001006
Dian Xiang769769a2015-09-09 15:20:08 -07001007 Program *validProgram = context->getProgram(id);
1008
1009 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001010 {
Dian Xiang769769a2015-09-09 15:20:08 -07001011 if (context->getShader(id))
1012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001014 }
1015 else
1016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001017 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001018 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001019 }
Dian Xiang769769a2015-09-09 15:20:08 -07001020
1021 return validProgram;
1022}
1023
Jamie Madill5b772312018-03-08 20:28:32 -05001024Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001025{
1026 // See ValidProgram for spec details.
1027
1028 Shader *validShader = context->getShader(id);
1029
1030 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001031 {
Dian Xiang769769a2015-09-09 15:20:08 -07001032 if (context->getProgram(id))
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001035 }
1036 else
1037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001039 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001040 }
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001043}
1044
Jamie Madill43da7c42018-08-01 11:34:49 -04001045bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001046{
Geoff Langfa125c92017-10-24 13:01:46 -04001047 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001048 {
Geoff Langfa125c92017-10-24 13:01:46 -04001049 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1050 {
1051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1052 return false;
1053 }
Jamie Madillb4472272014-07-03 10:38:55 -04001054
Geoff Langfa125c92017-10-24 13:01:46 -04001055 // Color attachment 0 is validated below because it is always valid
1056 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001058 {
Geoff Langfa125c92017-10-24 13:01:46 -04001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001061 }
1062 }
1063 else
1064 {
1065 switch (attachment)
1066 {
Geoff Langfa125c92017-10-24 13:01:46 -04001067 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001068 case GL_DEPTH_ATTACHMENT:
1069 case GL_STENCIL_ATTACHMENT:
1070 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001071
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_DEPTH_STENCIL_ATTACHMENT:
1073 if (!context->getExtensions().webglCompatibility &&
1074 context->getClientMajorVersion() < 3)
1075 {
Geoff Langfa125c92017-10-24 13:01:46 -04001076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001080
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001084 }
1085 }
1086
1087 return true;
1088}
1089
Jamie Madill5b772312018-03-08 20:28:32 -05001090bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 GLenum target,
1092 GLsizei samples,
1093 GLenum internalformat,
1094 GLsizei width,
1095 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096{
1097 switch (target)
1098 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001099 case GL_RENDERBUFFER:
1100 break;
1101 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105
1106 if (width < 0 || height < 0 || samples < 0)
1107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001112 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1113 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1114
1115 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001116 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001118 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
1122 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1123 // 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 -08001124 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001125 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001126 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 }
1131
Geoff Langaae65a42014-05-26 12:43:44 -04001132 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 if (handle == 0)
1140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
1145 return true;
1146}
1147
Jamie Madill43da7c42018-08-01 11:34:49 -04001148bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001149 GLenum target,
1150 GLenum attachment,
1151 GLenum renderbuffertarget,
1152 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001153{
Geoff Lange8afa902017-09-27 15:00:43 -04001154 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001158 }
1159
Jamie Madill43da7c42018-08-01 11:34:49 -04001160 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161
Jamie Madill84115c92015-04-23 15:00:07 -04001162 ASSERT(framebuffer);
1163 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167 }
1168
Jamie Madillb4472272014-07-03 10:38:55 -04001169 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001170 {
Jamie Madillb4472272014-07-03 10:38:55 -04001171 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 }
1173
Jamie Madillab9d82c2014-01-21 16:38:14 -05001174 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1175 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1176 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1177 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1178 if (renderbuffer != 0)
1179 {
1180 if (!context->getRenderbuffer(renderbuffer))
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001184 }
1185 }
1186
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 return true;
1188}
1189
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001190bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001191 GLint srcX0,
1192 GLint srcY0,
1193 GLint srcX1,
1194 GLint srcY1,
1195 GLint dstX0,
1196 GLint dstY0,
1197 GLint dstX1,
1198 GLint dstY1,
1199 GLbitfield mask,
1200 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201{
1202 switch (filter)
1203 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 case GL_NEAREST:
1205 break;
1206 case GL_LINEAR:
1207 break;
1208 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 }
1212
1213 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001215 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1220 // color buffer, leaving only nearest being unfiltered from above
1221 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
Jamie Madill51f40ec2016-06-15 14:06:00 -04001227 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001228 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1229 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001230
1231 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
Jamie Madill427064d2018-04-13 16:20:34 -04001237 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001238 {
Jamie Madill48faf802014-11-06 15:27:22 -05001239 return false;
1240 }
1241
Jamie Madill427064d2018-04-13 16:20:34 -04001242 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001243 {
Jamie Madill48faf802014-11-06 15:27:22 -05001244 return false;
1245 }
1246
Qin Jiajiaaef92162018-02-27 13:51:44 +08001247 if (readFramebuffer->id() == drawFramebuffer->id())
1248 {
1249 context->handleError(InvalidOperation());
1250 return false;
1251 }
1252
Jamie Madille98b1b52018-03-08 09:47:23 -05001253 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001258 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1259 // always run it in order to avoid triggering driver bugs.
1260 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1261 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001262 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001263 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1264 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001265 }
1266
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1268
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 if (mask & GL_COLOR_BUFFER_BIT)
1270 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001271 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001272 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273
He Yunchao66a41a22016-12-15 16:45:05 +08001274 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001276 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277
Geoff Langa15472a2015-08-11 11:48:03 -04001278 for (size_t drawbufferIdx = 0;
1279 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Geoff Langa15472a2015-08-11 11:48:03 -04001281 const FramebufferAttachment *attachment =
1282 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1283 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001285 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286
Geoff Langb2f3d052013-08-13 12:49:27 -04001287 // The GL ES 3.0.2 spec (pg 193) states that:
1288 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1290 // as well
1291 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1292 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001293 // Changes with EXT_color_buffer_float:
1294 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001295 GLenum readComponentType = readFormat.info->componentType;
1296 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001298 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001299 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001300 drawComponentType == GL_SIGNED_NORMALIZED);
1301
1302 if (extensions.colorBufferFloat)
1303 {
1304 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1305 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1306
1307 if (readFixedOrFloat != drawFixedOrFloat)
1308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation()
1310 << "If the read buffer contains fixed-point or "
1311 "floating-point values, the draw buffer must "
1312 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001313 return false;
1314 }
1315 }
1316 else if (readFixedPoint != drawFixedPoint)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "If the read buffer contains fixed-point values, "
1320 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001321 return false;
1322 }
1323
1324 if (readComponentType == GL_UNSIGNED_INT &&
1325 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 }
1330
Jamie Madill6163c752015-12-07 16:32:59 -05001331 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
1336
Jamie Madilla3944d42016-07-22 22:13:26 -04001337 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001338 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001340 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 }
Geoff Lange4915782017-04-12 15:19:07 -04001343
1344 if (context->getExtensions().webglCompatibility &&
1345 *readColorBuffer == *attachment)
1346 {
1347 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 InvalidOperation()
1349 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001350 return false;
1351 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 }
1353 }
1354
Jamie Madilla3944d42016-07-22 22:13:26 -04001355 if ((readFormat.info->componentType == GL_INT ||
1356 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1357 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 }
He Yunchao66a41a22016-12-15 16:45:05 +08001363 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1364 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1365 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1366 // situation is an application error that would lead to a crash in ANGLE.
1367 else if (drawFramebuffer->hasEnabledDrawBuffer())
1368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(
1370 InvalidOperation()
1371 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001372 return false;
1373 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 }
1375
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001377 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1378 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001380 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001382 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001383 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001384 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001385 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001387 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 {
Kenneth Russell69382852017-07-21 16:38:44 -04001389 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001395 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001398 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
Geoff Lange4915782017-04-12 15:19:07 -04001400
1401 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(
1404 InvalidOperation()
1405 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001406 return false;
1407 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
He Yunchao66a41a22016-12-15 16:45:05 +08001409 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1410 else if (drawBuffer)
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1413 "depth/stencil attachment of a "
1414 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001415 return false;
1416 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418 }
1419
Martin Radeva3ed4572017-07-27 18:29:37 +03001420 // ANGLE_multiview, Revision 1:
1421 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001422 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1423 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1424 // views in the current read framebuffer is more than one.
1425 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001426 {
1427 context->handleError(InvalidFramebufferOperation()
1428 << "Attempt to read from a multi-view framebuffer.");
1429 return false;
1430 }
1431 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
1433 context->handleError(InvalidFramebufferOperation()
1434 << "Attempt to write to a multi-view framebuffer.");
1435 return false;
1436 }
1437
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 return true;
1439}
1440
Jamie Madill4928b7c2017-06-20 12:57:39 -04001441bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001442 GLint x,
1443 GLint y,
1444 GLsizei width,
1445 GLsizei height,
1446 GLenum format,
1447 GLenum type,
1448 GLsizei bufSize,
1449 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001450 GLsizei *columns,
1451 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001452 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001453{
1454 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 return false;
1457 }
1458
Brandon Jonesd1049182018-03-28 10:02:20 -07001459 GLsizei writeLength = 0;
1460 GLsizei writeColumns = 0;
1461 GLsizei writeRows = 0;
1462
1463 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1464 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001465 {
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001467 }
1468
Brandon Jonesd1049182018-03-28 10:02:20 -07001469 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001470 {
Geoff Langb1196682014-07-23 13:47:29 -04001471 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001472 }
1473
Brandon Jonesd1049182018-03-28 10:02:20 -07001474 SetRobustLengthParam(length, writeLength);
1475 SetRobustLengthParam(columns, writeColumns);
1476 SetRobustLengthParam(rows, writeRows);
1477
Jamie Madillc29968b2016-01-20 11:17:23 -05001478 return true;
1479}
1480
1481bool ValidateReadnPixelsEXT(Context *context,
1482 GLint x,
1483 GLint y,
1484 GLsizei width,
1485 GLsizei height,
1486 GLenum format,
1487 GLenum type,
1488 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001489 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001490{
1491 if (bufSize < 0)
1492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001493 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
Geoff Lang62fce5b2016-09-30 10:46:35 -04001497 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001498 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001499}
Jamie Madill26e91952014-03-05 15:01:27 -05001500
Jamie Madill4928b7c2017-06-20 12:57:39 -04001501bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001502 GLint x,
1503 GLint y,
1504 GLsizei width,
1505 GLsizei height,
1506 GLenum format,
1507 GLenum type,
1508 GLsizei bufSize,
1509 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001510 GLsizei *columns,
1511 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001512 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001513{
Brandon Jonesd1049182018-03-28 10:02:20 -07001514 GLsizei writeLength = 0;
1515 GLsizei writeColumns = 0;
1516 GLsizei writeRows = 0;
1517
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001519 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001520 return false;
1521 }
1522
Brandon Jonesd1049182018-03-28 10:02:20 -07001523 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1524 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001525 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001527 }
1528
Brandon Jonesd1049182018-03-28 10:02:20 -07001529 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001530 {
1531 return false;
1532 }
1533
Brandon Jonesd1049182018-03-28 10:02:20 -07001534 SetRobustLengthParam(length, writeLength);
1535 SetRobustLengthParam(columns, writeColumns);
1536 SetRobustLengthParam(rows, writeRows);
1537
Geoff Lang62fce5b2016-09-30 10:46:35 -04001538 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001539}
1540
Jamie Madill43da7c42018-08-01 11:34:49 -04001541bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542{
1543 if (!context->getExtensions().occlusionQueryBoolean &&
1544 !context->getExtensions().disjointTimerQuery)
1545 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001547 return false;
1548 }
1549
Olli Etuaho41997e72016-03-10 13:38:39 +02001550 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001551}
1552
Jamie Madill43da7c42018-08-01 11:34:49 -04001553bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554{
1555 if (!context->getExtensions().occlusionQueryBoolean &&
1556 !context->getExtensions().disjointTimerQuery)
1557 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001559 return false;
1560 }
1561
Olli Etuaho41997e72016-03-10 13:38:39 +02001562 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001563}
1564
Jamie Madill43da7c42018-08-01 11:34:49 -04001565bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001566{
1567 if (!context->getExtensions().occlusionQueryBoolean &&
1568 !context->getExtensions().disjointTimerQuery)
1569 {
1570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1571 return false;
1572 }
1573
1574 return true;
1575}
1576
Jamie Madill43da7c42018-08-01 11:34:49 -04001577bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001578{
1579 if (!ValidQueryType(context, target))
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001582 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001583 }
1584
1585 if (id == 0)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001589 }
1590
1591 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1592 // of zero, if the active query object name for <target> is non-zero (for the
1593 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1594 // the active query for either target is non-zero), if <id> is the name of an
1595 // existing query object whose type does not match <target>, or if <id> is the
1596 // active query object name for any query type, the error INVALID_OPERATION is
1597 // generated.
1598
1599 // Ensure no other queries are active
1600 // NOTE: If other queries than occlusion are supported, we will need to check
1601 // separately that:
1602 // a) The query ID passed is not the current active query for any target/type
1603 // b) There are no active queries for the requested target (and in the case
1604 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1605 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001606
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001607 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 Query *queryObject = context->getQuery(id, true, target);
1614
1615 // check that name was obtained with glGenQueries
1616 if (!queryObject)
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001619 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001620 }
1621
1622 // check for type mismatch
1623 if (queryObject->getType() != target)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 return true;
1630}
1631
Jamie Madill43da7c42018-08-01 11:34:49 -04001632bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001633{
1634 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001635 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638 return false;
1639 }
1640
1641 return ValidateBeginQueryBase(context, target, id);
1642}
1643
Jamie Madill43da7c42018-08-01 11:34:49 -04001644bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001645{
1646 if (!ValidQueryType(context, target))
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001650 }
1651
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001652 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001653
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001658 }
1659
Jamie Madill45c785d2014-05-13 14:09:34 -04001660 return true;
1661}
1662
Jamie Madill43da7c42018-08-01 11:34:49 -04001663bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664{
1665 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001666 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
1672 return ValidateEndQueryBase(context, target);
1673}
1674
Corentin Wallezad3ae902018-03-09 13:40:42 -05001675bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676{
1677 if (!context->getExtensions().disjointTimerQuery)
1678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001679 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680 return false;
1681 }
1682
Corentin Wallezad3ae902018-03-09 13:40:42 -05001683 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
1689 Query *queryObject = context->getQuery(id, true, target);
1690 if (queryObject == nullptr)
1691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001693 return false;
1694 }
1695
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001696 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
1702 return true;
1703}
1704
Corentin Wallezad3ae902018-03-09 13:40:42 -05001705bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706{
Geoff Lang2186c382016-10-14 10:54:54 -04001707 if (numParams)
1708 {
1709 *numParams = 0;
1710 }
1711
Corentin Wallezad3ae902018-03-09 13:40:42 -05001712 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 switch (pname)
1719 {
1720 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726 break;
1727 case GL_QUERY_COUNTER_BITS_EXT:
1728 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001729 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734 break;
1735 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001736 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
Geoff Lang2186c382016-10-14 10:54:54 -04001740 if (numParams)
1741 {
1742 // All queries return only one value
1743 *numParams = 1;
1744 }
1745
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 return true;
1747}
1748
Corentin Wallezad3ae902018-03-09 13:40:42 -05001749bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750{
1751 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001752 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 return false;
1756 }
1757
Geoff Lang2186c382016-10-14 10:54:54 -04001758 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759}
1760
Geoff Lang2186c382016-10-14 10:54:54 -04001761bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001762 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001763 GLenum pname,
1764 GLsizei bufSize,
1765 GLsizei *length,
1766 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767{
Geoff Lang2186c382016-10-14 10:54:54 -04001768 if (!ValidateRobustEntryPoint(context, bufSize))
1769 {
1770 return false;
1771 }
1772
Brandon Jonesd1049182018-03-28 10:02:20 -07001773 GLsizei numParams = 0;
1774
1775 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001776 {
1777 return false;
1778 }
1779
Brandon Jonesd1049182018-03-28 10:02:20 -07001780 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001781 {
1782 return false;
1783 }
1784
Brandon Jonesd1049182018-03-28 10:02:20 -07001785 SetRobustLengthParam(length, numParams);
1786
Geoff Lang2186c382016-10-14 10:54:54 -04001787 return true;
1788}
1789
1790bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1791{
1792 if (numParams)
1793 {
1794 *numParams = 0;
1795 }
1796
Corentin Wallezad3ae902018-03-09 13:40:42 -05001797 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798
1799 if (!queryObject)
1800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001805 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
1811 switch (pname)
1812 {
1813 case GL_QUERY_RESULT_EXT:
1814 case GL_QUERY_RESULT_AVAILABLE_EXT:
1815 break;
1816
1817 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return false;
1820 }
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 if (numParams)
1823 {
1824 *numParams = 1;
1825 }
1826
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return true;
1828}
1829
1830bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1831{
1832 if (!context->getExtensions().disjointTimerQuery)
1833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001834 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 return false;
1836 }
Geoff Lang2186c382016-10-14 10:54:54 -04001837 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1838}
1839
1840bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1841 GLuint id,
1842 GLenum pname,
1843 GLsizei bufSize,
1844 GLsizei *length,
1845 GLint *params)
1846{
1847 if (!context->getExtensions().disjointTimerQuery)
1848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001849 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001850 return false;
1851 }
1852
1853 if (!ValidateRobustEntryPoint(context, bufSize))
1854 {
1855 return false;
1856 }
1857
Brandon Jonesd1049182018-03-28 10:02:20 -07001858 GLsizei numParams = 0;
1859
1860 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001861 {
1862 return false;
1863 }
1864
Brandon Jonesd1049182018-03-28 10:02:20 -07001865 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001866 {
1867 return false;
1868 }
1869
Brandon Jonesd1049182018-03-28 10:02:20 -07001870 SetRobustLengthParam(length, numParams);
1871
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873}
1874
1875bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1876{
1877 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001878 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 return false;
1882 }
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1884}
1885
1886bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1887 GLuint id,
1888 GLenum pname,
1889 GLsizei bufSize,
1890 GLsizei *length,
1891 GLuint *params)
1892{
1893 if (!context->getExtensions().disjointTimerQuery &&
1894 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001897 return false;
1898 }
1899
1900 if (!ValidateRobustEntryPoint(context, bufSize))
1901 {
1902 return false;
1903 }
1904
Brandon Jonesd1049182018-03-28 10:02:20 -07001905 GLsizei numParams = 0;
1906
1907 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001908 {
1909 return false;
1910 }
1911
Brandon Jonesd1049182018-03-28 10:02:20 -07001912 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001913 {
1914 return false;
1915 }
1916
Brandon Jonesd1049182018-03-28 10:02:20 -07001917 SetRobustLengthParam(length, numParams);
1918
Geoff Lang2186c382016-10-14 10:54:54 -04001919 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920}
1921
1922bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1923{
1924 if (!context->getExtensions().disjointTimerQuery)
1925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 return false;
1928 }
Geoff Lang2186c382016-10-14 10:54:54 -04001929 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1930}
1931
1932bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1933 GLuint id,
1934 GLenum pname,
1935 GLsizei bufSize,
1936 GLsizei *length,
1937 GLint64 *params)
1938{
1939 if (!context->getExtensions().disjointTimerQuery)
1940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001941 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001942 return false;
1943 }
1944
1945 if (!ValidateRobustEntryPoint(context, bufSize))
1946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 GLsizei numParams = 0;
1951
1952 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001953 {
1954 return false;
1955 }
1956
Brandon Jonesd1049182018-03-28 10:02:20 -07001957 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001958 {
1959 return false;
1960 }
1961
Brandon Jonesd1049182018-03-28 10:02:20 -07001962 SetRobustLengthParam(length, numParams);
1963
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965}
1966
1967bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1968{
1969 if (!context->getExtensions().disjointTimerQuery)
1970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001971 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972 return false;
1973 }
Geoff Lang2186c382016-10-14 10:54:54 -04001974 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1975}
1976
1977bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1978 GLuint id,
1979 GLenum pname,
1980 GLsizei bufSize,
1981 GLsizei *length,
1982 GLuint64 *params)
1983{
1984 if (!context->getExtensions().disjointTimerQuery)
1985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001987 return false;
1988 }
1989
1990 if (!ValidateRobustEntryPoint(context, bufSize))
1991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 GLsizei numParams = 0;
1996
1997 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001998 {
1999 return false;
2000 }
2001
Brandon Jonesd1049182018-03-28 10:02:20 -07002002 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002003 {
2004 return false;
2005 }
2006
Brandon Jonesd1049182018-03-28 10:02:20 -07002007 SetRobustLengthParam(length, numParams);
2008
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010}
2011
Jamie Madill5b772312018-03-08 20:28:32 -05002012bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002013 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002014 GLint location,
2015 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002016 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002017{
Jiajia Qin5451d532017-11-16 17:16:34 +08002018 // TODO(Jiajia): Add image uniform check in future.
2019 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002020 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002021 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002022 return false;
2023 }
2024
Jiajia Qin5451d532017-11-16 17:16:34 +08002025 if (!program)
2026 {
2027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2028 return false;
2029 }
2030
2031 if (!program->isLinked())
2032 {
2033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2034 return false;
2035 }
2036
2037 if (location == -1)
2038 {
2039 // Silently ignore the uniform command
2040 return false;
2041 }
2042
2043 const auto &uniformLocations = program->getUniformLocations();
2044 size_t castedLocation = static_cast<size_t>(location);
2045 if (castedLocation >= uniformLocations.size())
2046 {
2047 context->handleError(InvalidOperation() << "Invalid uniform location");
2048 return false;
2049 }
2050
2051 const auto &uniformLocation = uniformLocations[castedLocation];
2052 if (uniformLocation.ignored)
2053 {
2054 // Silently ignore the uniform command
2055 return false;
2056 }
2057
2058 if (!uniformLocation.used())
2059 {
2060 context->handleError(InvalidOperation());
2061 return false;
2062 }
2063
2064 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2065
2066 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002067 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 {
2069 context->handleError(InvalidOperation());
2070 return false;
2071 }
2072
2073 *uniformOut = &uniform;
2074 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002075}
2076
Jamie Madill5b772312018-03-08 20:28:32 -05002077bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002078 GLenum uniformType,
2079 GLsizei count,
2080 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002081{
Jiajia Qin5451d532017-11-16 17:16:34 +08002082 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2083 // It is compatible with INT or BOOL.
2084 // Do these cheap tests first, for a little extra speed.
2085 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002086 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002087 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002088 }
2089
Jiajia Qin5451d532017-11-16 17:16:34 +08002090 if (IsSamplerType(uniformType))
2091 {
2092 // Check that the values are in range.
2093 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2094 for (GLsizei i = 0; i < count; ++i)
2095 {
2096 if (value[i] < 0 || value[i] >= max)
2097 {
2098 context->handleError(InvalidValue() << "sampler uniform value out of range");
2099 return false;
2100 }
2101 }
2102 return true;
2103 }
2104
2105 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2106 return false;
2107}
2108
Jamie Madill5b772312018-03-08 20:28:32 -05002109bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002110{
2111 // Check that the value type is compatible with uniform type.
2112 // Do the cheaper test first, for a little extra speed.
2113 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2114 {
2115 return true;
2116 }
2117
2118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2119 return false;
2120}
2121
Jamie Madill5b772312018-03-08 20:28:32 -05002122bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002123{
2124 // Check that the value type is compatible with uniform type.
2125 if (valueType == uniformType)
2126 {
2127 return true;
2128 }
2129
2130 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2131 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002132}
2133
Jamie Madill5b772312018-03-08 20:28:32 -05002134bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002135{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002136 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002137 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002143{
2144 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002145 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002146 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2147 ValidateUniform1ivValue(context, uniform->type, count, value);
2148}
2149
Jamie Madill5b772312018-03-08 20:28:32 -05002150bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002151 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002152 GLint location,
2153 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002154 GLboolean transpose)
2155{
Geoff Lang92019432017-11-20 13:09:34 -05002156 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002158 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002159 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160 }
2161
Jamie Madill62d31cb2015-09-11 13:25:51 -04002162 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002163 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002164 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2165 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002166}
2167
Jamie Madill5b772312018-03-08 20:28:32 -05002168bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002169{
2170 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002172 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002173 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002174 }
2175
Jamie Madill0af26e12015-03-05 19:54:33 -05002176 const Caps &caps = context->getCaps();
2177
Jamie Madill893ab082014-05-16 16:56:10 -04002178 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2179 {
2180 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2181
Jamie Madill0af26e12015-03-05 19:54:33 -05002182 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002184 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002185 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002186 }
2187 }
2188
2189 switch (pname)
2190 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002191 case GL_TEXTURE_BINDING_2D:
2192 case GL_TEXTURE_BINDING_CUBE_MAP:
2193 case GL_TEXTURE_BINDING_3D:
2194 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002195 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002196 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002197 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2198 if (!context->getExtensions().textureRectangle)
2199 {
2200 context->handleError(InvalidEnum()
2201 << "ANGLE_texture_rectangle extension not present");
2202 return false;
2203 }
2204 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002205 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2206 if (!context->getExtensions().eglStreamConsumerExternal &&
2207 !context->getExtensions().eglImageExternal)
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2210 "nor GL_OES_EGL_image_external "
2211 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002212 return false;
2213 }
2214 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002215
He Yunchaoced53ae2016-11-29 15:00:51 +08002216 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2217 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002218 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002219 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2220 ASSERT(readFramebuffer);
2221
Jamie Madill427064d2018-04-13 16:20:34 -04002222 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002223 {
Geoff Langb1196682014-07-23 13:47:29 -04002224 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002225 }
2226
Jamie Madille98b1b52018-03-08 09:47:23 -05002227 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002228 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002230 return false;
2231 }
2232
Jamie Madille98b1b52018-03-08 09:47:23 -05002233 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002234 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002236 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002238 }
2239 }
2240 break;
2241
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 default:
2243 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002244 }
2245
2246 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002247 if (*numParams == 0)
2248 {
2249 return false;
2250 }
2251
2252 return true;
2253}
2254
Brandon Jonesd1049182018-03-28 10:02:20 -07002255bool ValidateGetBooleanvRobustANGLE(Context *context,
2256 GLenum pname,
2257 GLsizei bufSize,
2258 GLsizei *length,
2259 GLboolean *params)
2260{
2261 GLenum nativeType;
2262 unsigned int numParams = 0;
2263
2264 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2265 {
2266 return false;
2267 }
2268
2269 SetRobustLengthParam(length, numParams);
2270
2271 return true;
2272}
2273
2274bool ValidateGetFloatvRobustANGLE(Context *context,
2275 GLenum pname,
2276 GLsizei bufSize,
2277 GLsizei *length,
2278 GLfloat *params)
2279{
2280 GLenum nativeType;
2281 unsigned int numParams = 0;
2282
2283 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2284 {
2285 return false;
2286 }
2287
2288 SetRobustLengthParam(length, numParams);
2289
2290 return true;
2291}
2292
2293bool ValidateGetIntegervRobustANGLE(Context *context,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLint *data)
2298{
2299 GLenum nativeType;
2300 unsigned int numParams = 0;
2301
2302 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2303 {
2304 return false;
2305 }
2306
2307 SetRobustLengthParam(length, numParams);
2308
2309 return true;
2310}
2311
2312bool ValidateGetInteger64vRobustANGLE(Context *context,
2313 GLenum pname,
2314 GLsizei bufSize,
2315 GLsizei *length,
2316 GLint64 *data)
2317{
2318 GLenum nativeType;
2319 unsigned int numParams = 0;
2320
2321 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2322 {
2323 return false;
2324 }
2325
2326 if (nativeType == GL_INT_64_ANGLEX)
2327 {
2328 CastStateValues(context, nativeType, pname, numParams, data);
2329 return false;
2330 }
2331
2332 SetRobustLengthParam(length, numParams);
2333 return true;
2334}
2335
Jamie Madill5b772312018-03-08 20:28:32 -05002336bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002337 GLenum pname,
2338 GLsizei bufSize,
2339 GLenum *nativeType,
2340 unsigned int *numParams)
2341{
2342 if (!ValidateRobustEntryPoint(context, bufSize))
2343 {
2344 return false;
2345 }
2346
2347 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2348 {
2349 return false;
2350 }
2351
2352 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002353 {
2354 return false;
2355 }
2356
2357 return true;
2358}
2359
Jamie Madill5b772312018-03-08 20:28:32 -05002360bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002361 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002362 GLint level,
2363 GLenum internalformat,
2364 bool isSubImage,
2365 GLint xoffset,
2366 GLint yoffset,
2367 GLint zoffset,
2368 GLint x,
2369 GLint y,
2370 GLsizei width,
2371 GLsizei height,
2372 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002373 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002374{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002375 TextureType texType = TextureTargetToType(target);
2376
Brandon Jones6cad5662017-06-14 13:25:13 -07002377 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002379 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2380 return false;
2381 }
2382
2383 if (width < 0 || height < 0)
2384 {
2385 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 }
2388
He Yunchaoced53ae2016-11-29 15:00:51 +08002389 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2390 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 }
2395
2396 if (border != 0)
2397 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002398 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002402 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 }
2407
Jamie Madill43da7c42018-08-01 11:34:49 -04002408 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002409 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002410 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002411 {
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 }
2414
Jamie Madille98b1b52018-03-08 09:47:23 -05002415 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 {
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419
Martin Radev138064f2016-07-15 12:03:41 +03002420 if (readFramebuffer->getReadBufferState() == GL_NONE)
2421 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002423 return false;
2424 }
2425
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002426 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2427 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002428 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002429 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002430 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2431 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002434 return false;
2435 }
2436
Martin Radev04e2c3b2017-07-27 16:54:35 +03002437 // ANGLE_multiview spec, Revision 1:
2438 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2439 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002440 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2441 // framebuffer is more than one.
2442 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002443 {
2444 context->handleError(InvalidFramebufferOperation()
2445 << "The active read framebuffer object has multiview attachments.");
2446 return false;
2447 }
2448
Jamie Madill43da7c42018-08-01 11:34:49 -04002449 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002450
Geoff Langaae65a42014-05-26 12:43:44 -04002451 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002452 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002454 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002455 maxDimension = caps.max2DTextureSize;
2456 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002457
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002458 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002459 maxDimension = caps.maxCubeMapTextureSize;
2460 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002461
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002462 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002463 maxDimension = caps.maxRectangleTextureSize;
2464 break;
2465
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002466 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002467 maxDimension = caps.max2DTextureSize;
2468 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002469
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002470 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002471 maxDimension = caps.max3DTextureSize;
2472 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002473
He Yunchaoced53ae2016-11-29 15:00:51 +08002474 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002475 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002476 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002477 }
2478
Jamie Madill43da7c42018-08-01 11:34:49 -04002479 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002480 if (!texture)
2481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002482 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002484 }
2485
Geoff Lang69cce582015-09-17 13:20:36 -04002486 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Jamie Madill43da7c42018-08-01 11:34:49 -04002492 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002493 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002494 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002495
Geoff Lang966c9402017-04-18 12:38:27 -04002496 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
2502 if (isSubImage)
2503 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002504 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2505 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2506 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 }
2511 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002512 else
2513 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002514 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002515 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002516 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002518 }
2519
Geoff Langeb66a6e2016-10-31 13:06:12 -04002520 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002524 }
2525
2526 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002527 if (static_cast<int>(width) > maxLevelDimension ||
2528 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002530 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002532 }
2533 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002534
Jamie Madill0c8abca2016-07-22 20:21:26 -04002535 if (textureFormatOut)
2536 {
2537 *textureFormatOut = texture->getFormat(target, level);
2538 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002539
2540 // Detect texture copying feedback loops for WebGL.
2541 if (context->getExtensions().webglCompatibility)
2542 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002543 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002544 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002546 return false;
2547 }
2548 }
2549
Jamie Madill560a8d82014-05-21 13:06:20 -04002550 return true;
2551}
2552
Jamie Madille7d80f32018-08-08 15:49:23 -04002553ErrorAndMessage ValidateDrawStates(Context *context)
2554{
2555 const Extensions &extensions = context->getExtensions();
2556 const State &state = context->getGLState();
2557
2558 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2559 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2560 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2561 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
2562 {
2563 return {GL_INVALID_OPERATION, nullptr};
2564 }
2565
2566 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2567 // Section 6.10 of the WebGL 1.0 spec.
2568 Framebuffer *framebuffer = state.getDrawFramebuffer();
2569 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2570 {
2571 ASSERT(framebuffer);
2572 const FramebufferAttachment *dsAttachment =
2573 framebuffer->getStencilOrDepthStencilAttachment();
2574 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2575 ASSERT(stencilBits <= 8);
2576
2577 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2578 if (depthStencilState.stencilTest && stencilBits > 0)
2579 {
2580 GLuint maxStencilValue = (1 << stencilBits) - 1;
2581
2582 bool differentRefs =
2583 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2584 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2585 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2586 (depthStencilState.stencilBackWritemask & maxStencilValue);
2587 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2588 (depthStencilState.stencilBackMask & maxStencilValue);
2589
2590 if (differentRefs || differentWritemasks || differentMasks)
2591 {
2592 if (!extensions.webglCompatibility)
2593 {
2594 WARN() << "This ANGLE implementation does not support separate front/back "
2595 "stencil writemasks, reference values, or stencil mask values.";
2596 }
2597 return {GL_INVALID_OPERATION, kErrorStencilReferenceMaskOrMismatch};
2598 }
2599 }
2600 }
2601
2602 if (!framebuffer->isComplete(context))
2603 {
2604 return {GL_INVALID_FRAMEBUFFER_OPERATION, nullptr};
2605 }
2606
2607 if (context->getStateCache().hasAnyEnabledClientAttrib())
2608 {
2609 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2610 {
2611 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2612 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2613 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2614 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
2615 return {GL_INVALID_OPERATION, kErrorVertexArrayNoBuffer};
2616 }
2617
2618 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2619 {
2620 // This is an application error that would normally result in a crash, but we catch it
2621 // and return an error
2622 return {GL_INVALID_OPERATION, kErrorVertexArrayNoBufferPointer};
2623 }
2624 }
2625
2626 // If we are running GLES1, there is no current program.
2627 if (context->getClientVersion() >= Version(2, 0))
2628 {
2629 Program *program = state.getProgram();
2630 if (!program)
2631 {
2632 return {GL_INVALID_OPERATION, kErrorProgramNotBound};
2633 }
2634
2635 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2636 // vertex shader stage or fragment shader stage is a undefined behaviour.
2637 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2638 // produce undefined result.
2639 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2640 !program->hasLinkedShaderStage(ShaderType::Fragment))
2641 {
2642 return {GL_INVALID_OPERATION, kErrorNoActiveGraphicsShaderStage};
2643 }
2644
2645 if (!program->validateSamplers(nullptr, context->getCaps()))
2646 {
2647 return {GL_INVALID_OPERATION, nullptr};
2648 }
2649
2650 if (extensions.multiview)
2651 {
2652 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2653 const int framebufferNumViews = framebuffer->getNumViews();
2654 if (framebufferNumViews != programNumViews)
2655 {
2656 return {GL_INVALID_OPERATION, kErrorMultiviewMismatch};
2657 }
2658
2659 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2660 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2661 framebufferNumViews > 1)
2662 {
2663 return {GL_INVALID_OPERATION, kErrorMultiviewTransformFeedback};
2664 }
2665
2666 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2667 state.isQueryActive(QueryType::TimeElapsed))
2668 {
2669 return {GL_INVALID_OPERATION, kErrorMultiviewTimerQuery};
2670 }
2671 }
2672
2673 // Uniform buffer validation
2674 for (unsigned int uniformBlockIndex = 0;
2675 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2676 {
2677 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2678 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2679 const OffsetBindingPointer<Buffer> &uniformBuffer =
2680 state.getIndexedUniformBuffer(blockBinding);
2681
2682 if (uniformBuffer.get() == nullptr)
2683 {
2684 // undefined behaviour
2685 return {GL_INVALID_OPERATION, kErrorUniformBufferUnbound};
2686 }
2687
2688 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2689 if (uniformBufferSize < uniformBlock.dataSize)
2690 {
2691 // undefined behaviour
2692 return {GL_INVALID_OPERATION, kErrorUniformBufferTooSmall};
2693 }
2694
2695 if (extensions.webglCompatibility &&
2696 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2697 {
2698 return {GL_INVALID_OPERATION, kErrorUniformBufferBoundForTransformFeedback};
2699 }
2700 }
2701
2702 // Do some additonal WebGL-specific validation
2703 if (extensions.webglCompatibility)
2704 {
2705 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2706 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2707 transformFeedbackObject->buffersBoundForOtherUse())
2708 {
2709 return {GL_INVALID_OPERATION, kErrorTransformFeedbackBufferDoubleBound};
2710 }
2711
2712 // Detect rendering feedback loops for WebGL.
2713 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2714 {
2715 return {GL_INVALID_OPERATION, kErrorFeedbackLoop};
2716 }
2717
2718 // Detect that the vertex shader input types match the attribute types
2719 if (!ValidateVertexShaderAttributeTypeMatch(context))
2720 {
2721 return {GL_INVALID_OPERATION, kErrorVertexShaderTypeMismatch};
2722 }
2723
2724 // Detect that the color buffer types match the fragment shader output types
2725 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2726 {
2727 return {GL_INVALID_OPERATION, kErrorDrawBufferTypeMismatch};
2728 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002729
2730 const VertexArray *vao = context->getGLState().getVertexArray();
2731 if (vao->hasTransformFeedbackBindingConflict(context))
2732 {
2733 return {GL_INVALID_OPERATION, kErrorVertexBufferBoundForTransformFeedback};
2734 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002735 }
2736 }
2737
2738 return {GL_NO_ERROR, nullptr};
2739}
2740
Jamie Madill493f9572018-05-24 19:52:15 -04002741bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002742{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002743 const Extensions &extensions = context->getExtensions();
2744
Jamie Madill1aeb1312014-06-20 13:21:25 -04002745 switch (mode)
2746 {
Jamie Madill493f9572018-05-24 19:52:15 -04002747 case PrimitiveMode::Points:
2748 case PrimitiveMode::Lines:
2749 case PrimitiveMode::LineLoop:
2750 case PrimitiveMode::LineStrip:
2751 case PrimitiveMode::Triangles:
2752 case PrimitiveMode::TriangleStrip:
2753 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002754 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002755
Jamie Madill493f9572018-05-24 19:52:15 -04002756 case PrimitiveMode::LinesAdjacency:
2757 case PrimitiveMode::LineStripAdjacency:
2758 case PrimitiveMode::TrianglesAdjacency:
2759 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002760 if (!extensions.geometryShader)
2761 {
2762 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2763 return false;
2764 }
2765 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002766 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002767 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002768 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002769 }
2770
Jamie Madill250d33f2014-06-06 17:09:03 -04002771 if (count < 0)
2772 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002773 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002774 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002775 }
2776
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002777 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002778
Jamie Madille7d80f32018-08-08 15:49:23 -04002779 const ErrorAndMessage &errorAndMessage = ValidateDrawStates(context);
2780 if (errorAndMessage.errorType != GL_NO_ERROR)
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002782 if (errorAndMessage.message)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002783 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002784 context->handleError(Error(errorAndMessage.errorType, errorAndMessage.message));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002785 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002786 else
Jamie Madill2da53562018-08-01 11:34:47 -04002787 {
Jamie Madille7d80f32018-08-08 15:49:23 -04002788 context->handleError(Error(errorAndMessage.errorType));
Jamie Madill2da53562018-08-01 11:34:47 -04002789 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002790 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002791 }
2792
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002793 // If we are running GLES1, there is no current program.
2794 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002795 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002796 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002797 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002798
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 // Do geometry shader specific validations
2800 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002801 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 if (!IsCompatibleDrawModeWithGeometryShader(
2803 mode, program->getGeometryShaderInputPrimitiveType()))
2804 {
2805 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2806 IncompatibleDrawModeAgainstGeometryShader);
2807 return false;
2808 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002809 }
2810 }
2811
Jamie Madill9fdaa492018-02-16 10:52:11 -05002812 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002813}
2814
Jamie Madill5b772312018-03-08 20:28:32 -05002815bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002816 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002817 GLint first,
2818 GLsizei count,
2819 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002820{
Jamie Madillfd716582014-06-06 17:09:04 -04002821 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002822 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002823 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002824 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002825 }
2826
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002827 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002828 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002829 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002830 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002831 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002832 if (!ValidateTransformFeedbackPrimitiveMode(context,
2833 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002834 {
James Darpinian30b604d2018-03-12 17:26:57 -07002835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2836 return false;
2837 }
2838
2839 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2840 {
2841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2842 return false;
2843 }
Jamie Madillfd716582014-06-06 17:09:04 -04002844 }
2845
Jiajia Qind9671222016-11-29 16:30:31 +08002846 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002847 {
2848 return false;
2849 }
2850
Corentin Wallez71168a02016-12-19 15:11:18 -08002851 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002852 // - first < 0 has been checked as an error condition.
2853 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002854 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002855 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002856 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002857 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002858 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2859 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2860 {
2861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2862 return false;
2863 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002864
Jamie Madill2da53562018-08-01 11:34:47 -04002865 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 {
2867 return false;
2868 }
Jamie Madillfd716582014-06-06 17:09:04 -04002869 }
2870
2871 return true;
2872}
2873
He Yunchaoced53ae2016-11-29 15:00:51 +08002874bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002875 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002876 GLint first,
2877 GLsizei count,
2878 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002879{
Geoff Lang63c5a592017-09-27 14:08:16 -04002880 if (!context->getExtensions().instancedArrays)
2881 {
2882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2883 return false;
2884 }
2885
Corentin Wallez170efbf2017-05-02 13:45:01 -04002886 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002887 {
2888 return false;
2889 }
2890
Corentin Wallez0dc97812017-06-22 14:38:44 -04002891 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002892}
2893
Jamie Madill493f9572018-05-24 19:52:15 -04002894bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002895{
Jamie Madill250d33f2014-06-06 17:09:03 -04002896 switch (type)
2897 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 case GL_UNSIGNED_BYTE:
2899 case GL_UNSIGNED_SHORT:
2900 break;
2901 case GL_UNSIGNED_INT:
2902 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002905 return false;
2906 }
2907 break;
2908 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002911 }
2912
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002913 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002914
Jamie Madill43da7c42018-08-01 11:34:49 -04002915 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002916 if (curTransformFeedback && curTransformFeedback->isActive() &&
2917 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002919 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2920 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2921 if (context->getExtensions().geometryShader)
2922 {
2923 if (!ValidateTransformFeedbackPrimitiveMode(
2924 context, curTransformFeedback->getPrimitiveMode(), mode))
2925 {
2926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2927 return false;
2928 }
2929 }
2930 else
2931 {
2932 // It is an invalid operation to call DrawElements, DrawRangeElements or
2933 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2934 // 86)
2935 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2936 UnsupportedDrawModeForTransformFeedback);
2937 return false;
2938 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002939 }
2940
Jiajia Qind9671222016-11-29 16:30:31 +08002941 return true;
2942}
2943
Jamie Madill5b772312018-03-08 20:28:32 -05002944bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002945 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002946 GLsizei count,
2947 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002948 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002949 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002950{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002951 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002952 return false;
2953
2954 const State &state = context->getGLState();
2955
Corentin Wallez170efbf2017-05-02 13:45:01 -04002956 if (!ValidateDrawBase(context, mode, count))
2957 {
2958 return false;
2959 }
2960
Jamie Madill43da7c42018-08-01 11:34:49 -04002961 const VertexArray *vao = state.getVertexArray();
2962 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002963
Jamie Madill43da7c42018-08-01 11:34:49 -04002964 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002965
2966 if (context->getExtensions().webglCompatibility)
2967 {
2968 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2969 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2970 {
2971 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2972 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2973 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002975 return false;
2976 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002977
2978 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2979 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2980 // error is generated.
2981 if (reinterpret_cast<intptr_t>(indices) < 0)
2982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002983 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002984 return false;
2985 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002986 }
Jamie Madillcc73f242018-08-01 11:34:48 -04002987 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
2988 {
2989 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2990 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2991 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2992 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2993 return false;
2994 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002995
2996 if (context->getExtensions().webglCompatibility ||
2997 !context->getGLState().areClientArraysEnabled())
2998 {
Brandon Jones2a018152018-06-08 15:59:26 -07002999 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003000 {
3001 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003002 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3003 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003005 return false;
3006 }
3007 }
3008
Jamie Madill9fdaa492018-02-16 10:52:11 -05003009 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003010 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003011 // This is an application error that would normally result in a crash, but we catch it and
3012 // return an error
3013 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3014 return false;
3015 }
3016
3017 if (count > 0 && elementArrayBuffer)
3018 {
3019 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3020 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3021 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3022 constexpr uint64_t kMaxTypeSize = 8;
3023 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3024 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3025 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3026
3027 uint64_t typeSize = typeBytes;
3028 uint64_t elementCount = static_cast<uint64_t>(count);
3029 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3030
3031 // Doing the multiplication here is overflow-safe
3032 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3033
3034 // The offset can be any value, check for overflows
3035 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3036 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003037 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3039 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003040 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041
3042 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3043 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003044 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3046 return false;
3047 }
3048
3049 ASSERT(isPow2(typeSize) && typeSize > 0);
3050 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3051 {
3052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003054 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003055
3056 if (context->getExtensions().webglCompatibility &&
3057 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3058 {
3059 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3060 ElementArrayBufferBoundForTransformFeedback);
3061 return false;
3062 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003063 }
3064
Jamie Madill2da53562018-08-01 11:34:47 -04003065 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003066 {
3067 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003068 const DrawCallParams &params = context->getParams<DrawCallParams>();
3069 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3070 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003071
3072 // If we use an index greater than our maximum supported index range, return an error.
3073 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3074 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003075 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003076 {
3077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3078 return false;
3079 }
3080
Jamie Madill2da53562018-08-01 11:34:47 -04003081 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003082 {
3083 return false;
3084 }
3085
3086 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003087 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003088 }
3089
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003090 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003091}
3092
Jamie Madill5b772312018-03-08 20:28:32 -05003093bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003094 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003095 GLsizei count,
3096 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003097 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003098 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003099{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003100 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003101}
3102
Geoff Lang3edfe032015-09-04 16:38:24 -04003103bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003104 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003105 GLsizei count,
3106 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003107 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003108 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003109{
Geoff Lang63c5a592017-09-27 14:08:16 -04003110 if (!context->getExtensions().instancedArrays)
3111 {
3112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3113 return false;
3114 }
3115
Corentin Wallez170efbf2017-05-02 13:45:01 -04003116 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003117 {
3118 return false;
3119 }
3120
Corentin Wallez0dc97812017-06-22 14:38:44 -04003121 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003122}
3123
He Yunchaoced53ae2016-11-29 15:00:51 +08003124bool ValidateFramebufferTextureBase(Context *context,
3125 GLenum target,
3126 GLenum attachment,
3127 GLuint texture,
3128 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003129{
Geoff Lange8afa902017-09-27 15:00:43 -04003130 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003132 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003133 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003134 }
3135
3136 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003137 {
3138 return false;
3139 }
3140
Jamie Madill55ec3b12014-07-03 10:38:57 -04003141 if (texture != 0)
3142 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003143 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003144
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003145 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003147 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003148 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003149 }
3150
3151 if (level < 0)
3152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003153 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003154 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 }
3156 }
3157
Jamie Madill43da7c42018-08-01 11:34:49 -04003158 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003159 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160
Jamie Madill84115c92015-04-23 15:00:07 -04003161 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165 }
3166
3167 return true;
3168}
3169
Geoff Langb1196682014-07-23 13:47:29 -04003170bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003171{
3172 if (program == 0)
3173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003174 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003176 }
3177
Jamie Madill43da7c42018-08-01 11:34:49 -04003178 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003179 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003180 {
3181 return false;
3182 }
3183
Jamie Madill0063c512014-08-25 15:47:53 -04003184 if (!programObject || !programObject->isLinked())
3185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003188 }
3189
Geoff Lang7dd2e102014-11-10 15:19:26 -05003190 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003192 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003194 }
3195
Jamie Madill0063c512014-08-25 15:47:53 -04003196 return true;
3197}
3198
Geoff Langf41d0ee2016-10-07 13:04:23 -04003199static bool ValidateSizedGetUniform(Context *context,
3200 GLuint program,
3201 GLint location,
3202 GLsizei bufSize,
3203 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003204{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003205 if (length)
3206 {
3207 *length = 0;
3208 }
3209
Jamie Madill78f41802014-08-25 15:47:55 -04003210 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003211 {
Jamie Madill78f41802014-08-25 15:47:55 -04003212 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003213 }
3214
Geoff Langf41d0ee2016-10-07 13:04:23 -04003215 if (bufSize < 0)
3216 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003217 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003218 return false;
3219 }
3220
Jamie Madill43da7c42018-08-01 11:34:49 -04003221 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003222 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003223
Jamie Madill78f41802014-08-25 15:47:55 -04003224 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003225 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003226 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003227 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003228 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003230 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003231 }
3232
Geoff Langf41d0ee2016-10-07 13:04:23 -04003233 if (length)
3234 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003235 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003236 }
3237
Jamie Madill0063c512014-08-25 15:47:53 -04003238 return true;
3239}
3240
He Yunchaoced53ae2016-11-29 15:00:51 +08003241bool ValidateGetnUniformfvEXT(Context *context,
3242 GLuint program,
3243 GLint location,
3244 GLsizei bufSize,
3245 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003246{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003248}
3249
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003250bool ValidateGetnUniformfvRobustANGLE(Context *context,
3251 GLuint program,
3252 GLint location,
3253 GLsizei bufSize,
3254 GLsizei *length,
3255 GLfloat *params)
3256{
3257 UNIMPLEMENTED();
3258 return false;
3259}
3260
He Yunchaoced53ae2016-11-29 15:00:51 +08003261bool ValidateGetnUniformivEXT(Context *context,
3262 GLuint program,
3263 GLint location,
3264 GLsizei bufSize,
3265 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003266{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003267 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3268}
3269
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003270bool ValidateGetnUniformivRobustANGLE(Context *context,
3271 GLuint program,
3272 GLint location,
3273 GLsizei bufSize,
3274 GLsizei *length,
3275 GLint *params)
3276{
3277 UNIMPLEMENTED();
3278 return false;
3279}
3280
3281bool ValidateGetnUniformuivRobustANGLE(Context *context,
3282 GLuint program,
3283 GLint location,
3284 GLsizei bufSize,
3285 GLsizei *length,
3286 GLuint *params)
3287{
3288 UNIMPLEMENTED();
3289 return false;
3290}
3291
Geoff Langf41d0ee2016-10-07 13:04:23 -04003292bool ValidateGetUniformfvRobustANGLE(Context *context,
3293 GLuint program,
3294 GLint location,
3295 GLsizei bufSize,
3296 GLsizei *length,
3297 GLfloat *params)
3298{
3299 if (!ValidateRobustEntryPoint(context, bufSize))
3300 {
3301 return false;
3302 }
3303
Brandon Jonesd1049182018-03-28 10:02:20 -07003304 GLsizei writeLength = 0;
3305
Geoff Langf41d0ee2016-10-07 13:04:23 -04003306 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003307 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3308 {
3309 return false;
3310 }
3311
3312 SetRobustLengthParam(length, writeLength);
3313
3314 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003315}
3316
3317bool ValidateGetUniformivRobustANGLE(Context *context,
3318 GLuint program,
3319 GLint location,
3320 GLsizei bufSize,
3321 GLsizei *length,
3322 GLint *params)
3323{
3324 if (!ValidateRobustEntryPoint(context, bufSize))
3325 {
3326 return false;
3327 }
3328
Brandon Jonesd1049182018-03-28 10:02:20 -07003329 GLsizei writeLength = 0;
3330
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003332 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3333 {
3334 return false;
3335 }
3336
3337 SetRobustLengthParam(length, writeLength);
3338
3339 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003340}
3341
3342bool ValidateGetUniformuivRobustANGLE(Context *context,
3343 GLuint program,
3344 GLint location,
3345 GLsizei bufSize,
3346 GLsizei *length,
3347 GLuint *params)
3348{
3349 if (!ValidateRobustEntryPoint(context, bufSize))
3350 {
3351 return false;
3352 }
3353
3354 if (context->getClientMajorVersion() < 3)
3355 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003357 return false;
3358 }
3359
Brandon Jonesd1049182018-03-28 10:02:20 -07003360 GLsizei writeLength = 0;
3361
Geoff Langf41d0ee2016-10-07 13:04:23 -04003362 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003363 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3364 {
3365 return false;
3366 }
3367
3368 SetRobustLengthParam(length, writeLength);
3369
3370 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003371}
3372
He Yunchaoced53ae2016-11-29 15:00:51 +08003373bool ValidateDiscardFramebufferBase(Context *context,
3374 GLenum target,
3375 GLsizei numAttachments,
3376 const GLenum *attachments,
3377 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003378{
3379 if (numAttachments < 0)
3380 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003381 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003382 return false;
3383 }
3384
3385 for (GLsizei i = 0; i < numAttachments; ++i)
3386 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003387 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003388 {
3389 if (defaultFramebuffer)
3390 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003391 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003392 return false;
3393 }
3394
3395 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidOperation() << "Requested color attachment is "
3398 "greater than the maximum supported "
3399 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003400 return false;
3401 }
3402 }
3403 else
3404 {
3405 switch (attachments[i])
3406 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003407 case GL_DEPTH_ATTACHMENT:
3408 case GL_STENCIL_ATTACHMENT:
3409 case GL_DEPTH_STENCIL_ATTACHMENT:
3410 if (defaultFramebuffer)
3411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003412 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3413 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003414 return false;
3415 }
3416 break;
3417 case GL_COLOR:
3418 case GL_DEPTH:
3419 case GL_STENCIL:
3420 if (!defaultFramebuffer)
3421 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003422 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3423 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003424 return false;
3425 }
3426 break;
3427 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003429 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003430 }
3431 }
3432 }
3433
3434 return true;
3435}
3436
Austin Kinross6ee1e782015-05-29 17:05:37 -07003437bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3438{
Jamie Madill007530e2017-12-28 14:27:04 -05003439 if (!context->getExtensions().debugMarker)
3440 {
3441 // The debug marker calls should not set error state
3442 // However, it seems reasonable to set an error state if the extension is not enabled
3443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3444 return false;
3445 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003446
Jamie Madill007530e2017-12-28 14:27:04 -05003447 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003448 if (length < 0)
3449 {
3450 return false;
3451 }
3452
3453 if (marker == nullptr)
3454 {
3455 return false;
3456 }
3457
3458 return true;
3459}
3460
3461bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3462{
Jamie Madill007530e2017-12-28 14:27:04 -05003463 if (!context->getExtensions().debugMarker)
3464 {
3465 // The debug marker calls should not set error state
3466 // However, it seems reasonable to set an error state if the extension is not enabled
3467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3468 return false;
3469 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003470
Jamie Madill007530e2017-12-28 14:27:04 -05003471 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003472 if (length < 0)
3473 {
3474 return false;
3475 }
3476
3477 if (length > 0 && marker == nullptr)
3478 {
3479 return false;
3480 }
3481
3482 return true;
3483}
3484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003485bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003486{
Geoff Langa8406172015-07-21 16:53:39 -04003487 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003490 return false;
3491 }
3492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003493 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003494 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003495 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003496 if (!context->getExtensions().eglImage)
3497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003498 context->handleError(InvalidEnum()
3499 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003500 }
3501 break;
3502
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003503 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003504 if (!context->getExtensions().eglImageExternal)
3505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003506 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3507 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003508 }
Geoff Langa8406172015-07-21 16:53:39 -04003509 break;
3510
3511 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003513 return false;
3514 }
3515
Rafael Cintron05a449a2018-06-20 18:08:04 -07003516 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003517
Jamie Madill61e16b42017-06-19 11:13:23 -04003518 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003519 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003522 return false;
3523 }
3524
Jamie Madill007530e2017-12-28 14:27:04 -05003525 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidOperation()
3528 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003529 return false;
3530 }
3531
Geoff Langca271392017-04-05 12:30:00 -04003532 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003533 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003534 if (!textureCaps.texturable)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidOperation()
3537 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003538 return false;
3539 }
3540
Geoff Langdcab33b2015-07-21 13:03:16 -04003541 return true;
3542}
3543
3544bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003545 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003546 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003547{
Geoff Langa8406172015-07-21 16:53:39 -04003548 if (!context->getExtensions().eglImage)
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003551 return false;
3552 }
3553
3554 switch (target)
3555 {
3556 case GL_RENDERBUFFER:
3557 break;
3558
3559 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
Rafael Cintron05a449a2018-06-20 18:08:04 -07003564 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003565
Jamie Madill61e16b42017-06-19 11:13:23 -04003566 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003567 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003570 return false;
3571 }
3572
Geoff Langca271392017-04-05 12:30:00 -04003573 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003574 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003575 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidOperation()
3578 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003579 return false;
3580 }
3581
Geoff Langdcab33b2015-07-21 13:03:16 -04003582 return true;
3583}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003584
3585bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3586{
Geoff Lang36167ab2015-12-07 10:27:14 -05003587 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003588 {
3589 // The default VAO should always exist
3590 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003592 return false;
3593 }
3594
3595 return true;
3596}
3597
Geoff Langc5629752015-12-07 16:29:04 -05003598bool ValidateProgramBinaryBase(Context *context,
3599 GLuint program,
3600 GLenum binaryFormat,
3601 const void *binary,
3602 GLint length)
3603{
3604 Program *programObject = GetValidProgram(context, program);
3605 if (programObject == nullptr)
3606 {
3607 return false;
3608 }
3609
3610 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3611 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3612 programBinaryFormats.end())
3613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003615 return false;
3616 }
3617
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003618 if (context->hasActiveTransformFeedback(program))
3619 {
3620 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3622 "is associated with an active transform "
3623 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003624 return false;
3625 }
3626
Geoff Langc5629752015-12-07 16:29:04 -05003627 return true;
3628}
3629
3630bool ValidateGetProgramBinaryBase(Context *context,
3631 GLuint program,
3632 GLsizei bufSize,
3633 GLsizei *length,
3634 GLenum *binaryFormat,
3635 void *binary)
3636{
3637 Program *programObject = GetValidProgram(context, program);
3638 if (programObject == nullptr)
3639 {
3640 return false;
3641 }
3642
3643 if (!programObject->isLinked())
3644 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003646 return false;
3647 }
3648
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003649 if (context->getCaps().programBinaryFormats.empty())
3650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003651 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003652 return false;
3653 }
3654
Geoff Langc5629752015-12-07 16:29:04 -05003655 return true;
3656}
Jamie Madillc29968b2016-01-20 11:17:23 -05003657
Jamie Madill5b772312018-03-08 20:28:32 -05003658bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003659{
3660 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003661 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003662 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003663 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3664 return false;
3665 }
3666 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3667 {
3668 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003669 return false;
3670 }
3671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003672 ASSERT(context->getGLState().getDrawFramebuffer());
3673 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003674 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3675
3676 // This should come first before the check for the default frame buffer
3677 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3678 // rather than INVALID_OPERATION
3679 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3680 {
3681 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3682
3683 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003684 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3685 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003686 {
3687 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003688 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3689 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3690 // 3.1 is still a bit ambiguous about the error, but future specs are
3691 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003693 return false;
3694 }
3695 else if (bufs[colorAttachment] >= maxColorAttachment)
3696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidOperation()
3698 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003699 return false;
3700 }
3701 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3702 frameBufferId != 0)
3703 {
3704 // INVALID_OPERATION-GL is bound to buffer and ith argument
3705 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidOperation()
3707 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 return false;
3709 }
3710 }
3711
3712 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3713 // and n is not 1 or bufs is bound to value other than BACK and NONE
3714 if (frameBufferId == 0)
3715 {
3716 if (n != 1)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(InvalidOperation()
3719 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003720 return false;
3721 }
3722
3723 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(
3726 InvalidOperation()
3727 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730 }
3731
3732 return true;
3733}
3734
Geoff Lang496c02d2016-10-20 11:38:11 -07003735bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003736 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003737 GLenum pname,
3738 GLsizei *length,
3739 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003740{
Geoff Lang496c02d2016-10-20 11:38:11 -07003741 if (length)
3742 {
3743 *length = 0;
3744 }
3745
3746 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3747 {
3748 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003749 InvalidOperation()
3750 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003751 return false;
3752 }
3753
Corentin Walleze4477002017-12-01 14:39:58 -05003754 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003756 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003757 return false;
3758 }
3759
Geoff Lang496c02d2016-10-20 11:38:11 -07003760 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003761 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003762 case GL_BUFFER_MAP_POINTER:
3763 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003764
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003767 return false;
3768 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003769
3770 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3771 // target bound to zero generate an INVALID_OPERATION error."
3772 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003775 context->handleError(InvalidOperation()
3776 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 return false;
3778 }
3779
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 if (length)
3781 {
3782 *length = 1;
3783 }
3784
Olli Etuaho4f667482016-03-30 15:56:35 +03003785 return true;
3786}
3787
Corentin Wallez336129f2017-10-17 15:55:40 -04003788bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003789{
Corentin Walleze4477002017-12-01 14:39:58 -05003790 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 return false;
3794 }
3795
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003796 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003797
3798 if (buffer == nullptr || !buffer->isMapped())
3799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003800 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003801 return false;
3802 }
3803
3804 return true;
3805}
3806
3807bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003808 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 GLintptr offset,
3810 GLsizeiptr length,
3811 GLbitfield access)
3812{
Corentin Walleze4477002017-12-01 14:39:58 -05003813 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003816 return false;
3817 }
3818
Brandon Jones6cad5662017-06-14 13:25:13 -07003819 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003821 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3822 return false;
3823 }
3824
3825 if (length < 0)
3826 {
3827 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 return false;
3829 }
3830
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003831 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003832
3833 if (!buffer)
3834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003835 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 return false;
3837 }
3838
3839 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003840 CheckedNumeric<size_t> checkedOffset(offset);
3841 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003842
Jamie Madille2e406c2016-06-02 13:04:10 -04003843 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003845 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
3849 // Check for invalid bits in the mask
3850 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3851 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3852 GL_MAP_UNSYNCHRONIZED_BIT;
3853
3854 if (access & ~(allAccessBits))
3855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidValue()
3857 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
3861 if (length == 0)
3862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003863 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
3867 if (buffer->isMapped())
3868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003870 return false;
3871 }
3872
3873 // Check for invalid bit combinations
3874 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(InvalidOperation()
3877 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003878 return false;
3879 }
3880
3881 GLbitfield writeOnlyBits =
3882 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3883
3884 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidOperation()
3887 << "Invalid access bits when mapping buffer for reading: 0x"
3888 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003889 return false;
3890 }
3891
3892 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3893 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003894 context->handleError(
3895 InvalidOperation()
3896 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003897 return false;
3898 }
Geoff Lang79f71042017-08-14 16:43:43 -04003899
3900 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003901}
3902
3903bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003904 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 GLintptr offset,
3906 GLsizeiptr length)
3907{
Brandon Jones6cad5662017-06-14 13:25:13 -07003908 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003910 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3911 return false;
3912 }
3913
3914 if (length < 0)
3915 {
3916 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003917 return false;
3918 }
3919
Corentin Walleze4477002017-12-01 14:39:58 -05003920 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003923 return false;
3924 }
3925
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003926 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003927
3928 if (buffer == nullptr)
3929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 return false;
3932 }
3933
3934 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003936 context->handleError(InvalidOperation()
3937 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 return false;
3939 }
3940
3941 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003942 CheckedNumeric<size_t> checkedOffset(offset);
3943 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003944
Jamie Madille2e406c2016-06-02 13:04:10 -04003945 if (!checkedSize.IsValid() ||
3946 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(InvalidValue()
3949 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
3953 return true;
3954}
3955
Olli Etuaho41997e72016-03-10 13:38:39 +02003956bool ValidateGenOrDelete(Context *context, GLint n)
3957{
3958 if (n < 0)
3959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003960 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003961 return false;
3962 }
3963 return true;
3964}
3965
Jamie Madill5b772312018-03-08 20:28:32 -05003966bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003967{
3968 if (!context->getExtensions().robustClientMemory)
3969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidOperation()
3971 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003972 return false;
3973 }
3974
3975 if (bufSize < 0)
3976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003977 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003978 return false;
3979 }
3980
3981 return true;
3982}
3983
Jamie Madill5b772312018-03-08 20:28:32 -05003984bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003985{
3986 if (bufSize < numParams)
3987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003988 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3989 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003990 return false;
3991 }
3992
3993 return true;
3994}
3995
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003996bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003997 GLenum target,
3998 GLenum attachment,
3999 GLenum pname,
4000 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004001{
Geoff Lange8afa902017-09-27 15:00:43 -04004002 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004004 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004005 return false;
4006 }
4007
4008 int clientVersion = context->getClientMajorVersion();
4009
4010 switch (pname)
4011 {
4012 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4013 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4014 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4015 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4016 break;
4017
Martin Radeve5285d22017-07-14 16:23:53 +03004018 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4019 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4020 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4021 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4022 if (clientVersion < 3 || !context->getExtensions().multiview)
4023 {
4024 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4025 return false;
4026 }
4027 break;
4028
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4030 if (clientVersion < 3 && !context->getExtensions().sRGB)
4031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004032 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004033 return false;
4034 }
4035 break;
4036
4037 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4038 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4039 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4040 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4041 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4045 if (clientVersion < 3)
4046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004047 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return false;
4049 }
4050 break;
4051
Jiawei Shaoa8802472018-05-28 11:17:47 +08004052 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4053 if (!context->getExtensions().geometryShader)
4054 {
4055 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4056 return false;
4057 }
4058 break;
4059
Geoff Langff5b2d52016-09-07 11:32:23 -04004060 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004062 return false;
4063 }
4064
4065 // Determine if the attachment is a valid enum
4066 switch (attachment)
4067 {
4068 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 case GL_DEPTH:
4070 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 if (clientVersion < 3)
4072 {
Geoff Langfa125c92017-10-24 13:01:46 -04004073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 return false;
4075 }
4076 break;
4077
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004078 case GL_DEPTH_STENCIL_ATTACHMENT:
4079 if (clientVersion < 3 && !context->isWebGL1())
4080 {
4081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4082 return false;
4083 }
4084 break;
4085
Geoff Langfa125c92017-10-24 13:01:46 -04004086 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 case GL_DEPTH_ATTACHMENT:
4088 case GL_STENCIL_ATTACHMENT:
4089 break;
4090
4091 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004092 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4093 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4095 {
Geoff Langfa125c92017-10-24 13:01:46 -04004096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 break;
4100 }
4101
4102 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4103 ASSERT(framebuffer);
4104
4105 if (framebuffer->id() == 0)
4106 {
4107 if (clientVersion < 3)
4108 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 return false;
4111 }
4112
4113 switch (attachment)
4114 {
4115 case GL_BACK:
4116 case GL_DEPTH:
4117 case GL_STENCIL:
4118 break;
4119
4120 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 }
4125 else
4126 {
4127 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4128 {
4129 // Valid attachment query
4130 }
4131 else
4132 {
4133 switch (attachment)
4134 {
4135 case GL_DEPTH_ATTACHMENT:
4136 case GL_STENCIL_ATTACHMENT:
4137 break;
4138
4139 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004140 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004142 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 return false;
4144 }
4145 break;
4146
4147 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 return false;
4150 }
4151 }
4152 }
4153
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004154 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004155 if (attachmentObject)
4156 {
4157 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4158 attachmentObject->type() == GL_TEXTURE ||
4159 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4160
4161 switch (pname)
4162 {
4163 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4164 if (attachmentObject->type() != GL_RENDERBUFFER &&
4165 attachmentObject->type() != GL_TEXTURE)
4166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 return false;
4169 }
4170 break;
4171
4172 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4173 if (attachmentObject->type() != GL_TEXTURE)
4174 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 return false;
4177 }
4178 break;
4179
4180 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4181 if (attachmentObject->type() != GL_TEXTURE)
4182 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004184 return false;
4185 }
4186 break;
4187
4188 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4189 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4190 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004191 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 return false;
4193 }
4194 break;
4195
4196 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4197 if (attachmentObject->type() != GL_TEXTURE)
4198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
4204 default:
4205 break;
4206 }
4207 }
4208 else
4209 {
4210 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4211 // is NONE, then querying any other pname will generate INVALID_ENUM.
4212
4213 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4214 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4215 // INVALID_OPERATION for all other pnames
4216
4217 switch (pname)
4218 {
4219 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4220 break;
4221
4222 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4223 if (clientVersion < 3)
4224 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004225 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004226 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004227 return false;
4228 }
4229 break;
4230
4231 default:
4232 if (clientVersion < 3)
4233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004234 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004235 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004236 return false;
4237 }
4238 else
4239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004240 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004241 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004242 return false;
4243 }
4244 }
4245 }
4246
Martin Radeve5285d22017-07-14 16:23:53 +03004247 if (numParams)
4248 {
4249 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4250 {
4251 // Only when the viewport offsets are queried we can have a varying number of output
4252 // parameters.
4253 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4254 *numParams = numViews * 2;
4255 }
4256 else
4257 {
4258 // For all other queries we can have only one output parameter.
4259 *numParams = 1;
4260 }
4261 }
4262
Geoff Langff5b2d52016-09-07 11:32:23 -04004263 return true;
4264}
4265
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004266bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004267 GLenum target,
4268 GLenum attachment,
4269 GLenum pname,
4270 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004271 GLsizei *length,
4272 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004273{
4274 if (!ValidateRobustEntryPoint(context, bufSize))
4275 {
4276 return false;
4277 }
4278
Brandon Jonesd1049182018-03-28 10:02:20 -07004279 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004280 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004281 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004282 {
4283 return false;
4284 }
4285
Brandon Jonesd1049182018-03-28 10:02:20 -07004286 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004287 {
4288 return false;
4289 }
4290
Brandon Jonesd1049182018-03-28 10:02:20 -07004291 SetRobustLengthParam(length, numParams);
4292
Geoff Langff5b2d52016-09-07 11:32:23 -04004293 return true;
4294}
4295
Jamie Madill5b772312018-03-08 20:28:32 -05004296bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004297 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 GLenum pname,
4299 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004300 GLsizei *length,
4301 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004302{
4303 if (!ValidateRobustEntryPoint(context, bufSize))
4304 {
4305 return false;
4306 }
4307
Brandon Jonesd1049182018-03-28 10:02:20 -07004308 GLsizei numParams = 0;
4309
4310 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004311 {
4312 return false;
4313 }
4314
Brandon Jonesd1049182018-03-28 10:02:20 -07004315 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004316 {
4317 return false;
4318 }
4319
Brandon Jonesd1049182018-03-28 10:02:20 -07004320 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004321 return true;
4322}
4323
Jamie Madill5b772312018-03-08 20:28:32 -05004324bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004325 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004326 GLenum pname,
4327 GLsizei bufSize,
4328 GLsizei *length,
4329 GLint64 *params)
4330{
Brandon Jonesd1049182018-03-28 10:02:20 -07004331 GLsizei numParams = 0;
4332
Geoff Langebebe1c2016-10-14 12:01:31 -04004333 if (!ValidateRobustEntryPoint(context, bufSize))
4334 {
4335 return false;
4336 }
4337
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004339 {
4340 return false;
4341 }
4342
Brandon Jonesd1049182018-03-28 10:02:20 -07004343 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 SetRobustLengthParam(length, numParams);
4349
Geoff Langff5b2d52016-09-07 11:32:23 -04004350 return true;
4351}
4352
Jamie Madill5b772312018-03-08 20:28:32 -05004353bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004354{
4355 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004356 if (numParams)
4357 {
4358 *numParams = 1;
4359 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004360
4361 Program *programObject = GetValidProgram(context, program);
4362 if (!programObject)
4363 {
4364 return false;
4365 }
4366
4367 switch (pname)
4368 {
4369 case GL_DELETE_STATUS:
4370 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004371 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004372 case GL_VALIDATE_STATUS:
4373 case GL_INFO_LOG_LENGTH:
4374 case GL_ATTACHED_SHADERS:
4375 case GL_ACTIVE_ATTRIBUTES:
4376 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4377 case GL_ACTIVE_UNIFORMS:
4378 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4379 break;
4380
4381 case GL_PROGRAM_BINARY_LENGTH:
4382 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004384 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4385 "requires GL_OES_get_program_binary or "
4386 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004387 return false;
4388 }
4389 break;
4390
4391 case GL_ACTIVE_UNIFORM_BLOCKS:
4392 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4393 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4394 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4395 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4396 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4397 if (context->getClientMajorVersion() < 3)
4398 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004400 return false;
4401 }
4402 break;
4403
Yunchao He61afff12017-03-14 15:34:03 +08004404 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004405 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004406 if (context->getClientVersion() < Version(3, 1))
4407 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004409 return false;
4410 }
4411 break;
4412
Jiawei Shao6ae51612018-02-23 14:03:25 +08004413 case GL_COMPUTE_WORK_GROUP_SIZE:
4414 if (context->getClientVersion() < Version(3, 1))
4415 {
4416 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4417 return false;
4418 }
4419
4420 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4421 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4422 // program which has not been linked successfully, or which does not contain objects to
4423 // form a compute shader.
4424 if (!programObject->isLinked())
4425 {
4426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4427 return false;
4428 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004429 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004430 {
4431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4432 return false;
4433 }
4434 break;
4435
Jiawei Shao447bfac2018-03-14 14:23:40 +08004436 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4437 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4438 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4439 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4440 if (!context->getExtensions().geometryShader)
4441 {
4442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4443 return false;
4444 }
4445
4446 // [EXT_geometry_shader] Chapter 7.12
4447 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4448 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4449 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4450 // successfully, or which does not contain objects to form a geometry shader.
4451 if (!programObject->isLinked())
4452 {
4453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4454 return false;
4455 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004456 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004457 {
4458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4459 return false;
4460 }
4461 break;
4462
Geoff Langff5b2d52016-09-07 11:32:23 -04004463 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004465 return false;
4466 }
4467
4468 return true;
4469}
4470
4471bool ValidateGetProgramivRobustANGLE(Context *context,
4472 GLuint program,
4473 GLenum pname,
4474 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004475 GLsizei *length,
4476 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004477{
4478 if (!ValidateRobustEntryPoint(context, bufSize))
4479 {
4480 return false;
4481 }
4482
Brandon Jonesd1049182018-03-28 10:02:20 -07004483 GLsizei numParams = 0;
4484
4485 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004486 {
4487 return false;
4488 }
4489
Brandon Jonesd1049182018-03-28 10:02:20 -07004490 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004491 {
4492 return false;
4493 }
4494
Brandon Jonesd1049182018-03-28 10:02:20 -07004495 SetRobustLengthParam(length, numParams);
4496
Geoff Langff5b2d52016-09-07 11:32:23 -04004497 return true;
4498}
4499
Geoff Lang740d9022016-10-07 11:20:52 -04004500bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4501 GLenum target,
4502 GLenum pname,
4503 GLsizei bufSize,
4504 GLsizei *length,
4505 GLint *params)
4506{
4507 if (!ValidateRobustEntryPoint(context, bufSize))
4508 {
4509 return false;
4510 }
4511
Brandon Jonesd1049182018-03-28 10:02:20 -07004512 GLsizei numParams = 0;
4513
4514 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004515 {
4516 return false;
4517 }
4518
Brandon Jonesd1049182018-03-28 10:02:20 -07004519 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004520 {
4521 return false;
4522 }
4523
Brandon Jonesd1049182018-03-28 10:02:20 -07004524 SetRobustLengthParam(length, numParams);
4525
Geoff Lang740d9022016-10-07 11:20:52 -04004526 return true;
4527}
4528
Geoff Langd7d0ed32016-10-07 11:33:51 -04004529bool ValidateGetShaderivRobustANGLE(Context *context,
4530 GLuint shader,
4531 GLenum pname,
4532 GLsizei bufSize,
4533 GLsizei *length,
4534 GLint *params)
4535{
4536 if (!ValidateRobustEntryPoint(context, bufSize))
4537 {
4538 return false;
4539 }
4540
Brandon Jonesd1049182018-03-28 10:02:20 -07004541 GLsizei numParams = 0;
4542
4543 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004549 {
4550 return false;
4551 }
4552
Brandon Jonesd1049182018-03-28 10:02:20 -07004553 SetRobustLengthParam(length, numParams);
4554
Geoff Langd7d0ed32016-10-07 11:33:51 -04004555 return true;
4556}
4557
Geoff Langc1984ed2016-10-07 12:41:00 -04004558bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004559 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004560 GLenum pname,
4561 GLsizei bufSize,
4562 GLsizei *length,
4563 GLfloat *params)
4564{
4565 if (!ValidateRobustEntryPoint(context, bufSize))
4566 {
4567 return false;
4568 }
4569
Brandon Jonesd1049182018-03-28 10:02:20 -07004570 GLsizei numParams = 0;
4571
4572 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004578 {
4579 return false;
4580 }
4581
Brandon Jonesd1049182018-03-28 10:02:20 -07004582 SetRobustLengthParam(length, numParams);
4583
Geoff Langc1984ed2016-10-07 12:41:00 -04004584 return true;
4585}
4586
Geoff Langc1984ed2016-10-07 12:41:00 -04004587bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004588 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004589 GLenum pname,
4590 GLsizei bufSize,
4591 GLsizei *length,
4592 GLint *params)
4593{
Brandon Jonesd1049182018-03-28 10:02:20 -07004594
Geoff Langc1984ed2016-10-07 12:41:00 -04004595 if (!ValidateRobustEntryPoint(context, bufSize))
4596 {
4597 return false;
4598 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004599 GLsizei numParams = 0;
4600 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004601 {
4602 return false;
4603 }
4604
Brandon Jonesd1049182018-03-28 10:02:20 -07004605 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004606 {
4607 return false;
4608 }
4609
Brandon Jonesd1049182018-03-28 10:02:20 -07004610 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004611 return true;
4612}
4613
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004614bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4615 TextureType target,
4616 GLenum pname,
4617 GLsizei bufSize,
4618 GLsizei *length,
4619 GLint *params)
4620{
4621 UNIMPLEMENTED();
4622 return false;
4623}
4624
4625bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4626 TextureType target,
4627 GLenum pname,
4628 GLsizei bufSize,
4629 GLsizei *length,
4630 GLuint *params)
4631{
4632 UNIMPLEMENTED();
4633 return false;
4634}
4635
Geoff Langc1984ed2016-10-07 12:41:00 -04004636bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004637 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004638 GLenum pname,
4639 GLsizei bufSize,
4640 const GLfloat *params)
4641{
4642 if (!ValidateRobustEntryPoint(context, bufSize))
4643 {
4644 return false;
4645 }
4646
4647 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4648}
4649
Geoff Langc1984ed2016-10-07 12:41:00 -04004650bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004651 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004652 GLenum pname,
4653 GLsizei bufSize,
4654 const GLint *params)
4655{
4656 if (!ValidateRobustEntryPoint(context, bufSize))
4657 {
4658 return false;
4659 }
4660
4661 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4662}
4663
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004664bool ValidateTexParameterIivRobustANGLE(Context *context,
4665 TextureType target,
4666 GLenum pname,
4667 GLsizei bufSize,
4668 const GLint *params)
4669{
4670 UNIMPLEMENTED();
4671 return false;
4672}
4673
4674bool ValidateTexParameterIuivRobustANGLE(Context *context,
4675 TextureType target,
4676 GLenum pname,
4677 GLsizei bufSize,
4678 const GLuint *params)
4679{
4680 UNIMPLEMENTED();
4681 return false;
4682}
4683
Geoff Langc1984ed2016-10-07 12:41:00 -04004684bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4685 GLuint sampler,
4686 GLenum pname,
4687 GLuint bufSize,
4688 GLsizei *length,
4689 GLfloat *params)
4690{
4691 if (!ValidateRobustEntryPoint(context, bufSize))
4692 {
4693 return false;
4694 }
4695
Brandon Jonesd1049182018-03-28 10:02:20 -07004696 GLsizei numParams = 0;
4697
4698 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004699 {
4700 return false;
4701 }
4702
Brandon Jonesd1049182018-03-28 10:02:20 -07004703 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004704 {
4705 return false;
4706 }
4707
Brandon Jonesd1049182018-03-28 10:02:20 -07004708 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004709 return true;
4710}
4711
Geoff Langc1984ed2016-10-07 12:41:00 -04004712bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4713 GLuint sampler,
4714 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004715 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 GLsizei *length,
4717 GLint *params)
4718{
4719 if (!ValidateRobustEntryPoint(context, bufSize))
4720 {
4721 return false;
4722 }
4723
Brandon Jonesd1049182018-03-28 10:02:20 -07004724 GLsizei numParams = 0;
4725
4726 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004727 {
4728 return false;
4729 }
4730
Brandon Jonesd1049182018-03-28 10:02:20 -07004731 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004732 {
4733 return false;
4734 }
4735
Brandon Jonesd1049182018-03-28 10:02:20 -07004736 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004737 return true;
4738}
4739
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004740bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4741 GLuint sampler,
4742 GLenum pname,
4743 GLsizei bufSize,
4744 GLsizei *length,
4745 GLint *params)
4746{
4747 UNIMPLEMENTED();
4748 return false;
4749}
4750
4751bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4752 GLuint sampler,
4753 GLenum pname,
4754 GLsizei bufSize,
4755 GLsizei *length,
4756 GLuint *params)
4757{
4758 UNIMPLEMENTED();
4759 return false;
4760}
4761
Geoff Langc1984ed2016-10-07 12:41:00 -04004762bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4763 GLuint sampler,
4764 GLenum pname,
4765 GLsizei bufSize,
4766 const GLfloat *params)
4767{
4768 if (!ValidateRobustEntryPoint(context, bufSize))
4769 {
4770 return false;
4771 }
4772
4773 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4774}
4775
Geoff Langc1984ed2016-10-07 12:41:00 -04004776bool ValidateSamplerParameterivRobustANGLE(Context *context,
4777 GLuint sampler,
4778 GLenum pname,
4779 GLsizei bufSize,
4780 const GLint *params)
4781{
4782 if (!ValidateRobustEntryPoint(context, bufSize))
4783 {
4784 return false;
4785 }
4786
4787 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4788}
4789
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004790bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4791 GLuint sampler,
4792 GLenum pname,
4793 GLsizei bufSize,
4794 const GLint *param)
4795{
4796 UNIMPLEMENTED();
4797 return false;
4798}
4799
4800bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4801 GLuint sampler,
4802 GLenum pname,
4803 GLsizei bufSize,
4804 const GLuint *param)
4805{
4806 UNIMPLEMENTED();
4807 return false;
4808}
4809
Geoff Lang0b031062016-10-13 14:30:04 -04004810bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4811 GLuint index,
4812 GLenum pname,
4813 GLsizei bufSize,
4814 GLsizei *length,
4815 GLfloat *params)
4816{
4817 if (!ValidateRobustEntryPoint(context, bufSize))
4818 {
4819 return false;
4820 }
4821
Brandon Jonesd1049182018-03-28 10:02:20 -07004822 GLsizei writeLength = 0;
4823
4824 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004825 {
4826 return false;
4827 }
4828
Brandon Jonesd1049182018-03-28 10:02:20 -07004829 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004830 {
4831 return false;
4832 }
4833
Brandon Jonesd1049182018-03-28 10:02:20 -07004834 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004835 return true;
4836}
4837
Geoff Lang0b031062016-10-13 14:30:04 -04004838bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4839 GLuint index,
4840 GLenum pname,
4841 GLsizei bufSize,
4842 GLsizei *length,
4843 GLint *params)
4844{
4845 if (!ValidateRobustEntryPoint(context, bufSize))
4846 {
4847 return false;
4848 }
4849
Brandon Jonesd1049182018-03-28 10:02:20 -07004850 GLsizei writeLength = 0;
4851
4852 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004853 {
4854 return false;
4855 }
4856
Brandon Jonesd1049182018-03-28 10:02:20 -07004857 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004858 {
4859 return false;
4860 }
4861
Brandon Jonesd1049182018-03-28 10:02:20 -07004862 SetRobustLengthParam(length, writeLength);
4863
Geoff Lang0b031062016-10-13 14:30:04 -04004864 return true;
4865}
4866
Geoff Lang0b031062016-10-13 14:30:04 -04004867bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4868 GLuint index,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 GLsizei *length,
4872 void **pointer)
4873{
4874 if (!ValidateRobustEntryPoint(context, bufSize))
4875 {
4876 return false;
4877 }
4878
Brandon Jonesd1049182018-03-28 10:02:20 -07004879 GLsizei writeLength = 0;
4880
4881 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004887 {
4888 return false;
4889 }
4890
Brandon Jonesd1049182018-03-28 10:02:20 -07004891 SetRobustLengthParam(length, writeLength);
4892
Geoff Lang0b031062016-10-13 14:30:04 -04004893 return true;
4894}
4895
Geoff Lang0b031062016-10-13 14:30:04 -04004896bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4897 GLuint index,
4898 GLenum pname,
4899 GLsizei bufSize,
4900 GLsizei *length,
4901 GLint *params)
4902{
4903 if (!ValidateRobustEntryPoint(context, bufSize))
4904 {
4905 return false;
4906 }
4907
Brandon Jonesd1049182018-03-28 10:02:20 -07004908 GLsizei writeLength = 0;
4909
4910 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004916 {
4917 return false;
4918 }
4919
Brandon Jonesd1049182018-03-28 10:02:20 -07004920 SetRobustLengthParam(length, writeLength);
4921
Geoff Lang0b031062016-10-13 14:30:04 -04004922 return true;
4923}
4924
Geoff Lang0b031062016-10-13 14:30:04 -04004925bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4926 GLuint index,
4927 GLenum pname,
4928 GLsizei bufSize,
4929 GLsizei *length,
4930 GLuint *params)
4931{
4932 if (!ValidateRobustEntryPoint(context, bufSize))
4933 {
4934 return false;
4935 }
4936
Brandon Jonesd1049182018-03-28 10:02:20 -07004937 GLsizei writeLength = 0;
4938
4939 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004945 {
4946 return false;
4947 }
4948
Brandon Jonesd1049182018-03-28 10:02:20 -07004949 SetRobustLengthParam(length, writeLength);
4950
Geoff Lang0b031062016-10-13 14:30:04 -04004951 return true;
4952}
4953
Geoff Lang6899b872016-10-14 11:30:13 -04004954bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4955 GLuint program,
4956 GLuint uniformBlockIndex,
4957 GLenum pname,
4958 GLsizei bufSize,
4959 GLsizei *length,
4960 GLint *params)
4961{
4962 if (!ValidateRobustEntryPoint(context, bufSize))
4963 {
4964 return false;
4965 }
4966
Brandon Jonesd1049182018-03-28 10:02:20 -07004967 GLsizei writeLength = 0;
4968
4969 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4970 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004971 {
4972 return false;
4973 }
4974
Brandon Jonesd1049182018-03-28 10:02:20 -07004975 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004976 {
4977 return false;
4978 }
4979
Brandon Jonesd1049182018-03-28 10:02:20 -07004980 SetRobustLengthParam(length, writeLength);
4981
Geoff Lang6899b872016-10-14 11:30:13 -04004982 return true;
4983}
4984
Brandon Jones416aaf92018-04-10 08:10:16 -07004985bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004986 GLenum target,
4987 GLenum internalformat,
4988 GLenum pname,
4989 GLsizei bufSize,
4990 GLsizei *length,
4991 GLint *params)
4992{
4993 if (!ValidateRobustEntryPoint(context, bufSize))
4994 {
4995 return false;
4996 }
4997
Brandon Jonesd1049182018-03-28 10:02:20 -07004998 GLsizei numParams = 0;
4999
5000 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5001 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005002 {
5003 return false;
5004 }
5005
Brandon Jonesd1049182018-03-28 10:02:20 -07005006 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 SetRobustLengthParam(length, numParams);
5012
Geoff Lang0a9661f2016-10-20 10:59:20 -07005013 return true;
5014}
5015
Jamie Madill5b772312018-03-08 20:28:32 -05005016bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005017 GLuint attribIndex,
5018 GLint size,
5019 GLenum type,
5020 GLboolean pureInteger)
5021{
5022 const Caps &caps = context->getCaps();
5023 if (attribIndex >= caps.maxVertexAttributes)
5024 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005025 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005026 return false;
5027 }
5028
5029 if (size < 1 || size > 4)
5030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005031 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005032 return false;
Shao80957d92017-02-20 21:25:59 +08005033 }
5034
5035 switch (type)
5036 {
5037 case GL_BYTE:
5038 case GL_UNSIGNED_BYTE:
5039 case GL_SHORT:
5040 case GL_UNSIGNED_SHORT:
5041 break;
5042
5043 case GL_INT:
5044 case GL_UNSIGNED_INT:
5045 if (context->getClientMajorVersion() < 3)
5046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005047 context->handleError(InvalidEnum()
5048 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005049 return false;
5050 }
5051 break;
5052
5053 case GL_FIXED:
5054 case GL_FLOAT:
5055 if (pureInteger)
5056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005057 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005058 return false;
5059 }
5060 break;
5061
5062 case GL_HALF_FLOAT:
5063 if (context->getClientMajorVersion() < 3)
5064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005065 context->handleError(InvalidEnum()
5066 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005067 return false;
5068 }
5069 if (pureInteger)
5070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005072 return false;
5073 }
5074 break;
5075
5076 case GL_INT_2_10_10_10_REV:
5077 case GL_UNSIGNED_INT_2_10_10_10_REV:
5078 if (context->getClientMajorVersion() < 3)
5079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005080 context->handleError(InvalidEnum()
5081 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005082 return false;
5083 }
5084 if (pureInteger)
5085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005087 return false;
5088 }
5089 if (size != 4)
5090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5092 "UNSIGNED_INT_2_10_10_10_REV and "
5093 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005094 return false;
5095 }
5096 break;
5097
5098 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005100 return false;
5101 }
5102
5103 return true;
5104}
5105
Geoff Lang76e65652017-03-27 14:58:02 -04005106// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5107// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5108// specified clear value and the type of a buffer that is being cleared generates an
5109// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005110bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005111 GLint drawbuffer,
5112 const GLenum *validComponentTypes,
5113 size_t validComponentTypeCount)
5114{
5115 const FramebufferAttachment *attachment =
5116 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5117 if (attachment)
5118 {
5119 GLenum componentType = attachment->getFormat().info->componentType;
5120 const GLenum *end = validComponentTypes + validComponentTypeCount;
5121 if (std::find(validComponentTypes, end, componentType) == end)
5122 {
5123 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005124 InvalidOperation()
5125 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005126 return false;
5127 }
5128 }
5129
5130 return true;
5131}
5132
Jamie Madill5b772312018-03-08 20:28:32 -05005133bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005134{
5135 if (!ValidateRobustEntryPoint(context, dataSize))
5136 {
5137 return false;
5138 }
5139
Jamie Madill43da7c42018-08-01 11:34:49 -04005140 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005141 if (pixelUnpackBuffer == nullptr)
5142 {
5143 if (dataSize < imageSize)
5144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005145 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005146 }
5147 }
5148 return true;
5149}
5150
Jamie Madill5b772312018-03-08 20:28:32 -05005151bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005152 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005153 GLenum pname,
5154 bool pointerVersion,
5155 GLsizei *numParams)
5156{
5157 if (numParams)
5158 {
5159 *numParams = 0;
5160 }
5161
Corentin Walleze4477002017-12-01 14:39:58 -05005162 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 return false;
5166 }
5167
5168 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5169 if (!buffer)
5170 {
5171 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 return false;
5174 }
5175
5176 const Extensions &extensions = context->getExtensions();
5177
5178 switch (pname)
5179 {
5180 case GL_BUFFER_USAGE:
5181 case GL_BUFFER_SIZE:
5182 break;
5183
5184 case GL_BUFFER_ACCESS_OES:
5185 if (!extensions.mapBuffer)
5186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005187 context->handleError(InvalidEnum()
5188 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191 break;
5192
5193 case GL_BUFFER_MAPPED:
5194 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5195 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5196 !extensions.mapBufferRange)
5197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005198 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5199 "GL_OES_mapbuffer or "
5200 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 return false;
5202 }
5203 break;
5204
5205 case GL_BUFFER_MAP_POINTER:
5206 if (!pointerVersion)
5207 {
5208 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005209 InvalidEnum()
5210 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 return false;
5212 }
5213 break;
5214
5215 case GL_BUFFER_ACCESS_FLAGS:
5216 case GL_BUFFER_MAP_OFFSET:
5217 case GL_BUFFER_MAP_LENGTH:
5218 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005220 context->handleError(InvalidEnum()
5221 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 break;
5225
5226 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005227 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 return false;
5229 }
5230
5231 // All buffer parameter queries return one value.
5232 if (numParams)
5233 {
5234 *numParams = 1;
5235 }
5236
5237 return true;
5238}
5239
5240bool ValidateGetRenderbufferParameterivBase(Context *context,
5241 GLenum target,
5242 GLenum pname,
5243 GLsizei *length)
5244{
5245 if (length)
5246 {
5247 *length = 0;
5248 }
5249
5250 if (target != GL_RENDERBUFFER)
5251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255
5256 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5257 if (renderbuffer == nullptr)
5258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262
5263 switch (pname)
5264 {
5265 case GL_RENDERBUFFER_WIDTH:
5266 case GL_RENDERBUFFER_HEIGHT:
5267 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5268 case GL_RENDERBUFFER_RED_SIZE:
5269 case GL_RENDERBUFFER_GREEN_SIZE:
5270 case GL_RENDERBUFFER_BLUE_SIZE:
5271 case GL_RENDERBUFFER_ALPHA_SIZE:
5272 case GL_RENDERBUFFER_DEPTH_SIZE:
5273 case GL_RENDERBUFFER_STENCIL_SIZE:
5274 break;
5275
5276 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5277 if (!context->getExtensions().framebufferMultisample)
5278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005279 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282 break;
5283
5284 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288
5289 if (length)
5290 {
5291 *length = 1;
5292 }
5293 return true;
5294}
5295
5296bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5297{
5298 if (length)
5299 {
5300 *length = 0;
5301 }
5302
5303 if (GetValidShader(context, shader) == nullptr)
5304 {
5305 return false;
5306 }
5307
5308 switch (pname)
5309 {
5310 case GL_SHADER_TYPE:
5311 case GL_DELETE_STATUS:
5312 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005313 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005314 case GL_INFO_LOG_LENGTH:
5315 case GL_SHADER_SOURCE_LENGTH:
5316 break;
5317
5318 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5319 if (!context->getExtensions().translatedShaderSource)
5320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 return false;
5323 }
5324 break;
5325
5326 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005327 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
5330
5331 if (length)
5332 {
5333 *length = 1;
5334 }
5335 return true;
5336}
5337
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005338bool ValidateGetTexParameterBase(Context *context,
5339 TextureType target,
5340 GLenum pname,
5341 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005342{
5343 if (length)
5344 {
5345 *length = 0;
5346 }
5347
5348 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5349 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353
5354 if (context->getTargetTexture(target) == nullptr)
5355 {
5356 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005361 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5362 {
5363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5364 return false;
5365 }
5366
Jamie Madillbe849e42017-05-02 15:49:00 -04005367 switch (pname)
5368 {
5369 case GL_TEXTURE_MAG_FILTER:
5370 case GL_TEXTURE_MIN_FILTER:
5371 case GL_TEXTURE_WRAP_S:
5372 case GL_TEXTURE_WRAP_T:
5373 break;
5374
5375 case GL_TEXTURE_USAGE_ANGLE:
5376 if (!context->getExtensions().textureUsage)
5377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381 break;
5382
5383 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005384 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005385 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 case GL_TEXTURE_IMMUTABLE_FORMAT:
5391 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 return false;
5395 }
5396 break;
5397
5398 case GL_TEXTURE_WRAP_R:
5399 case GL_TEXTURE_IMMUTABLE_LEVELS:
5400 case GL_TEXTURE_SWIZZLE_R:
5401 case GL_TEXTURE_SWIZZLE_G:
5402 case GL_TEXTURE_SWIZZLE_B:
5403 case GL_TEXTURE_SWIZZLE_A:
5404 case GL_TEXTURE_BASE_LEVEL:
5405 case GL_TEXTURE_MAX_LEVEL:
5406 case GL_TEXTURE_MIN_LOD:
5407 case GL_TEXTURE_MAX_LOD:
5408 case GL_TEXTURE_COMPARE_MODE:
5409 case GL_TEXTURE_COMPARE_FUNC:
5410 if (context->getClientMajorVersion() < 3)
5411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005412 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 return false;
5414 }
5415 break;
5416
5417 case GL_TEXTURE_SRGB_DECODE_EXT:
5418 if (!context->getExtensions().textureSRGBDecode)
5419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005420 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005421 return false;
5422 }
5423 break;
5424
Yunchao Hebacaa712018-01-30 14:01:39 +08005425 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5426 if (context->getClientVersion() < Version(3, 1))
5427 {
5428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5429 return false;
5430 }
5431 break;
5432
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005433 case GL_GENERATE_MIPMAP:
5434 case GL_TEXTURE_CROP_RECT_OES:
5435 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5436 // after GL_OES_draw_texture functionality implemented
5437 if (context->getClientMajorVersion() > 1)
5438 {
5439 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5440 return false;
5441 }
5442 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005444 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 return false;
5446 }
5447
5448 if (length)
5449 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005450 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 }
5452 return true;
5453}
5454
5455bool ValidateGetVertexAttribBase(Context *context,
5456 GLuint index,
5457 GLenum pname,
5458 GLsizei *length,
5459 bool pointer,
5460 bool pureIntegerEntryPoint)
5461{
5462 if (length)
5463 {
5464 *length = 0;
5465 }
5466
5467 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005469 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472
5473 if (index >= context->getCaps().maxVertexAttributes)
5474 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005475 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
5478
5479 if (pointer)
5480 {
5481 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 }
5487 else
5488 {
5489 switch (pname)
5490 {
5491 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5492 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5493 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5494 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5495 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5496 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5497 case GL_CURRENT_VERTEX_ATTRIB:
5498 break;
5499
5500 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5501 static_assert(
5502 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5503 "ANGLE extension enums not equal to GL enums.");
5504 if (context->getClientMajorVersion() < 3 &&
5505 !context->getExtensions().instancedArrays)
5506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005507 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5508 "requires OpenGL ES 3.0 or "
5509 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 return false;
5511 }
5512 break;
5513
5514 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5515 if (context->getClientMajorVersion() < 3)
5516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005517 context->handleError(
5518 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 return false;
5520 }
5521 break;
5522
5523 case GL_VERTEX_ATTRIB_BINDING:
5524 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5525 if (context->getClientVersion() < ES_3_1)
5526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005527 context->handleError(InvalidEnum()
5528 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531 break;
5532
5533 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005534 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 return false;
5536 }
5537 }
5538
5539 if (length)
5540 {
5541 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5542 {
5543 *length = 4;
5544 }
5545 else
5546 {
5547 *length = 1;
5548 }
5549 }
5550
5551 return true;
5552}
5553
Jamie Madill4928b7c2017-06-20 12:57:39 -04005554bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 GLint x,
5556 GLint y,
5557 GLsizei width,
5558 GLsizei height,
5559 GLenum format,
5560 GLenum type,
5561 GLsizei bufSize,
5562 GLsizei *length,
5563 GLsizei *columns,
5564 GLsizei *rows,
5565 void *pixels)
5566{
5567 if (length != nullptr)
5568 {
5569 *length = 0;
5570 }
5571 if (rows != nullptr)
5572 {
5573 *rows = 0;
5574 }
5575 if (columns != nullptr)
5576 {
5577 *columns = 0;
5578 }
5579
5580 if (width < 0 || height < 0)
5581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005582 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005586 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005587
Jamie Madill427064d2018-04-13 16:20:34 -04005588 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592
Jamie Madille98b1b52018-03-08 09:47:23 -05005593 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005594 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005595 return false;
5596 }
5597
Jamie Madill690c8eb2018-03-12 15:20:03 -04005598 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 ASSERT(framebuffer);
5600
5601 if (framebuffer->getReadBufferState() == GL_NONE)
5602 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005603 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 return false;
5605 }
5606
5607 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5608 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5609 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5610 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5611 // situation is an application error that would lead to a crash in ANGLE.
5612 if (readBuffer == nullptr)
5613 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005615 return false;
5616 }
5617
Martin Radev28031682017-07-28 14:47:56 +03005618 // ANGLE_multiview, Revision 1:
5619 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005620 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5621 // in the current read framebuffer is more than one.
5622 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005623 {
5624 context->handleError(InvalidFramebufferOperation()
5625 << "Attempting to read from a multi-view framebuffer.");
5626 return false;
5627 }
5628
Geoff Lang280ba992017-04-18 16:30:58 -04005629 if (context->getExtensions().webglCompatibility)
5630 {
5631 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5632 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5633 // and type before validating the combination of format and type. However, the
5634 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5635 // verifies that GL_INVALID_OPERATION is generated.
5636 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5637 // dEQP/WebGL.
5638 if (!ValidReadPixelsFormatEnum(context, format))
5639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005640 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005641 return false;
5642 }
5643
5644 if (!ValidReadPixelsTypeEnum(context, type))
5645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005647 return false;
5648 }
5649 }
5650
Jamie Madill690c8eb2018-03-12 15:20:03 -04005651 GLenum currentFormat = GL_NONE;
5652 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5653
5654 GLenum currentType = GL_NONE;
5655 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5656
Jamie Madillbe849e42017-05-02 15:49:00 -04005657 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5658
5659 bool validFormatTypeCombination =
5660 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5661
5662 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5663 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005665 return false;
5666 }
5667
5668 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005669 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5671 {
5672 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005673 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005676 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5677 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5678 {
5679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5680 return false;
5681 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005682
5683 // .. the data would be packed to the buffer object such that the memory writes required
5684 // would exceed the data store size.
5685 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005686 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 const auto &pack = context->getGLState().getPackState();
5688
Jamie Madillca2ff382018-07-11 09:01:17 -04005689 GLuint endByte = 0;
5690 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005691 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005693 return false;
5694 }
5695
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 if (bufSize >= 0)
5697 {
5698 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005701 return false;
5702 }
5703 }
5704
5705 if (pixelPackBuffer != nullptr)
5706 {
5707 CheckedNumeric<size_t> checkedEndByte(endByte);
5708 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5709 checkedEndByte += checkedOffset;
5710
5711 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5712 {
5713 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005715 return false;
5716 }
5717 }
5718
5719 if (pixelPackBuffer == nullptr && length != nullptr)
5720 {
5721 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5722 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 return false;
5725 }
5726
5727 *length = static_cast<GLsizei>(endByte);
5728 }
5729
Geoff Langa953b522018-02-21 16:56:23 -05005730 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 angle::CheckedNumeric<int> clippedExtent(length);
5732 if (start < 0)
5733 {
5734 // "subtract" the area that is less than 0
5735 clippedExtent += start;
5736 }
5737
Geoff Langa953b522018-02-21 16:56:23 -05005738 angle::CheckedNumeric<int> readExtent = start;
5739 readExtent += length;
5740 if (!readExtent.IsValid())
5741 {
5742 return false;
5743 }
5744
5745 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 {
5747 // Subtract the region to the right of the read buffer
5748 clippedExtent -= (readExtent - bufferSize);
5749 }
5750
5751 if (!clippedExtent.IsValid())
5752 {
Geoff Langa953b522018-02-21 16:56:23 -05005753 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 }
5755
Geoff Langa953b522018-02-21 16:56:23 -05005756 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5757 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 };
5759
Geoff Langa953b522018-02-21 16:56:23 -05005760 GLsizei writtenColumns = 0;
5761 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5762 {
5763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5764 return false;
5765 }
5766
5767 GLsizei writtenRows = 0;
5768 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5769 {
5770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5771 return false;
5772 }
5773
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 if (columns != nullptr)
5775 {
Geoff Langa953b522018-02-21 16:56:23 -05005776 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 }
5778
5779 if (rows != nullptr)
5780 {
Geoff Langa953b522018-02-21 16:56:23 -05005781 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 }
5783
5784 return true;
5785}
5786
5787template <typename ParamType>
5788bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005789 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 GLenum pname,
5791 GLsizei bufSize,
5792 const ParamType *params)
5793{
5794 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5795 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 return false;
5798 }
5799
5800 if (context->getTargetTexture(target) == nullptr)
5801 {
5802 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005807 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 if (bufSize >= 0 && bufSize < minBufSize)
5809 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 return false;
5812 }
5813
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005814 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5815 {
5816 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5817 return false;
5818 }
5819
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 switch (pname)
5821 {
5822 case GL_TEXTURE_WRAP_R:
5823 case GL_TEXTURE_SWIZZLE_R:
5824 case GL_TEXTURE_SWIZZLE_G:
5825 case GL_TEXTURE_SWIZZLE_B:
5826 case GL_TEXTURE_SWIZZLE_A:
5827 case GL_TEXTURE_BASE_LEVEL:
5828 case GL_TEXTURE_MAX_LEVEL:
5829 case GL_TEXTURE_COMPARE_MODE:
5830 case GL_TEXTURE_COMPARE_FUNC:
5831 case GL_TEXTURE_MIN_LOD:
5832 case GL_TEXTURE_MAX_LOD:
5833 if (context->getClientMajorVersion() < 3)
5834 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005836 return false;
5837 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005838 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005840 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5841 "available without "
5842 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 return false;
5844 }
5845 break;
5846
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005847 case GL_GENERATE_MIPMAP:
5848 case GL_TEXTURE_CROP_RECT_OES:
5849 if (context->getClientMajorVersion() > 1)
5850 {
5851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5852 return false;
5853 }
5854 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 default:
5856 break;
5857 }
5858
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005859 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005860 {
5861 switch (pname)
5862 {
5863 case GL_TEXTURE_MIN_FILTER:
5864 case GL_TEXTURE_MAG_FILTER:
5865 case GL_TEXTURE_WRAP_S:
5866 case GL_TEXTURE_WRAP_T:
5867 case GL_TEXTURE_WRAP_R:
5868 case GL_TEXTURE_MIN_LOD:
5869 case GL_TEXTURE_MAX_LOD:
5870 case GL_TEXTURE_COMPARE_MODE:
5871 case GL_TEXTURE_COMPARE_FUNC:
5872 context->handleError(InvalidEnum()
5873 << "Invalid parameter for 2D multisampled textures.");
5874 return false;
5875 }
5876 }
5877
Jamie Madillbe849e42017-05-02 15:49:00 -04005878 switch (pname)
5879 {
5880 case GL_TEXTURE_WRAP_S:
5881 case GL_TEXTURE_WRAP_T:
5882 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005883 {
5884 bool restrictedWrapModes =
5885 target == TextureType::External || target == TextureType::Rectangle;
5886 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005887 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005888 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005889 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005890 }
5891 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005892
5893 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005894 {
5895 bool restrictedMinFilter =
5896 target == TextureType::External || target == TextureType::Rectangle;
5897 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005898 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005899 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005900 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005901 }
5902 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005903
5904 case GL_TEXTURE_MAG_FILTER:
5905 if (!ValidateTextureMagFilterValue(context, params))
5906 {
5907 return false;
5908 }
5909 break;
5910
5911 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005912 if (!context->getExtensions().textureUsage)
5913 {
5914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5915 return false;
5916 }
5917
Jamie Madillbe849e42017-05-02 15:49:00 -04005918 switch (ConvertToGLenum(params[0]))
5919 {
5920 case GL_NONE:
5921 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5922 break;
5923
5924 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005926 return false;
5927 }
5928 break;
5929
5930 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005931 {
5932 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5933 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
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 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5938 }
5939 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005940
5941 case GL_TEXTURE_MIN_LOD:
5942 case GL_TEXTURE_MAX_LOD:
5943 // any value is permissible
5944 break;
5945
5946 case GL_TEXTURE_COMPARE_MODE:
5947 if (!ValidateTextureCompareModeValue(context, params))
5948 {
5949 return false;
5950 }
5951 break;
5952
5953 case GL_TEXTURE_COMPARE_FUNC:
5954 if (!ValidateTextureCompareFuncValue(context, params))
5955 {
5956 return false;
5957 }
5958 break;
5959
5960 case GL_TEXTURE_SWIZZLE_R:
5961 case GL_TEXTURE_SWIZZLE_G:
5962 case GL_TEXTURE_SWIZZLE_B:
5963 case GL_TEXTURE_SWIZZLE_A:
5964 switch (ConvertToGLenum(params[0]))
5965 {
5966 case GL_RED:
5967 case GL_GREEN:
5968 case GL_BLUE:
5969 case GL_ALPHA:
5970 case GL_ZERO:
5971 case GL_ONE:
5972 break;
5973
5974 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005976 return false;
5977 }
5978 break;
5979
5980 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005981 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005983 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 return false;
5985 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005986 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005988 context->handleError(InvalidOperation()
5989 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 return false;
5991 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005992 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005993 {
5994 context->handleError(InvalidOperation()
5995 << "Base level must be 0 for multisampled textures.");
5996 return false;
5997 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005998 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005999 {
6000 context->handleError(InvalidOperation()
6001 << "Base level must be 0 for rectangle textures.");
6002 return false;
6003 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006004 break;
6005
6006 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006007 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006009 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006010 return false;
6011 }
6012 break;
6013
6014 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6015 if (context->getClientVersion() < Version(3, 1))
6016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006017 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006018 return false;
6019 }
6020 switch (ConvertToGLenum(params[0]))
6021 {
6022 case GL_DEPTH_COMPONENT:
6023 case GL_STENCIL_INDEX:
6024 break;
6025
6026 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006027 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006028 return false;
6029 }
6030 break;
6031
6032 case GL_TEXTURE_SRGB_DECODE_EXT:
6033 if (!ValidateTextureSRGBDecodeValue(context, params))
6034 {
6035 return false;
6036 }
6037 break;
6038
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006039 case GL_GENERATE_MIPMAP:
6040 case GL_TEXTURE_CROP_RECT_OES:
6041 if (context->getClientMajorVersion() > 1)
6042 {
6043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6044 return false;
6045 }
6046 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006047 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006048 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006049 return false;
6050 }
6051
6052 return true;
6053}
6054
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006055template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6056template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006057
Jamie Madill5b772312018-03-08 20:28:32 -05006058bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006059{
6060 if (index >= MAX_VERTEX_ATTRIBS)
6061 {
6062 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6063 return false;
6064 }
6065
6066 return true;
6067}
6068
6069bool ValidateGetActiveUniformBlockivBase(Context *context,
6070 GLuint program,
6071 GLuint uniformBlockIndex,
6072 GLenum pname,
6073 GLsizei *length)
6074{
6075 if (length)
6076 {
6077 *length = 0;
6078 }
6079
6080 if (context->getClientMajorVersion() < 3)
6081 {
6082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6083 return false;
6084 }
6085
6086 Program *programObject = GetValidProgram(context, program);
6087 if (!programObject)
6088 {
6089 return false;
6090 }
6091
6092 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6093 {
6094 context->handleError(InvalidValue()
6095 << "uniformBlockIndex exceeds active uniform block count.");
6096 return false;
6097 }
6098
6099 switch (pname)
6100 {
6101 case GL_UNIFORM_BLOCK_BINDING:
6102 case GL_UNIFORM_BLOCK_DATA_SIZE:
6103 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6104 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6105 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6106 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6107 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6108 break;
6109
6110 default:
6111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6112 return false;
6113 }
6114
6115 if (length)
6116 {
6117 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6118 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006119 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006120 programObject->getUniformBlockByIndex(uniformBlockIndex);
6121 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6122 }
6123 else
6124 {
6125 *length = 1;
6126 }
6127 }
6128
6129 return true;
6130}
6131
Jamie Madill9696d072017-08-26 23:19:57 -04006132template <typename ParamType>
6133bool ValidateSamplerParameterBase(Context *context,
6134 GLuint sampler,
6135 GLenum pname,
6136 GLsizei bufSize,
6137 ParamType *params)
6138{
6139 if (context->getClientMajorVersion() < 3)
6140 {
6141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6142 return false;
6143 }
6144
6145 if (!context->isSampler(sampler))
6146 {
6147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6148 return false;
6149 }
6150
6151 const GLsizei minBufSize = 1;
6152 if (bufSize >= 0 && bufSize < minBufSize)
6153 {
6154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6155 return false;
6156 }
6157
6158 switch (pname)
6159 {
6160 case GL_TEXTURE_WRAP_S:
6161 case GL_TEXTURE_WRAP_T:
6162 case GL_TEXTURE_WRAP_R:
6163 if (!ValidateTextureWrapModeValue(context, params, false))
6164 {
6165 return false;
6166 }
6167 break;
6168
6169 case GL_TEXTURE_MIN_FILTER:
6170 if (!ValidateTextureMinFilterValue(context, params, false))
6171 {
6172 return false;
6173 }
6174 break;
6175
6176 case GL_TEXTURE_MAG_FILTER:
6177 if (!ValidateTextureMagFilterValue(context, params))
6178 {
6179 return false;
6180 }
6181 break;
6182
6183 case GL_TEXTURE_MIN_LOD:
6184 case GL_TEXTURE_MAX_LOD:
6185 // any value is permissible
6186 break;
6187
6188 case GL_TEXTURE_COMPARE_MODE:
6189 if (!ValidateTextureCompareModeValue(context, params))
6190 {
6191 return false;
6192 }
6193 break;
6194
6195 case GL_TEXTURE_COMPARE_FUNC:
6196 if (!ValidateTextureCompareFuncValue(context, params))
6197 {
6198 return false;
6199 }
6200 break;
6201
6202 case GL_TEXTURE_SRGB_DECODE_EXT:
6203 if (!ValidateTextureSRGBDecodeValue(context, params))
6204 {
6205 return false;
6206 }
6207 break;
6208
Luc Ferron1b1a8642018-01-23 15:12:01 -05006209 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6210 {
6211 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6212 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6213 {
6214 return false;
6215 }
6216 }
6217 break;
6218
Jamie Madill9696d072017-08-26 23:19:57 -04006219 default:
6220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6221 return false;
6222 }
6223
6224 return true;
6225}
6226
6227template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6228template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6229
6230bool ValidateGetSamplerParameterBase(Context *context,
6231 GLuint sampler,
6232 GLenum pname,
6233 GLsizei *length)
6234{
6235 if (length)
6236 {
6237 *length = 0;
6238 }
6239
6240 if (context->getClientMajorVersion() < 3)
6241 {
6242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6243 return false;
6244 }
6245
6246 if (!context->isSampler(sampler))
6247 {
6248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6249 return false;
6250 }
6251
6252 switch (pname)
6253 {
6254 case GL_TEXTURE_WRAP_S:
6255 case GL_TEXTURE_WRAP_T:
6256 case GL_TEXTURE_WRAP_R:
6257 case GL_TEXTURE_MIN_FILTER:
6258 case GL_TEXTURE_MAG_FILTER:
6259 case GL_TEXTURE_MIN_LOD:
6260 case GL_TEXTURE_MAX_LOD:
6261 case GL_TEXTURE_COMPARE_MODE:
6262 case GL_TEXTURE_COMPARE_FUNC:
6263 break;
6264
Luc Ferron1b1a8642018-01-23 15:12:01 -05006265 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6266 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6267 {
6268 return false;
6269 }
6270 break;
6271
Jamie Madill9696d072017-08-26 23:19:57 -04006272 case GL_TEXTURE_SRGB_DECODE_EXT:
6273 if (!context->getExtensions().textureSRGBDecode)
6274 {
6275 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6276 return false;
6277 }
6278 break;
6279
6280 default:
6281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6282 return false;
6283 }
6284
6285 if (length)
6286 {
6287 *length = 1;
6288 }
6289 return true;
6290}
6291
6292bool ValidateGetInternalFormativBase(Context *context,
6293 GLenum target,
6294 GLenum internalformat,
6295 GLenum pname,
6296 GLsizei bufSize,
6297 GLsizei *numParams)
6298{
6299 if (numParams)
6300 {
6301 *numParams = 0;
6302 }
6303
6304 if (context->getClientMajorVersion() < 3)
6305 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006307 return false;
6308 }
6309
6310 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006311 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006312 {
6313 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6314 return false;
6315 }
6316
6317 switch (target)
6318 {
6319 case GL_RENDERBUFFER:
6320 break;
6321
6322 case GL_TEXTURE_2D_MULTISAMPLE:
6323 if (context->getClientVersion() < ES_3_1)
6324 {
6325 context->handleError(InvalidOperation()
6326 << "Texture target requires at least OpenGL ES 3.1.");
6327 return false;
6328 }
6329 break;
6330
6331 default:
6332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6333 return false;
6334 }
6335
6336 if (bufSize < 0)
6337 {
6338 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6339 return false;
6340 }
6341
6342 GLsizei maxWriteParams = 0;
6343 switch (pname)
6344 {
6345 case GL_NUM_SAMPLE_COUNTS:
6346 maxWriteParams = 1;
6347 break;
6348
6349 case GL_SAMPLES:
6350 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6351 break;
6352
6353 default:
6354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6355 return false;
6356 }
6357
6358 if (numParams)
6359 {
6360 // glGetInternalFormativ will not overflow bufSize
6361 *numParams = std::min(bufSize, maxWriteParams);
6362 }
6363
6364 return true;
6365}
6366
Jamie Madille98b1b52018-03-08 09:47:23 -05006367bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6368{
Jamie Madill427064d2018-04-13 16:20:34 -04006369 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006370 {
6371 context->handleError(InvalidOperation());
6372 return false;
6373 }
6374 return true;
6375}
6376
Lingfeng Yang038dd532018-03-29 17:31:52 -07006377bool ValidateMultitextureUnit(Context *context, GLenum texture)
6378{
6379 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6380 {
6381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6382 return false;
6383 }
6384 return true;
6385}
6386
Jamie Madillc29968b2016-01-20 11:17:23 -05006387} // namespace gl