blob: 8e05cd2f27f3311c5f9b065b80de8a8fd4616f5a [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));
Olli Etuahod310a432018-08-24 15:40:23 +0300503 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300504 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400505
He Yunchaoced53ae2016-11-29 15:00:51 +0800506 default:
507 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500508 }
Jamie Madill35d15012013-10-07 10:46:37 -0400509}
510
Jamie Madill5b772312018-03-08 20:28:32 -0500511bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500512{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500514 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800515 case TextureType::_2D:
516 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500517 return true;
518
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800519 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400520 return context->getExtensions().textureRectangle;
521
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522 default:
523 return false;
524 }
525}
526
Jamie Madill5b772312018-03-08 20:28:32 -0500527bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528{
529 switch (target)
530 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800531 case TextureType::_3D:
532 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300533 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534
535 default:
536 return false;
537 }
538}
539
Ian Ewellbda75592016-04-18 17:25:54 -0400540// Most texture GL calls are not compatible with external textures, so we have a separate validation
541// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500542bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400543{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800544 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400545 (context->getExtensions().eglImageExternal ||
546 context->getExtensions().eglStreamConsumerExternal);
547}
548
Shannon Woods4dfed832014-03-17 20:03:39 -0400549// This function differs from ValidTextureTarget in that the target must be
550// usable as the destination of a 2D operation-- so a cube face is valid, but
551// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400552// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400554{
555 switch (target)
556 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureTarget::_2D:
558 case TextureTarget::CubeMapNegativeX:
559 case TextureTarget::CubeMapNegativeY:
560 case TextureTarget::CubeMapNegativeZ:
561 case TextureTarget::CubeMapPositiveX:
562 case TextureTarget::CubeMapPositiveY:
563 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800564 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400566 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800567 default:
568 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500569 }
570}
571
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800572bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400573 PrimitiveMode transformFeedbackPrimitiveMode,
574 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800575{
576 ASSERT(context);
577
578 if (!context->getExtensions().geometryShader)
579 {
580 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
581 // that does not match the current transform feedback object's draw mode (if transform
582 // feedback is active), (3.0.2, section 2.14, pg 86)
583 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
584 }
585
586 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400587 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800588 {
Jamie Madill493f9572018-05-24 19:52:15 -0400589 case PrimitiveMode::Points:
590 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
591 case PrimitiveMode::Lines:
592 case PrimitiveMode::LineStrip:
593 case PrimitiveMode::LineLoop:
594 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
595 case PrimitiveMode::Triangles:
596 case PrimitiveMode::TriangleFan:
597 case PrimitiveMode::TriangleStrip:
598 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800599 default:
600 UNREACHABLE();
601 return false;
602 }
603}
604
Jamie Madill5b772312018-03-08 20:28:32 -0500605bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400606 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400607 GLsizei count,
608 GLenum type,
609 const GLvoid *indices,
610 GLsizei primcount)
611{
612 if (primcount < 0)
613 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700614 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400615 return false;
616 }
617
618 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
619 {
620 return false;
621 }
622
Jamie Madill9fdaa492018-02-16 10:52:11 -0500623 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400624}
625
626bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400627 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400628 GLint first,
629 GLsizei count,
630 GLsizei primcount)
631{
632 if (primcount < 0)
633 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700634 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 return false;
636 }
637
638 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
639 {
640 return false;
641 }
642
Jamie Madill9fdaa492018-02-16 10:52:11 -0500643 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400644}
645
Jamie Madill5b772312018-03-08 20:28:32 -0500646bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400647{
648 // Verify there is at least one active attribute with a divisor of zero
649 const State &state = context->getGLState();
650
651 Program *program = state.getProgram();
652
653 const auto &attribs = state.getVertexArray()->getVertexAttributes();
654 const auto &bindings = state.getVertexArray()->getVertexBindings();
655 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
656 {
657 const VertexAttribute &attrib = attribs[attributeIndex];
658 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300659 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 {
661 return true;
662 }
663 }
664
Brandon Jonesafa75152017-07-21 13:11:29 -0700665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400666 return false;
667}
668
Jamie Madill5b772312018-03-08 20:28:32 -0500669bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500670{
671 switch (target)
672 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800673 case TextureType::_3D:
674 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800675 return true;
676 default:
677 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400678 }
679}
680
Jamie Madill5b772312018-03-08 20:28:32 -0500681bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800682{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800683 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800684 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800685 case TextureType::_2D:
686 case TextureType::_2DArray:
687 case TextureType::_2DMultisample:
688 case TextureType::CubeMap:
689 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800690 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800691 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400692 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300693 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300694 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800695 default:
696 return false;
697 }
698}
699
Jamie Madill5b772312018-03-08 20:28:32 -0500700bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500701{
He Yunchaoced53ae2016-11-29 15:00:51 +0800702 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
703 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400704 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500705
706 switch (target)
707 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_FRAMEBUFFER:
709 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400710
He Yunchaoced53ae2016-11-29 15:00:51 +0800711 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400713 return (context->getExtensions().framebufferBlit ||
714 context->getClientMajorVersion() >= 3);
715
He Yunchaoced53ae2016-11-29 15:00:51 +0800716 default:
717 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500718 }
719}
720
Jamie Madill5b772312018-03-08 20:28:32 -0500721bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400722{
Jamie Madillc29968b2016-01-20 11:17:23 -0500723 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400724 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800725 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400726 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800727 case TextureType::_2D:
728 case TextureType::_2DArray:
729 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300730 case TextureType::_2DMultisampleArray:
731 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
732 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500733 maxDimension = caps.max2DTextureSize;
734 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800735 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 maxDimension = caps.maxCubeMapTextureSize;
737 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800738 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400739 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800740 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 maxDimension = caps.max3DTextureSize;
742 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 default:
744 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400745 }
746
Jamie Madill43da7c42018-08-01 11:34:49 -0400747 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400748}
749
Jamie Madill5b772312018-03-08 20:28:32 -0500750bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800751 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700752 GLint level,
753 GLsizei width,
754 GLsizei height,
755 GLsizei depth,
756 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400757{
Brandon Jones6cad5662017-06-14 13:25:13 -0700758 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400759 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700760 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400761 return false;
762 }
Austin Kinross08528e12015-10-07 16:24:40 -0700763 // TexSubImage parameters can be NPOT without textureNPOT extension,
764 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500765 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500766 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500767 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400768 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400769 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700770 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400771 return false;
772 }
773
774 if (!ValidMipLevel(context, target, level))
775 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700776 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400777 return false;
778 }
779
780 return true;
781}
782
Geoff Lang966c9402017-04-18 12:38:27 -0400783bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
784{
785 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
786 (size % blockSize == 0);
787}
788
Jamie Madill5b772312018-03-08 20:28:32 -0500789bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500790 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400791 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500792 GLsizei width,
793 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400794{
Jamie Madill43da7c42018-08-01 11:34:49 -0400795 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400796 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400797 {
798 return false;
799 }
800
Geoff Lang966c9402017-04-18 12:38:27 -0400801 if (width < 0 || height < 0)
802 {
803 return false;
804 }
805
806 if (CompressedTextureFormatRequiresExactSize(internalFormat))
807 {
808 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
809 // block size for level 0 but WebGL disallows this.
810 bool smallerThanBlockSizeAllowed =
811 level > 0 || !context->getExtensions().webglCompatibility;
812
813 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
814 smallerThanBlockSizeAllowed) ||
815 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
816 smallerThanBlockSizeAllowed))
817 {
818 return false;
819 }
820 }
821
822 return true;
823}
824
Jamie Madill5b772312018-03-08 20:28:32 -0500825bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400826 GLenum internalFormat,
827 GLint xoffset,
828 GLint yoffset,
829 GLsizei width,
830 GLsizei height,
831 size_t textureWidth,
832 size_t textureHeight)
833{
Jamie Madill43da7c42018-08-01 11:34:49 -0400834 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400835 if (!formatInfo.compressed)
836 {
837 return false;
838 }
839
Geoff Lang44ff5a72017-02-03 15:15:43 -0500840 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400841 {
842 return false;
843 }
844
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500845 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400846 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500847 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400848 yoffset % formatInfo.compressedBlockHeight != 0)
849 {
850 return false;
851 }
852
853 // Allowed to either have data that is a multiple of block size or is smaller than the block
854 // size but fills the entire mip
855 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
856 static_cast<size_t>(width) == textureWidth &&
857 static_cast<size_t>(height) == textureHeight;
858 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
859 (height % formatInfo.compressedBlockHeight) == 0;
860 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400861 {
862 return false;
863 }
864 }
865
Geoff Langd4f180b2013-09-24 13:57:44 -0400866 return true;
867}
868
Jamie Madill5b772312018-03-08 20:28:32 -0500869bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800870 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400871 GLsizei width,
872 GLsizei height,
873 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400874 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400875 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400876 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400877 GLsizei imageSize)
878{
Jamie Madill43da7c42018-08-01 11:34:49 -0400879 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400880 if (pixelUnpackBuffer == nullptr && imageSize < 0)
881 {
882 // Checks are not required
883 return true;
884 }
885
886 // ...the data would be unpacked from the buffer object such that the memory reads required
887 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400888 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400889 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400890 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 const auto &unpack = context->getGLState().getUnpackState();
892
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800893 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400894 GLuint endByte = 0;
895 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400896 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400898 return false;
899 }
900
Geoff Langff5b2d52016-09-07 11:32:23 -0400901 if (pixelUnpackBuffer)
902 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400903 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400904 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
905 checkedEndByte += checkedOffset;
906
907 if (!checkedEndByte.IsValid() ||
908 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
909 {
910 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400912 return false;
913 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800914 if (context->getExtensions().webglCompatibility &&
915 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
916 {
917 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
918 PixelUnpackBufferBoundForTransformFeedback);
919 return false;
920 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400921 }
922 else
923 {
924 ASSERT(imageSize >= 0);
925 if (pixels == nullptr && imageSize != 0)
926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation()
928 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400929 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400930 }
931
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400932 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500934 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 return false;
936 }
937 }
938
939 return true;
940}
941
Corentin Wallezad3ae902018-03-09 13:40:42 -0500942bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500943{
Geoff Lang37dde692014-01-31 16:34:54 -0500944 switch (queryType)
945 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500946 case QueryType::AnySamples:
947 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400948 return context->getClientMajorVersion() >= 3 ||
949 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500950 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500952 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800953 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500954 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800955 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500956 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800957 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800958 default:
959 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500960 }
961}
962
Jamie Madill5b772312018-03-08 20:28:32 -0500963bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 GLenum type,
965 GLboolean normalized,
966 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400967 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400968 bool pureInteger)
969{
970 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400971 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
972 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
973 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
974 // parameter exceeds 255.
975 constexpr GLsizei kMaxWebGLStride = 255;
976 if (stride > kMaxWebGLStride)
977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500978 context->handleError(InvalidValue()
979 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400980 return false;
981 }
982
983 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
984 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
985 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
986 // or an INVALID_OPERATION error is generated.
987 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
988 size_t typeSize = GetVertexFormatTypeSize(internalType);
989
990 ASSERT(isPow2(typeSize) && typeSize > 0);
991 size_t sizeMask = (typeSize - 1);
992 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
993 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400995 return false;
996 }
997
998 if ((stride & sizeMask) != 0)
999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 return false;
1002 }
1003
1004 return true;
1005}
1006
Jamie Madill5b772312018-03-08 20:28:32 -05001007Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001008{
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1010 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1011 // or program object and INVALID_OPERATION if the provided name identifies an object
1012 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001013
Dian Xiang769769a2015-09-09 15:20:08 -07001014 Program *validProgram = context->getProgram(id);
1015
1016 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001017 {
Dian Xiang769769a2015-09-09 15:20:08 -07001018 if (context->getShader(id))
1019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001021 }
1022 else
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001025 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001026 }
Dian Xiang769769a2015-09-09 15:20:08 -07001027
1028 return validProgram;
1029}
1030
Jamie Madill5b772312018-03-08 20:28:32 -05001031Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001032{
1033 // See ValidProgram for spec details.
1034
1035 Shader *validShader = context->getShader(id);
1036
1037 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038 {
Dian Xiang769769a2015-09-09 15:20:08 -07001039 if (context->getProgram(id))
1040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001042 }
1043 else
1044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001045 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001046 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 }
Dian Xiang769769a2015-09-09 15:20:08 -07001048
1049 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001050}
1051
Jamie Madill43da7c42018-08-01 11:34:49 -04001052bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001053{
Geoff Langfa125c92017-10-24 13:01:46 -04001054 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001055 {
Geoff Langfa125c92017-10-24 13:01:46 -04001056 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1057 {
1058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1059 return false;
1060 }
Jamie Madillb4472272014-07-03 10:38:55 -04001061
Geoff Langfa125c92017-10-24 13:01:46 -04001062 // Color attachment 0 is validated below because it is always valid
1063 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001064 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001065 {
Geoff Langfa125c92017-10-24 13:01:46 -04001066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001068 }
1069 }
1070 else
1071 {
1072 switch (attachment)
1073 {
Geoff Langfa125c92017-10-24 13:01:46 -04001074 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 case GL_DEPTH_ATTACHMENT:
1076 case GL_STENCIL_ATTACHMENT:
1077 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001078
He Yunchaoced53ae2016-11-29 15:00:51 +08001079 case GL_DEPTH_STENCIL_ATTACHMENT:
1080 if (!context->getExtensions().webglCompatibility &&
1081 context->getClientMajorVersion() < 3)
1082 {
Geoff Langfa125c92017-10-24 13:01:46 -04001083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001084 return false;
1085 }
1086 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001087
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001090 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001091 }
1092 }
1093
1094 return true;
1095}
1096
Jamie Madill5b772312018-03-08 20:28:32 -05001097bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 GLenum target,
1099 GLsizei samples,
1100 GLenum internalformat,
1101 GLsizei width,
1102 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103{
1104 switch (target)
1105 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 case GL_RENDERBUFFER:
1107 break;
1108 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 }
1112
1113 if (width < 0 || height < 0 || samples < 0)
1114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001116 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 }
1118
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001119 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1120 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1121
1122 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001123 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001125 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 }
1128
1129 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1130 // 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 -08001131 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001132 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001133 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001137 }
1138
Geoff Langaae65a42014-05-26 12:43:44 -04001139 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001145 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 if (handle == 0)
1147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
1152 return true;
1153}
1154
Jamie Madill43da7c42018-08-01 11:34:49 -04001155bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 GLenum target,
1157 GLenum attachment,
1158 GLenum renderbuffertarget,
1159 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001160{
Geoff Lange8afa902017-09-27 15:00:43 -04001161 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001163 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001165 }
1166
Jamie Madill43da7c42018-08-01 11:34:49 -04001167 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001168
Jamie Madill84115c92015-04-23 15:00:07 -04001169 ASSERT(framebuffer);
1170 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001174 }
1175
Jamie Madillb4472272014-07-03 10:38:55 -04001176 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001177 {
Jamie Madillb4472272014-07-03 10:38:55 -04001178 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001179 }
1180
Jamie Madillab9d82c2014-01-21 16:38:14 -05001181 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1182 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1183 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1184 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1185 if (renderbuffer != 0)
1186 {
1187 if (!context->getRenderbuffer(renderbuffer))
1188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001190 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001191 }
1192 }
1193
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001194 return true;
1195}
1196
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001197bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001198 GLint srcX0,
1199 GLint srcY0,
1200 GLint srcX1,
1201 GLint srcY1,
1202 GLint dstX0,
1203 GLint dstY0,
1204 GLint dstX1,
1205 GLint dstY1,
1206 GLbitfield mask,
1207 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208{
1209 switch (filter)
1210 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 case GL_NEAREST:
1212 break;
1213 case GL_LINEAR:
1214 break;
1215 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001218 }
1219
1220 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1221 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001222 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001224 }
1225
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1227 // color buffer, leaving only nearest being unfiltered from above
1228 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1229 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 }
1233
Jamie Madill51f40ec2016-06-15 14:06:00 -04001234 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001235 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1236 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001237
1238 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001240 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001241 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001242 }
1243
Jamie Madill427064d2018-04-13 16:20:34 -04001244 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001245 {
Jamie Madill48faf802014-11-06 15:27:22 -05001246 return false;
1247 }
1248
Jamie Madill427064d2018-04-13 16:20:34 -04001249 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001250 {
Jamie Madill48faf802014-11-06 15:27:22 -05001251 return false;
1252 }
1253
Qin Jiajiaaef92162018-02-27 13:51:44 +08001254 if (readFramebuffer->id() == drawFramebuffer->id())
1255 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001257 return false;
1258 }
1259
Jamie Madille98b1b52018-03-08 09:47:23 -05001260 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 {
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001265 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1266 // always run it in order to avoid triggering driver bugs.
1267 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1268 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001269 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001270 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1271 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001272 }
1273
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1275
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276 if (mask & GL_COLOR_BUFFER_BIT)
1277 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001278 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001279 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280
He Yunchao66a41a22016-12-15 16:45:05 +08001281 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001283 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284
Geoff Langa15472a2015-08-11 11:48:03 -04001285 for (size_t drawbufferIdx = 0;
1286 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 {
Geoff Langa15472a2015-08-11 11:48:03 -04001288 const FramebufferAttachment *attachment =
1289 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1290 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001292 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293
Geoff Langb2f3d052013-08-13 12:49:27 -04001294 // The GL ES 3.0.2 spec (pg 193) states that:
1295 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1297 // as well
1298 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1299 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001300 // Changes with EXT_color_buffer_float:
1301 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001302 GLenum readComponentType = readFormat.info->componentType;
1303 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001304 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001305 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001306 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001307 drawComponentType == GL_SIGNED_NORMALIZED);
1308
1309 if (extensions.colorBufferFloat)
1310 {
1311 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1312 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1313
1314 if (readFixedOrFloat != drawFixedOrFloat)
1315 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001316 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1317 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001318 return false;
1319 }
1320 }
1321 else if (readFixedPoint != drawFixedPoint)
1322 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001323 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1324 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001325 return false;
1326 }
1327
1328 if (readComponentType == GL_UNSIGNED_INT &&
1329 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001331 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1332 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335
Jamie Madill6163c752015-12-07 16:32:59 -05001336 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1339 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001340 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 }
1342
Jamie Madilla3944d42016-07-22 22:13:26 -04001343 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001344 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001346 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1347 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001348 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 }
Geoff Lange4915782017-04-12 15:19:07 -04001350
1351 if (context->getExtensions().webglCompatibility &&
1352 *readColorBuffer == *attachment)
1353 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001354 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001355 return false;
1356 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 }
1358 }
1359
Jamie Madilla3944d42016-07-22 22:13:26 -04001360 if ((readFormat.info->componentType == GL_INT ||
1361 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1362 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
He Yunchao66a41a22016-12-15 16:45:05 +08001368 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1369 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1370 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1371 // situation is an application error that would lead to a crash in ANGLE.
1372 else if (drawFramebuffer->hasEnabledDrawBuffer())
1373 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001374 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001375 return false;
1376 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001380 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1381 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001383 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001385 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001386 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001387 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001388 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001390 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 {
Kenneth Russell69382852017-07-21 16:38:44 -04001392 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001394 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1395 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001399 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001401 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1402 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
Geoff Lange4915782017-04-12 15:19:07 -04001405
1406 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1407 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
He Yunchao66a41a22016-12-15 16:45:05 +08001412 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1413 else if (drawBuffer)
1414 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001416 return false;
1417 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
1419 }
1420
Martin Radeva3ed4572017-07-27 18:29:37 +03001421 // ANGLE_multiview, Revision 1:
1422 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001423 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1424 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1425 // views in the current read framebuffer is more than one.
1426 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001427 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001428 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001429 return false;
1430 }
1431 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001433 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001434 return false;
1435 }
1436
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 return true;
1438}
1439
Jamie Madill4928b7c2017-06-20 12:57:39 -04001440bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001441 GLint x,
1442 GLint y,
1443 GLsizei width,
1444 GLsizei height,
1445 GLenum format,
1446 GLenum type,
1447 GLsizei bufSize,
1448 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001449 GLsizei *columns,
1450 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001451 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001452{
1453 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001454 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 return false;
1456 }
1457
Brandon Jonesd1049182018-03-28 10:02:20 -07001458 GLsizei writeLength = 0;
1459 GLsizei writeColumns = 0;
1460 GLsizei writeRows = 0;
1461
1462 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1463 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001464 {
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001466 }
1467
Brandon Jonesd1049182018-03-28 10:02:20 -07001468 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001469 {
Geoff Langb1196682014-07-23 13:47:29 -04001470 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001471 }
1472
Brandon Jonesd1049182018-03-28 10:02:20 -07001473 SetRobustLengthParam(length, writeLength);
1474 SetRobustLengthParam(columns, writeColumns);
1475 SetRobustLengthParam(rows, writeRows);
1476
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 return true;
1478}
1479
1480bool ValidateReadnPixelsEXT(Context *context,
1481 GLint x,
1482 GLint y,
1483 GLsizei width,
1484 GLsizei height,
1485 GLenum format,
1486 GLenum type,
1487 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001488 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001489{
1490 if (bufSize < 0)
1491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001492 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Geoff Lang62fce5b2016-09-30 10:46:35 -04001496 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001497 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001498}
Jamie Madill26e91952014-03-05 15:01:27 -05001499
Jamie Madill4928b7c2017-06-20 12:57:39 -04001500bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001501 GLint x,
1502 GLint y,
1503 GLsizei width,
1504 GLsizei height,
1505 GLenum format,
1506 GLenum type,
1507 GLsizei bufSize,
1508 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001509 GLsizei *columns,
1510 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001511 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001512{
Brandon Jonesd1049182018-03-28 10:02:20 -07001513 GLsizei writeLength = 0;
1514 GLsizei writeColumns = 0;
1515 GLsizei writeRows = 0;
1516
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001518 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001519 return false;
1520 }
1521
Brandon Jonesd1049182018-03-28 10:02:20 -07001522 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1523 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001524 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001525 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001526 }
1527
Brandon Jonesd1049182018-03-28 10:02:20 -07001528 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529 {
1530 return false;
1531 }
1532
Brandon Jonesd1049182018-03-28 10:02:20 -07001533 SetRobustLengthParam(length, writeLength);
1534 SetRobustLengthParam(columns, writeColumns);
1535 SetRobustLengthParam(rows, writeRows);
1536
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001538}
1539
Jamie Madill43da7c42018-08-01 11:34:49 -04001540bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001541{
1542 if (!context->getExtensions().occlusionQueryBoolean &&
1543 !context->getExtensions().disjointTimerQuery)
1544 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001546 return false;
1547 }
1548
Olli Etuaho41997e72016-03-10 13:38:39 +02001549 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550}
1551
Jamie Madill43da7c42018-08-01 11:34:49 -04001552bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001553{
1554 if (!context->getExtensions().occlusionQueryBoolean &&
1555 !context->getExtensions().disjointTimerQuery)
1556 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001557 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001558 return false;
1559 }
1560
Olli Etuaho41997e72016-03-10 13:38:39 +02001561 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562}
1563
Jamie Madill43da7c42018-08-01 11:34:49 -04001564bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001565{
1566 if (!context->getExtensions().occlusionQueryBoolean &&
1567 !context->getExtensions().disjointTimerQuery)
1568 {
1569 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1570 return false;
1571 }
1572
1573 return true;
1574}
1575
Jamie Madill43da7c42018-08-01 11:34:49 -04001576bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001577{
1578 if (!ValidQueryType(context, target))
1579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001581 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001582 }
1583
1584 if (id == 0)
1585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001587 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001588 }
1589
1590 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1591 // of zero, if the active query object name for <target> is non-zero (for the
1592 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1593 // the active query for either target is non-zero), if <id> is the name of an
1594 // existing query object whose type does not match <target>, or if <id> is the
1595 // active query object name for any query type, the error INVALID_OPERATION is
1596 // generated.
1597
1598 // Ensure no other queries are active
1599 // NOTE: If other queries than occlusion are supported, we will need to check
1600 // separately that:
1601 // a) The query ID passed is not the current active query for any target/type
1602 // b) There are no active queries for the requested target (and in the case
1603 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1604 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001605
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001606 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001610 }
1611
1612 Query *queryObject = context->getQuery(id, true, target);
1613
1614 // check that name was obtained with glGenQueries
1615 if (!queryObject)
1616 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001619 }
1620
1621 // check for type mismatch
1622 if (queryObject->getType() != target)
1623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001624 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001626 }
1627
1628 return true;
1629}
1630
Jamie Madill43da7c42018-08-01 11:34:49 -04001631bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632{
1633 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001634 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001637 return false;
1638 }
1639
1640 return ValidateBeginQueryBase(context, target, id);
1641}
1642
Jamie Madill43da7c42018-08-01 11:34:49 -04001643bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001644{
1645 if (!ValidQueryType(context, target))
1646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001649 }
1650
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001651 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001652
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001657 }
1658
Jamie Madill45c785d2014-05-13 14:09:34 -04001659 return true;
1660}
1661
Jamie Madill43da7c42018-08-01 11:34:49 -04001662bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663{
1664 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001665 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668 return false;
1669 }
1670
1671 return ValidateEndQueryBase(context, target);
1672}
1673
Corentin Wallezad3ae902018-03-09 13:40:42 -05001674bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675{
1676 if (!context->getExtensions().disjointTimerQuery)
1677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001678 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679 return false;
1680 }
1681
Corentin Wallezad3ae902018-03-09 13:40:42 -05001682 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685 return false;
1686 }
1687
1688 Query *queryObject = context->getQuery(id, true, target);
1689 if (queryObject == nullptr)
1690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 return false;
1693 }
1694
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001695 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001698 return false;
1699 }
1700
1701 return true;
1702}
1703
Corentin Wallezad3ae902018-03-09 13:40:42 -05001704bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705{
Geoff Lang2186c382016-10-14 10:54:54 -04001706 if (numParams)
1707 {
1708 *numParams = 0;
1709 }
1710
Corentin Wallezad3ae902018-03-09 13:40:42 -05001711 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001713 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 return false;
1715 }
1716
1717 switch (pname)
1718 {
1719 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001720 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001722 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725 break;
1726 case GL_QUERY_COUNTER_BITS_EXT:
1727 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001728 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733 break;
1734 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
Geoff Lang2186c382016-10-14 10:54:54 -04001739 if (numParams)
1740 {
1741 // All queries return only one value
1742 *numParams = 1;
1743 }
1744
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return true;
1746}
1747
Corentin Wallezad3ae902018-03-09 13:40:42 -05001748bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749{
1750 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001751 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 return false;
1755 }
1756
Geoff Lang2186c382016-10-14 10:54:54 -04001757 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758}
1759
Geoff Lang2186c382016-10-14 10:54:54 -04001760bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001761 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001762 GLenum pname,
1763 GLsizei bufSize,
1764 GLsizei *length,
1765 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766{
Geoff Lang2186c382016-10-14 10:54:54 -04001767 if (!ValidateRobustEntryPoint(context, bufSize))
1768 {
1769 return false;
1770 }
1771
Brandon Jonesd1049182018-03-28 10:02:20 -07001772 GLsizei numParams = 0;
1773
1774 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001775 {
1776 return false;
1777 }
1778
Brandon Jonesd1049182018-03-28 10:02:20 -07001779 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001780 {
1781 return false;
1782 }
1783
Brandon Jonesd1049182018-03-28 10:02:20 -07001784 SetRobustLengthParam(length, numParams);
1785
Geoff Lang2186c382016-10-14 10:54:54 -04001786 return true;
1787}
1788
1789bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1790{
1791 if (numParams)
1792 {
1793 *numParams = 0;
1794 }
1795
Corentin Wallezad3ae902018-03-09 13:40:42 -05001796 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797
1798 if (!queryObject)
1799 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 return false;
1802 }
1803
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001804 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return false;
1808 }
1809
1810 switch (pname)
1811 {
1812 case GL_QUERY_RESULT_EXT:
1813 case GL_QUERY_RESULT_AVAILABLE_EXT:
1814 break;
1815
1816 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001817 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818 return false;
1819 }
1820
Geoff Lang2186c382016-10-14 10:54:54 -04001821 if (numParams)
1822 {
1823 *numParams = 1;
1824 }
1825
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 return true;
1827}
1828
1829bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1830{
1831 if (!context->getExtensions().disjointTimerQuery)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 return false;
1835 }
Geoff Lang2186c382016-10-14 10:54:54 -04001836 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1837}
1838
1839bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1840 GLuint id,
1841 GLenum pname,
1842 GLsizei bufSize,
1843 GLsizei *length,
1844 GLint *params)
1845{
1846 if (!context->getExtensions().disjointTimerQuery)
1847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001848 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001849 return false;
1850 }
1851
1852 if (!ValidateRobustEntryPoint(context, bufSize))
1853 {
1854 return false;
1855 }
1856
Brandon Jonesd1049182018-03-28 10:02:20 -07001857 GLsizei numParams = 0;
1858
1859 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001860 {
1861 return false;
1862 }
1863
Brandon Jonesd1049182018-03-28 10:02:20 -07001864 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001865 {
1866 return false;
1867 }
1868
Brandon Jonesd1049182018-03-28 10:02:20 -07001869 SetRobustLengthParam(length, numParams);
1870
Geoff Lang2186c382016-10-14 10:54:54 -04001871 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001872}
1873
1874bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1875{
1876 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001877 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001880 return false;
1881 }
Geoff Lang2186c382016-10-14 10:54:54 -04001882 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1883}
1884
1885bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1886 GLuint id,
1887 GLenum pname,
1888 GLsizei bufSize,
1889 GLsizei *length,
1890 GLuint *params)
1891{
1892 if (!context->getExtensions().disjointTimerQuery &&
1893 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001895 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001896 return false;
1897 }
1898
1899 if (!ValidateRobustEntryPoint(context, bufSize))
1900 {
1901 return false;
1902 }
1903
Brandon Jonesd1049182018-03-28 10:02:20 -07001904 GLsizei numParams = 0;
1905
1906 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001907 {
1908 return false;
1909 }
1910
Brandon Jonesd1049182018-03-28 10:02:20 -07001911 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001912 {
1913 return false;
1914 }
1915
Brandon Jonesd1049182018-03-28 10:02:20 -07001916 SetRobustLengthParam(length, numParams);
1917
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919}
1920
1921bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1922{
1923 if (!context->getExtensions().disjointTimerQuery)
1924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926 return false;
1927 }
Geoff Lang2186c382016-10-14 10:54:54 -04001928 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1929}
1930
1931bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1932 GLuint id,
1933 GLenum pname,
1934 GLsizei bufSize,
1935 GLsizei *length,
1936 GLint64 *params)
1937{
1938 if (!context->getExtensions().disjointTimerQuery)
1939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001941 return false;
1942 }
1943
1944 if (!ValidateRobustEntryPoint(context, bufSize))
1945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 GLsizei numParams = 0;
1950
1951 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001952 {
1953 return false;
1954 }
1955
Brandon Jonesd1049182018-03-28 10:02:20 -07001956 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001957 {
1958 return false;
1959 }
1960
Brandon Jonesd1049182018-03-28 10:02:20 -07001961 SetRobustLengthParam(length, numParams);
1962
Geoff Lang2186c382016-10-14 10:54:54 -04001963 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964}
1965
1966bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1967{
1968 if (!context->getExtensions().disjointTimerQuery)
1969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971 return false;
1972 }
Geoff Lang2186c382016-10-14 10:54:54 -04001973 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1974}
1975
1976bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1977 GLuint id,
1978 GLenum pname,
1979 GLsizei bufSize,
1980 GLsizei *length,
1981 GLuint64 *params)
1982{
1983 if (!context->getExtensions().disjointTimerQuery)
1984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001986 return false;
1987 }
1988
1989 if (!ValidateRobustEntryPoint(context, bufSize))
1990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 GLsizei numParams = 0;
1995
1996 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001997 {
1998 return false;
1999 }
2000
Brandon Jonesd1049182018-03-28 10:02:20 -07002001 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002002 {
2003 return false;
2004 }
2005
Brandon Jonesd1049182018-03-28 10:02:20 -07002006 SetRobustLengthParam(length, numParams);
2007
Geoff Lang2186c382016-10-14 10:54:54 -04002008 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009}
2010
Jamie Madill5b772312018-03-08 20:28:32 -05002011bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002012 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002013 GLint location,
2014 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002015 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002016{
Jiajia Qin5451d532017-11-16 17:16:34 +08002017 // TODO(Jiajia): Add image uniform check in future.
2018 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002019 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002020 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002021 return false;
2022 }
2023
Jiajia Qin5451d532017-11-16 17:16:34 +08002024 if (!program)
2025 {
2026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2027 return false;
2028 }
2029
2030 if (!program->isLinked())
2031 {
2032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2033 return false;
2034 }
2035
2036 if (location == -1)
2037 {
2038 // Silently ignore the uniform command
2039 return false;
2040 }
2041
2042 const auto &uniformLocations = program->getUniformLocations();
2043 size_t castedLocation = static_cast<size_t>(location);
2044 if (castedLocation >= uniformLocations.size())
2045 {
2046 context->handleError(InvalidOperation() << "Invalid uniform location");
2047 return false;
2048 }
2049
2050 const auto &uniformLocation = uniformLocations[castedLocation];
2051 if (uniformLocation.ignored)
2052 {
2053 // Silently ignore the uniform command
2054 return false;
2055 }
2056
2057 if (!uniformLocation.used())
2058 {
2059 context->handleError(InvalidOperation());
2060 return false;
2061 }
2062
2063 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2064
2065 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002066 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 {
2068 context->handleError(InvalidOperation());
2069 return false;
2070 }
2071
2072 *uniformOut = &uniform;
2073 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002074}
2075
Jamie Madill5b772312018-03-08 20:28:32 -05002076bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 GLenum uniformType,
2078 GLsizei count,
2079 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002080{
Jiajia Qin5451d532017-11-16 17:16:34 +08002081 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2082 // It is compatible with INT or BOOL.
2083 // Do these cheap tests first, for a little extra speed.
2084 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002085 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002086 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002087 }
2088
Jiajia Qin5451d532017-11-16 17:16:34 +08002089 if (IsSamplerType(uniformType))
2090 {
2091 // Check that the values are in range.
2092 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2093 for (GLsizei i = 0; i < count; ++i)
2094 {
2095 if (value[i] < 0 || value[i] >= max)
2096 {
2097 context->handleError(InvalidValue() << "sampler uniform value out of range");
2098 return false;
2099 }
2100 }
2101 return true;
2102 }
2103
2104 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2105 return false;
2106}
2107
Jamie Madill5b772312018-03-08 20:28:32 -05002108bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002109{
2110 // Check that the value type is compatible with uniform type.
2111 // Do the cheaper test first, for a little extra speed.
2112 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2113 {
2114 return true;
2115 }
2116
2117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2118 return false;
2119}
2120
Jamie Madill5b772312018-03-08 20:28:32 -05002121bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002122{
2123 // Check that the value type is compatible with uniform type.
2124 if (valueType == uniformType)
2125 {
2126 return true;
2127 }
2128
2129 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2130 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002131}
2132
Jamie Madill5b772312018-03-08 20:28:32 -05002133bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002134{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002135 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002136 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002137 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2138 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002139}
2140
Jamie Madill5b772312018-03-08 20:28:32 -05002141bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002142{
2143 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002144 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002145 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2146 ValidateUniform1ivValue(context, uniform->type, count, value);
2147}
2148
Jamie Madill5b772312018-03-08 20:28:32 -05002149bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002150 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002151 GLint location,
2152 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002153 GLboolean transpose)
2154{
Geoff Lang92019432017-11-20 13:09:34 -05002155 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002157 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002158 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002159 }
2160
Jamie Madill62d31cb2015-09-11 13:25:51 -04002161 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002162 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002163 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2164 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165}
2166
Jamie Madill5b772312018-03-08 20:28:32 -05002167bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002168{
2169 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002172 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002173 }
2174
Jamie Madill0af26e12015-03-05 19:54:33 -05002175 const Caps &caps = context->getCaps();
2176
Jamie Madill893ab082014-05-16 16:56:10 -04002177 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2178 {
2179 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2180
Jamie Madill0af26e12015-03-05 19:54:33 -05002181 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002184 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002185 }
2186 }
2187
2188 switch (pname)
2189 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002190 case GL_TEXTURE_BINDING_2D:
2191 case GL_TEXTURE_BINDING_CUBE_MAP:
2192 case GL_TEXTURE_BINDING_3D:
2193 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002194 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002195 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002196 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002197 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002198 {
2199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2200 return false;
2201 }
2202 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002203 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2204 if (!context->getExtensions().textureRectangle)
2205 {
2206 context->handleError(InvalidEnum()
2207 << "ANGLE_texture_rectangle extension not present");
2208 return false;
2209 }
2210 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2212 if (!context->getExtensions().eglStreamConsumerExternal &&
2213 !context->getExtensions().eglImageExternal)
2214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2216 "nor GL_OES_EGL_image_external "
2217 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002218 return false;
2219 }
2220 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002221
He Yunchaoced53ae2016-11-29 15:00:51 +08002222 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2223 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002224 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002225 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2226 ASSERT(readFramebuffer);
2227
Jamie Madill427064d2018-04-13 16:20:34 -04002228 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002229 {
Geoff Langb1196682014-07-23 13:47:29 -04002230 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002231 }
2232
Jamie Madille98b1b52018-03-08 09:47:23 -05002233 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002236 return false;
2237 }
2238
Jamie Madille98b1b52018-03-08 09:47:23 -05002239 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002240 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002242 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002243 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002244 }
2245 }
2246 break;
2247
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 default:
2249 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002250 }
2251
2252 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002253 if (*numParams == 0)
2254 {
2255 return false;
2256 }
2257
2258 return true;
2259}
2260
Brandon Jonesd1049182018-03-28 10:02:20 -07002261bool ValidateGetBooleanvRobustANGLE(Context *context,
2262 GLenum pname,
2263 GLsizei bufSize,
2264 GLsizei *length,
2265 GLboolean *params)
2266{
2267 GLenum nativeType;
2268 unsigned int numParams = 0;
2269
2270 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2271 {
2272 return false;
2273 }
2274
2275 SetRobustLengthParam(length, numParams);
2276
2277 return true;
2278}
2279
2280bool ValidateGetFloatvRobustANGLE(Context *context,
2281 GLenum pname,
2282 GLsizei bufSize,
2283 GLsizei *length,
2284 GLfloat *params)
2285{
2286 GLenum nativeType;
2287 unsigned int numParams = 0;
2288
2289 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2290 {
2291 return false;
2292 }
2293
2294 SetRobustLengthParam(length, numParams);
2295
2296 return true;
2297}
2298
2299bool ValidateGetIntegervRobustANGLE(Context *context,
2300 GLenum pname,
2301 GLsizei bufSize,
2302 GLsizei *length,
2303 GLint *data)
2304{
2305 GLenum nativeType;
2306 unsigned int numParams = 0;
2307
2308 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2309 {
2310 return false;
2311 }
2312
2313 SetRobustLengthParam(length, numParams);
2314
2315 return true;
2316}
2317
2318bool ValidateGetInteger64vRobustANGLE(Context *context,
2319 GLenum pname,
2320 GLsizei bufSize,
2321 GLsizei *length,
2322 GLint64 *data)
2323{
2324 GLenum nativeType;
2325 unsigned int numParams = 0;
2326
2327 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2328 {
2329 return false;
2330 }
2331
2332 if (nativeType == GL_INT_64_ANGLEX)
2333 {
2334 CastStateValues(context, nativeType, pname, numParams, data);
2335 return false;
2336 }
2337
2338 SetRobustLengthParam(length, numParams);
2339 return true;
2340}
2341
Jamie Madill5b772312018-03-08 20:28:32 -05002342bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002343 GLenum pname,
2344 GLsizei bufSize,
2345 GLenum *nativeType,
2346 unsigned int *numParams)
2347{
2348 if (!ValidateRobustEntryPoint(context, bufSize))
2349 {
2350 return false;
2351 }
2352
2353 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2354 {
2355 return false;
2356 }
2357
2358 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002359 {
2360 return false;
2361 }
2362
2363 return true;
2364}
2365
Jamie Madill5b772312018-03-08 20:28:32 -05002366bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002367 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002368 GLint level,
2369 GLenum internalformat,
2370 bool isSubImage,
2371 GLint xoffset,
2372 GLint yoffset,
2373 GLint zoffset,
2374 GLint x,
2375 GLint y,
2376 GLsizei width,
2377 GLsizei height,
2378 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002379 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002380{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002381 TextureType texType = TextureTargetToType(target);
2382
Brandon Jones6cad5662017-06-14 13:25:13 -07002383 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002385 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2386 return false;
2387 }
2388
2389 if (width < 0 || height < 0)
2390 {
2391 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002392 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 }
2394
He Yunchaoced53ae2016-11-29 15:00:51 +08002395 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2396 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
2402 if (border != 0)
2403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 }
2407
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002408 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002409 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002410 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002411 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002412 }
2413
Jamie Madill43da7c42018-08-01 11:34:49 -04002414 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002415 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002416 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 {
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002419 }
2420
Jamie Madille98b1b52018-03-08 09:47:23 -05002421 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002422 {
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
Martin Radev138064f2016-07-15 12:03:41 +03002426 if (readFramebuffer->getReadBufferState() == GL_NONE)
2427 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002429 return false;
2430 }
2431
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002432 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2433 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002434 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002435 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002436 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2437 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002440 return false;
2441 }
2442
Martin Radev04e2c3b2017-07-27 16:54:35 +03002443 // ANGLE_multiview spec, Revision 1:
2444 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2445 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002446 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2447 // framebuffer is more than one.
2448 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002449 {
2450 context->handleError(InvalidFramebufferOperation()
2451 << "The active read framebuffer object has multiview attachments.");
2452 return false;
2453 }
2454
Jamie Madill43da7c42018-08-01 11:34:49 -04002455 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002456
Geoff Langaae65a42014-05-26 12:43:44 -04002457 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002458 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002460 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002461 maxDimension = caps.max2DTextureSize;
2462 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002463
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002464 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002465 maxDimension = caps.maxCubeMapTextureSize;
2466 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002467
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002468 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002469 maxDimension = caps.maxRectangleTextureSize;
2470 break;
2471
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002472 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002473 maxDimension = caps.max2DTextureSize;
2474 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002475
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002476 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002477 maxDimension = caps.max3DTextureSize;
2478 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002479
He Yunchaoced53ae2016-11-29 15:00:51 +08002480 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002483 }
2484
Jamie Madill43da7c42018-08-01 11:34:49 -04002485 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002486 if (!texture)
2487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Geoff Lang69cce582015-09-17 13:20:36 -04002492 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002494 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496 }
2497
Jamie Madill43da7c42018-08-01 11:34:49 -04002498 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002499 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002500 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002501
Geoff Lang966c9402017-04-18 12:38:27 -04002502 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002505 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 }
2507
2508 if (isSubImage)
2509 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002510 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2511 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2512 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002514 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 }
2517 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002518 else
2519 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002520 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002524 }
2525
Geoff Langeb66a6e2016-10-31 13:06:12 -04002526 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002529 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002530 }
2531
2532 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002533 if (static_cast<int>(width) > maxLevelDimension ||
2534 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 }
2539 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002540
Jamie Madill0c8abca2016-07-22 20:21:26 -04002541 if (textureFormatOut)
2542 {
2543 *textureFormatOut = texture->getFormat(target, level);
2544 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002545
2546 // Detect texture copying feedback loops for WebGL.
2547 if (context->getExtensions().webglCompatibility)
2548 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002549 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002550 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002552 return false;
2553 }
2554 }
2555
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 return true;
2557}
2558
Jamie Madillb42162f2018-08-20 12:58:37 -04002559// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2560// completeness check.
2561const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002562{
2563 const Extensions &extensions = context->getExtensions();
2564 const State &state = context->getGLState();
2565
2566 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2567 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2568 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2569 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
2570 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002571 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002572 }
2573
2574 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2575 // Section 6.10 of the WebGL 1.0 spec.
2576 Framebuffer *framebuffer = state.getDrawFramebuffer();
2577 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2578 {
2579 ASSERT(framebuffer);
2580 const FramebufferAttachment *dsAttachment =
2581 framebuffer->getStencilOrDepthStencilAttachment();
2582 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2583 ASSERT(stencilBits <= 8);
2584
2585 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2586 if (depthStencilState.stencilTest && stencilBits > 0)
2587 {
2588 GLuint maxStencilValue = (1 << stencilBits) - 1;
2589
2590 bool differentRefs =
2591 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2592 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2593 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2594 (depthStencilState.stencilBackWritemask & maxStencilValue);
2595 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2596 (depthStencilState.stencilBackMask & maxStencilValue);
2597
2598 if (differentRefs || differentWritemasks || differentMasks)
2599 {
2600 if (!extensions.webglCompatibility)
2601 {
2602 WARN() << "This ANGLE implementation does not support separate front/back "
2603 "stencil writemasks, reference values, or stencil mask values.";
2604 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002605 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002606 }
2607 }
2608 }
2609
2610 if (!framebuffer->isComplete(context))
2611 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002612 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2613 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002614 }
2615
2616 if (context->getStateCache().hasAnyEnabledClientAttrib())
2617 {
2618 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2619 {
2620 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2621 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2622 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2623 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002624 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002625 }
2626
2627 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2628 {
2629 // This is an application error that would normally result in a crash, but we catch it
2630 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002631 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002632 }
2633 }
2634
2635 // If we are running GLES1, there is no current program.
2636 if (context->getClientVersion() >= Version(2, 0))
2637 {
2638 Program *program = state.getProgram();
2639 if (!program)
2640 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002641 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002642 }
2643
2644 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2645 // vertex shader stage or fragment shader stage is a undefined behaviour.
2646 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2647 // produce undefined result.
2648 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2649 !program->hasLinkedShaderStage(ShaderType::Fragment))
2650 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002651 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002652 }
2653
2654 if (!program->validateSamplers(nullptr, context->getCaps()))
2655 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002656 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002657 }
2658
2659 if (extensions.multiview)
2660 {
2661 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2662 const int framebufferNumViews = framebuffer->getNumViews();
2663 if (framebufferNumViews != programNumViews)
2664 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002665 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002666 }
2667
2668 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2669 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2670 framebufferNumViews > 1)
2671 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002672 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002673 }
2674
2675 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2676 state.isQueryActive(QueryType::TimeElapsed))
2677 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002678 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680 }
2681
2682 // Uniform buffer validation
2683 for (unsigned int uniformBlockIndex = 0;
2684 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2685 {
2686 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2687 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2688 const OffsetBindingPointer<Buffer> &uniformBuffer =
2689 state.getIndexedUniformBuffer(blockBinding);
2690
2691 if (uniformBuffer.get() == nullptr)
2692 {
2693 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002694 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002695 }
2696
2697 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2698 if (uniformBufferSize < uniformBlock.dataSize)
2699 {
2700 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002701 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002702 }
2703
2704 if (extensions.webglCompatibility &&
2705 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2706 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002707 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002708 }
2709 }
2710
2711 // Do some additonal WebGL-specific validation
2712 if (extensions.webglCompatibility)
2713 {
2714 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2715 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2716 transformFeedbackObject->buffersBoundForOtherUse())
2717 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002718 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002719 }
2720
2721 // Detect rendering feedback loops for WebGL.
2722 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2723 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002724 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002725 }
2726
2727 // Detect that the vertex shader input types match the attribute types
2728 if (!ValidateVertexShaderAttributeTypeMatch(context))
2729 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002730 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002731 }
2732
2733 // Detect that the color buffer types match the fragment shader output types
2734 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2735 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002736 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002737 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002738
2739 const VertexArray *vao = context->getGLState().getVertexArray();
2740 if (vao->hasTransformFeedbackBindingConflict(context))
2741 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002742 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002743 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002744 }
2745 }
2746
Jamie Madillb42162f2018-08-20 12:58:37 -04002747 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002748}
2749
Jamie Madill493f9572018-05-24 19:52:15 -04002750bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002751{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002752 const Extensions &extensions = context->getExtensions();
2753
Jamie Madill1aeb1312014-06-20 13:21:25 -04002754 switch (mode)
2755 {
Jamie Madill493f9572018-05-24 19:52:15 -04002756 case PrimitiveMode::Points:
2757 case PrimitiveMode::Lines:
2758 case PrimitiveMode::LineLoop:
2759 case PrimitiveMode::LineStrip:
2760 case PrimitiveMode::Triangles:
2761 case PrimitiveMode::TriangleStrip:
2762 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002763 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002764
Jamie Madill493f9572018-05-24 19:52:15 -04002765 case PrimitiveMode::LinesAdjacency:
2766 case PrimitiveMode::LineStripAdjacency:
2767 case PrimitiveMode::TrianglesAdjacency:
2768 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002769 if (!extensions.geometryShader)
2770 {
2771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2772 return false;
2773 }
2774 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002775 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002778 }
2779
Jamie Madill250d33f2014-06-06 17:09:03 -04002780 if (count < 0)
2781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002782 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002783 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002784 }
2785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002786 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002787
Jamie Madillb42162f2018-08-20 12:58:37 -04002788 const char *errorMessage = ValidateDrawStates(context);
2789 if (errorMessage)
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002791 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2792 // Incomplete.
2793 GLenum errorCode =
2794 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2795 : GL_INVALID_OPERATION);
2796 context->handleError(Error(errorCode, errorMessage));
Jamie Madille7d80f32018-08-08 15:49:23 -04002797 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002798 }
2799
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002800 // If we are running GLES1, there is no current program.
2801 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002802 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002803 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002804 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002805
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002806 // Do geometry shader specific validations
2807 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002808 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002809 if (!IsCompatibleDrawModeWithGeometryShader(
2810 mode, program->getGeometryShaderInputPrimitiveType()))
2811 {
2812 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2813 IncompatibleDrawModeAgainstGeometryShader);
2814 return false;
2815 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002816 }
2817 }
2818
Jamie Madill9fdaa492018-02-16 10:52:11 -05002819 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002820}
2821
Jamie Madill5b772312018-03-08 20:28:32 -05002822bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002823 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002824 GLint first,
2825 GLsizei count,
2826 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002827{
Jamie Madillfd716582014-06-06 17:09:04 -04002828 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002830 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002831 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002832 }
2833
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002834 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002835 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002836 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002837 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002838 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002839 if (!ValidateTransformFeedbackPrimitiveMode(context,
2840 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002841 {
James Darpinian30b604d2018-03-12 17:26:57 -07002842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2843 return false;
2844 }
2845
2846 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2847 {
2848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2849 return false;
2850 }
Jamie Madillfd716582014-06-06 17:09:04 -04002851 }
2852
Jiajia Qind9671222016-11-29 16:30:31 +08002853 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002854 {
2855 return false;
2856 }
2857
Corentin Wallez71168a02016-12-19 15:11:18 -08002858 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002859 // - first < 0 has been checked as an error condition.
2860 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002861 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002862 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002863 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002864 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002865 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2866 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2867 {
2868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2869 return false;
2870 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002871
Jamie Madill2da53562018-08-01 11:34:47 -04002872 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002873 {
2874 return false;
2875 }
Jamie Madillfd716582014-06-06 17:09:04 -04002876 }
2877
2878 return true;
2879}
2880
He Yunchaoced53ae2016-11-29 15:00:51 +08002881bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002882 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002883 GLint first,
2884 GLsizei count,
2885 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002886{
Geoff Lang63c5a592017-09-27 14:08:16 -04002887 if (!context->getExtensions().instancedArrays)
2888 {
2889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2890 return false;
2891 }
2892
Corentin Wallez170efbf2017-05-02 13:45:01 -04002893 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002894 {
2895 return false;
2896 }
2897
Corentin Wallez0dc97812017-06-22 14:38:44 -04002898 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002899}
2900
Jamie Madill493f9572018-05-24 19:52:15 -04002901bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002902{
Jamie Madill250d33f2014-06-06 17:09:03 -04002903 switch (type)
2904 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002905 case GL_UNSIGNED_BYTE:
2906 case GL_UNSIGNED_SHORT:
2907 break;
2908 case GL_UNSIGNED_INT:
2909 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002912 return false;
2913 }
2914 break;
2915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002917 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 }
2919
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002920 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002921
Jamie Madill43da7c42018-08-01 11:34:49 -04002922 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002923 if (curTransformFeedback && curTransformFeedback->isActive() &&
2924 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002925 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002926 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2927 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2928 if (context->getExtensions().geometryShader)
2929 {
2930 if (!ValidateTransformFeedbackPrimitiveMode(
2931 context, curTransformFeedback->getPrimitiveMode(), mode))
2932 {
2933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2934 return false;
2935 }
2936 }
2937 else
2938 {
2939 // It is an invalid operation to call DrawElements, DrawRangeElements or
2940 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2941 // 86)
2942 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2943 UnsupportedDrawModeForTransformFeedback);
2944 return false;
2945 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002946 }
2947
Jiajia Qind9671222016-11-29 16:30:31 +08002948 return true;
2949}
2950
Jamie Madill5b772312018-03-08 20:28:32 -05002951bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002952 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002953 GLsizei count,
2954 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002955 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002956 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002957{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002958 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002959 return false;
2960
2961 const State &state = context->getGLState();
2962
Corentin Wallez170efbf2017-05-02 13:45:01 -04002963 if (!ValidateDrawBase(context, mode, count))
2964 {
2965 return false;
2966 }
2967
Jamie Madill43da7c42018-08-01 11:34:49 -04002968 const VertexArray *vao = state.getVertexArray();
2969 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002970
Jamie Madill43da7c42018-08-01 11:34:49 -04002971 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002972
2973 if (context->getExtensions().webglCompatibility)
2974 {
2975 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2976 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2977 {
2978 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2979 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2980 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002982 return false;
2983 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002984
2985 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2986 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2987 // error is generated.
2988 if (reinterpret_cast<intptr_t>(indices) < 0)
2989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002990 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002991 return false;
2992 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002993 }
Jamie Madillcc73f242018-08-01 11:34:48 -04002994 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
2995 {
2996 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2997 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2998 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2999 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3000 return false;
3001 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003002
3003 if (context->getExtensions().webglCompatibility ||
3004 !context->getGLState().areClientArraysEnabled())
3005 {
Brandon Jones2a018152018-06-08 15:59:26 -07003006 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003007 {
3008 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003009 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3010 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003012 return false;
3013 }
3014 }
3015
Jamie Madill9fdaa492018-02-16 10:52:11 -05003016 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003017 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003018 // This is an application error that would normally result in a crash, but we catch it and
3019 // return an error
3020 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3021 return false;
3022 }
3023
3024 if (count > 0 && elementArrayBuffer)
3025 {
3026 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3027 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3028 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3029 constexpr uint64_t kMaxTypeSize = 8;
3030 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3031 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3032 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3033
3034 uint64_t typeSize = typeBytes;
3035 uint64_t elementCount = static_cast<uint64_t>(count);
3036 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3037
3038 // Doing the multiplication here is overflow-safe
3039 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3040
3041 // The offset can be any value, check for overflows
3042 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3043 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003044 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3046 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003047 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003048
3049 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3050 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003051 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3053 return false;
3054 }
3055
3056 ASSERT(isPow2(typeSize) && typeSize > 0);
3057 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3058 {
3059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003061 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003062
3063 if (context->getExtensions().webglCompatibility &&
3064 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3065 {
3066 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3067 ElementArrayBufferBoundForTransformFeedback);
3068 return false;
3069 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003070 }
3071
Jamie Madill2da53562018-08-01 11:34:47 -04003072 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003073 {
3074 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003075 const DrawCallParams &params = context->getParams<DrawCallParams>();
3076 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3077 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003078
3079 // If we use an index greater than our maximum supported index range, return an error.
3080 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3081 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003082 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083 {
3084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3085 return false;
3086 }
3087
Jamie Madill2da53562018-08-01 11:34:47 -04003088 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003089 {
3090 return false;
3091 }
3092
3093 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003094 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003095 }
3096
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003097 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003098}
3099
Jamie Madill5b772312018-03-08 20:28:32 -05003100bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003101 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003102 GLsizei count,
3103 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003104 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003105 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003106{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003107 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003108}
3109
Geoff Lang3edfe032015-09-04 16:38:24 -04003110bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003111 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003112 GLsizei count,
3113 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003114 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003115 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003116{
Geoff Lang63c5a592017-09-27 14:08:16 -04003117 if (!context->getExtensions().instancedArrays)
3118 {
3119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3120 return false;
3121 }
3122
Corentin Wallez170efbf2017-05-02 13:45:01 -04003123 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003124 {
3125 return false;
3126 }
3127
Corentin Wallez0dc97812017-06-22 14:38:44 -04003128 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003129}
3130
He Yunchaoced53ae2016-11-29 15:00:51 +08003131bool ValidateFramebufferTextureBase(Context *context,
3132 GLenum target,
3133 GLenum attachment,
3134 GLuint texture,
3135 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003136{
Geoff Lange8afa902017-09-27 15:00:43 -04003137 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003140 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003141 }
3142
3143 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003144 {
3145 return false;
3146 }
3147
Jamie Madill55ec3b12014-07-03 10:38:57 -04003148 if (texture != 0)
3149 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003150 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003151
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003152 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003154 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003156 }
3157
3158 if (level < 0)
3159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003160 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003161 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 }
3163 }
3164
Jamie Madill43da7c42018-08-01 11:34:49 -04003165 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003166 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167
Jamie Madill84115c92015-04-23 15:00:07 -04003168 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003172 }
3173
3174 return true;
3175}
3176
Geoff Langb1196682014-07-23 13:47:29 -04003177bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003178{
3179 if (program == 0)
3180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003181 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003183 }
3184
Jamie Madill43da7c42018-08-01 11:34:49 -04003185 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003186 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003187 {
3188 return false;
3189 }
3190
Jamie Madill0063c512014-08-25 15:47:53 -04003191 if (!programObject || !programObject->isLinked())
3192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003195 }
3196
Geoff Lang7dd2e102014-11-10 15:19:26 -05003197 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003199 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003200 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003201 }
3202
Jamie Madill0063c512014-08-25 15:47:53 -04003203 return true;
3204}
3205
Geoff Langf41d0ee2016-10-07 13:04:23 -04003206static bool ValidateSizedGetUniform(Context *context,
3207 GLuint program,
3208 GLint location,
3209 GLsizei bufSize,
3210 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003211{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003212 if (length)
3213 {
3214 *length = 0;
3215 }
3216
Jamie Madill78f41802014-08-25 15:47:55 -04003217 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003218 {
Jamie Madill78f41802014-08-25 15:47:55 -04003219 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003220 }
3221
Geoff Langf41d0ee2016-10-07 13:04:23 -04003222 if (bufSize < 0)
3223 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003224 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003225 return false;
3226 }
3227
Jamie Madill43da7c42018-08-01 11:34:49 -04003228 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003229 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003230
Jamie Madill78f41802014-08-25 15:47:55 -04003231 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003232 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003233 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003234 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003235 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003238 }
3239
Geoff Langf41d0ee2016-10-07 13:04:23 -04003240 if (length)
3241 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003242 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003243 }
3244
Jamie Madill0063c512014-08-25 15:47:53 -04003245 return true;
3246}
3247
He Yunchaoced53ae2016-11-29 15:00:51 +08003248bool ValidateGetnUniformfvEXT(Context *context,
3249 GLuint program,
3250 GLint location,
3251 GLsizei bufSize,
3252 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003253{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003255}
3256
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003257bool ValidateGetnUniformfvRobustANGLE(Context *context,
3258 GLuint program,
3259 GLint location,
3260 GLsizei bufSize,
3261 GLsizei *length,
3262 GLfloat *params)
3263{
3264 UNIMPLEMENTED();
3265 return false;
3266}
3267
He Yunchaoced53ae2016-11-29 15:00:51 +08003268bool ValidateGetnUniformivEXT(Context *context,
3269 GLuint program,
3270 GLint location,
3271 GLsizei bufSize,
3272 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003273{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003274 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3275}
3276
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003277bool ValidateGetnUniformivRobustANGLE(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLsizei *length,
3282 GLint *params)
3283{
3284 UNIMPLEMENTED();
3285 return false;
3286}
3287
3288bool ValidateGetnUniformuivRobustANGLE(Context *context,
3289 GLuint program,
3290 GLint location,
3291 GLsizei bufSize,
3292 GLsizei *length,
3293 GLuint *params)
3294{
3295 UNIMPLEMENTED();
3296 return false;
3297}
3298
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299bool ValidateGetUniformfvRobustANGLE(Context *context,
3300 GLuint program,
3301 GLint location,
3302 GLsizei bufSize,
3303 GLsizei *length,
3304 GLfloat *params)
3305{
3306 if (!ValidateRobustEntryPoint(context, bufSize))
3307 {
3308 return false;
3309 }
3310
Brandon Jonesd1049182018-03-28 10:02:20 -07003311 GLsizei writeLength = 0;
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003314 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3315 {
3316 return false;
3317 }
3318
3319 SetRobustLengthParam(length, writeLength);
3320
3321 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322}
3323
3324bool ValidateGetUniformivRobustANGLE(Context *context,
3325 GLuint program,
3326 GLint location,
3327 GLsizei bufSize,
3328 GLsizei *length,
3329 GLint *params)
3330{
3331 if (!ValidateRobustEntryPoint(context, bufSize))
3332 {
3333 return false;
3334 }
3335
Brandon Jonesd1049182018-03-28 10:02:20 -07003336 GLsizei writeLength = 0;
3337
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003339 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3340 {
3341 return false;
3342 }
3343
3344 SetRobustLengthParam(length, writeLength);
3345
3346 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003347}
3348
3349bool ValidateGetUniformuivRobustANGLE(Context *context,
3350 GLuint program,
3351 GLint location,
3352 GLsizei bufSize,
3353 GLsizei *length,
3354 GLuint *params)
3355{
3356 if (!ValidateRobustEntryPoint(context, bufSize))
3357 {
3358 return false;
3359 }
3360
3361 if (context->getClientMajorVersion() < 3)
3362 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003363 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003364 return false;
3365 }
3366
Brandon Jonesd1049182018-03-28 10:02:20 -07003367 GLsizei writeLength = 0;
3368
Geoff Langf41d0ee2016-10-07 13:04:23 -04003369 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003370 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3371 {
3372 return false;
3373 }
3374
3375 SetRobustLengthParam(length, writeLength);
3376
3377 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003378}
3379
He Yunchaoced53ae2016-11-29 15:00:51 +08003380bool ValidateDiscardFramebufferBase(Context *context,
3381 GLenum target,
3382 GLsizei numAttachments,
3383 const GLenum *attachments,
3384 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003385{
3386 if (numAttachments < 0)
3387 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003388 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003389 return false;
3390 }
3391
3392 for (GLsizei i = 0; i < numAttachments; ++i)
3393 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003394 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003395 {
3396 if (defaultFramebuffer)
3397 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003399 return false;
3400 }
3401
3402 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003404 context->handleError(InvalidOperation() << "Requested color attachment is "
3405 "greater than the maximum supported "
3406 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003407 return false;
3408 }
3409 }
3410 else
3411 {
3412 switch (attachments[i])
3413 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003414 case GL_DEPTH_ATTACHMENT:
3415 case GL_STENCIL_ATTACHMENT:
3416 case GL_DEPTH_STENCIL_ATTACHMENT:
3417 if (defaultFramebuffer)
3418 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003419 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3420 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003421 return false;
3422 }
3423 break;
3424 case GL_COLOR:
3425 case GL_DEPTH:
3426 case GL_STENCIL:
3427 if (!defaultFramebuffer)
3428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003429 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3430 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003431 return false;
3432 }
3433 break;
3434 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003436 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003437 }
3438 }
3439 }
3440
3441 return true;
3442}
3443
Austin Kinross6ee1e782015-05-29 17:05:37 -07003444bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3445{
Jamie Madill007530e2017-12-28 14:27:04 -05003446 if (!context->getExtensions().debugMarker)
3447 {
3448 // The debug marker calls should not set error state
3449 // However, it seems reasonable to set an error state if the extension is not enabled
3450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3451 return false;
3452 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003453
Jamie Madill007530e2017-12-28 14:27:04 -05003454 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003455 if (length < 0)
3456 {
3457 return false;
3458 }
3459
3460 if (marker == nullptr)
3461 {
3462 return false;
3463 }
3464
3465 return true;
3466}
3467
3468bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3469{
Jamie Madill007530e2017-12-28 14:27:04 -05003470 if (!context->getExtensions().debugMarker)
3471 {
3472 // The debug marker calls should not set error state
3473 // However, it seems reasonable to set an error state if the extension is not enabled
3474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3475 return false;
3476 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003477
Jamie Madill007530e2017-12-28 14:27:04 -05003478 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003479 if (length < 0)
3480 {
3481 return false;
3482 }
3483
3484 if (length > 0 && marker == nullptr)
3485 {
3486 return false;
3487 }
3488
3489 return true;
3490}
3491
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003492bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003493{
Geoff Langa8406172015-07-21 16:53:39 -04003494 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003497 return false;
3498 }
3499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003500 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003501 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003502 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003503 if (!context->getExtensions().eglImage)
3504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidEnum()
3506 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003507 }
3508 break;
3509
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003510 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003511 if (!context->getExtensions().eglImageExternal)
3512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3514 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003515 }
Geoff Langa8406172015-07-21 16:53:39 -04003516 break;
3517
3518 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003520 return false;
3521 }
3522
Rafael Cintron05a449a2018-06-20 18:08:04 -07003523 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003524
Jamie Madill61e16b42017-06-19 11:13:23 -04003525 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003526 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003528 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003529 return false;
3530 }
3531
Jamie Madill007530e2017-12-28 14:27:04 -05003532 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 context->handleError(InvalidOperation()
3535 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003536 return false;
3537 }
3538
Geoff Langca271392017-04-05 12:30:00 -04003539 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003540 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003541 if (!textureCaps.texturable)
3542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidOperation()
3544 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003545 return false;
3546 }
3547
Geoff Langdcab33b2015-07-21 13:03:16 -04003548 return true;
3549}
3550
3551bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003552 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003553 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003554{
Geoff Langa8406172015-07-21 16:53:39 -04003555 if (!context->getExtensions().eglImage)
3556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003558 return false;
3559 }
3560
3561 switch (target)
3562 {
3563 case GL_RENDERBUFFER:
3564 break;
3565
3566 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003568 return false;
3569 }
3570
Rafael Cintron05a449a2018-06-20 18:08:04 -07003571 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003572
Jamie Madill61e16b42017-06-19 11:13:23 -04003573 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003574 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003577 return false;
3578 }
3579
Geoff Langca271392017-04-05 12:30:00 -04003580 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003581 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003582 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidOperation()
3585 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003586 return false;
3587 }
3588
Geoff Langdcab33b2015-07-21 13:03:16 -04003589 return true;
3590}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003591
3592bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3593{
Geoff Lang36167ab2015-12-07 10:27:14 -05003594 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003595 {
3596 // The default VAO should always exist
3597 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003599 return false;
3600 }
3601
3602 return true;
3603}
3604
Geoff Langc5629752015-12-07 16:29:04 -05003605bool ValidateProgramBinaryBase(Context *context,
3606 GLuint program,
3607 GLenum binaryFormat,
3608 const void *binary,
3609 GLint length)
3610{
3611 Program *programObject = GetValidProgram(context, program);
3612 if (programObject == nullptr)
3613 {
3614 return false;
3615 }
3616
3617 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3618 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3619 programBinaryFormats.end())
3620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003622 return false;
3623 }
3624
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003625 if (context->hasActiveTransformFeedback(program))
3626 {
3627 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3629 "is associated with an active transform "
3630 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003631 return false;
3632 }
3633
Geoff Langc5629752015-12-07 16:29:04 -05003634 return true;
3635}
3636
3637bool ValidateGetProgramBinaryBase(Context *context,
3638 GLuint program,
3639 GLsizei bufSize,
3640 GLsizei *length,
3641 GLenum *binaryFormat,
3642 void *binary)
3643{
3644 Program *programObject = GetValidProgram(context, program);
3645 if (programObject == nullptr)
3646 {
3647 return false;
3648 }
3649
3650 if (!programObject->isLinked())
3651 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003653 return false;
3654 }
3655
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003656 if (context->getCaps().programBinaryFormats.empty())
3657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003659 return false;
3660 }
3661
Geoff Langc5629752015-12-07 16:29:04 -05003662 return true;
3663}
Jamie Madillc29968b2016-01-20 11:17:23 -05003664
Jamie Madill5b772312018-03-08 20:28:32 -05003665bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003666{
3667 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003668 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3671 return false;
3672 }
3673 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3674 {
3675 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003676 return false;
3677 }
3678
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003679 ASSERT(context->getGLState().getDrawFramebuffer());
3680 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3682
3683 // This should come first before the check for the default frame buffer
3684 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3685 // rather than INVALID_OPERATION
3686 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3687 {
3688 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3689
3690 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003691 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3692 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003693 {
3694 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003695 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3696 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3697 // 3.1 is still a bit ambiguous about the error, but future specs are
3698 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003700 return false;
3701 }
3702 else if (bufs[colorAttachment] >= maxColorAttachment)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidOperation()
3705 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003706 return false;
3707 }
3708 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3709 frameBufferId != 0)
3710 {
3711 // INVALID_OPERATION-GL is bound to buffer and ith argument
3712 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation()
3714 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003715 return false;
3716 }
3717 }
3718
3719 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3720 // and n is not 1 or bufs is bound to value other than BACK and NONE
3721 if (frameBufferId == 0)
3722 {
3723 if (n != 1)
3724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidOperation()
3726 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003727 return false;
3728 }
3729
3730 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003732 context->handleError(
3733 InvalidOperation()
3734 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003735 return false;
3736 }
3737 }
3738
3739 return true;
3740}
3741
Geoff Lang496c02d2016-10-20 11:38:11 -07003742bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003743 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003744 GLenum pname,
3745 GLsizei *length,
3746 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003747{
Geoff Lang496c02d2016-10-20 11:38:11 -07003748 if (length)
3749 {
3750 *length = 0;
3751 }
3752
3753 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3754 {
3755 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003756 InvalidOperation()
3757 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003758 return false;
3759 }
3760
Corentin Walleze4477002017-12-01 14:39:58 -05003761 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003762 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003763 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003764 return false;
3765 }
3766
Geoff Lang496c02d2016-10-20 11:38:11 -07003767 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003768 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003769 case GL_BUFFER_MAP_POINTER:
3770 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003771
Geoff Lang496c02d2016-10-20 11:38:11 -07003772 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003774 return false;
3775 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003776
3777 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3778 // target bound to zero generate an INVALID_OPERATION error."
3779 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidOperation()
3783 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 return false;
3785 }
3786
Geoff Lang496c02d2016-10-20 11:38:11 -07003787 if (length)
3788 {
3789 *length = 1;
3790 }
3791
Olli Etuaho4f667482016-03-30 15:56:35 +03003792 return true;
3793}
3794
Corentin Wallez336129f2017-10-17 15:55:40 -04003795bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003796{
Corentin Walleze4477002017-12-01 14:39:58 -05003797 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 return false;
3801 }
3802
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003803 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003804
3805 if (buffer == nullptr || !buffer->isMapped())
3806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003807 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 return false;
3809 }
3810
3811 return true;
3812}
3813
3814bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003815 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003816 GLintptr offset,
3817 GLsizeiptr length,
3818 GLbitfield access)
3819{
Corentin Walleze4477002017-12-01 14:39:58 -05003820 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 return false;
3824 }
3825
Brandon Jones6cad5662017-06-14 13:25:13 -07003826 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003828 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3829 return false;
3830 }
3831
3832 if (length < 0)
3833 {
3834 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 return false;
3836 }
3837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003838 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003839
3840 if (!buffer)
3841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003842 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 return false;
3844 }
3845
3846 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003847 CheckedNumeric<size_t> checkedOffset(offset);
3848 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003849
Jamie Madille2e406c2016-06-02 13:04:10 -04003850 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003852 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 return false;
3854 }
3855
3856 // Check for invalid bits in the mask
3857 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3858 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3859 GL_MAP_UNSYNCHRONIZED_BIT;
3860
3861 if (access & ~(allAccessBits))
3862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003863 context->handleError(InvalidValue()
3864 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
3868 if (length == 0)
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
3874 if (buffer->isMapped())
3875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 return false;
3878 }
3879
3880 // Check for invalid bit combinations
3881 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidOperation()
3884 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
3888 GLbitfield writeOnlyBits =
3889 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3890
3891 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003893 context->handleError(InvalidOperation()
3894 << "Invalid access bits when mapping buffer for reading: 0x"
3895 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(
3902 InvalidOperation()
3903 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003904 return false;
3905 }
Geoff Lang79f71042017-08-14 16:43:43 -04003906
3907 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908}
3909
3910bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003911 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 GLintptr offset,
3913 GLsizeiptr length)
3914{
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003917 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3918 return false;
3919 }
3920
3921 if (length < 0)
3922 {
3923 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
Corentin Walleze4477002017-12-01 14:39:58 -05003927 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003929 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003930 return false;
3931 }
3932
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003933 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003934
3935 if (buffer == nullptr)
3936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003937 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 return false;
3939 }
3940
3941 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003943 context->handleError(InvalidOperation()
3944 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003945 return false;
3946 }
3947
3948 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003949 CheckedNumeric<size_t> checkedOffset(offset);
3950 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003951
Jamie Madille2e406c2016-06-02 13:04:10 -04003952 if (!checkedSize.IsValid() ||
3953 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003955 context->handleError(InvalidValue()
3956 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 return false;
3958 }
3959
3960 return true;
3961}
3962
Olli Etuaho41997e72016-03-10 13:38:39 +02003963bool ValidateGenOrDelete(Context *context, GLint n)
3964{
3965 if (n < 0)
3966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003968 return false;
3969 }
3970 return true;
3971}
3972
Jamie Madill5b772312018-03-08 20:28:32 -05003973bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003974{
3975 if (!context->getExtensions().robustClientMemory)
3976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003977 context->handleError(InvalidOperation()
3978 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003979 return false;
3980 }
3981
3982 if (bufSize < 0)
3983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003984 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 return false;
3986 }
3987
3988 return true;
3989}
3990
Jamie Madill5b772312018-03-08 20:28:32 -05003991bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003992{
3993 if (bufSize < numParams)
3994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003995 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3996 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003997 return false;
3998 }
3999
4000 return true;
4001}
4002
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004003bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004004 GLenum target,
4005 GLenum attachment,
4006 GLenum pname,
4007 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004008{
Geoff Lange8afa902017-09-27 15:00:43 -04004009 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004011 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return false;
4013 }
4014
4015 int clientVersion = context->getClientMajorVersion();
4016
4017 switch (pname)
4018 {
4019 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4020 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4021 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4022 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4023 break;
4024
Martin Radeve5285d22017-07-14 16:23:53 +03004025 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4026 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4027 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4028 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4029 if (clientVersion < 3 || !context->getExtensions().multiview)
4030 {
4031 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4032 return false;
4033 }
4034 break;
4035
Geoff Langff5b2d52016-09-07 11:32:23 -04004036 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4037 if (clientVersion < 3 && !context->getExtensions().sRGB)
4038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004039 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004040 return false;
4041 }
4042 break;
4043
4044 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4045 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4046 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4047 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4052 if (clientVersion < 3)
4053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004054 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 return false;
4056 }
4057 break;
4058
Jiawei Shaoa8802472018-05-28 11:17:47 +08004059 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4060 if (!context->getExtensions().geometryShader)
4061 {
4062 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4063 return false;
4064 }
4065 break;
4066
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004068 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 return false;
4070 }
4071
4072 // Determine if the attachment is a valid enum
4073 switch (attachment)
4074 {
4075 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 case GL_DEPTH:
4077 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 if (clientVersion < 3)
4079 {
Geoff Langfa125c92017-10-24 13:01:46 -04004080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 return false;
4082 }
4083 break;
4084
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004085 case GL_DEPTH_STENCIL_ATTACHMENT:
4086 if (clientVersion < 3 && !context->isWebGL1())
4087 {
4088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4089 return false;
4090 }
4091 break;
4092
Geoff Langfa125c92017-10-24 13:01:46 -04004093 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 case GL_DEPTH_ATTACHMENT:
4095 case GL_STENCIL_ATTACHMENT:
4096 break;
4097
4098 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004099 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4100 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4102 {
Geoff Langfa125c92017-10-24 13:01:46 -04004103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 return false;
4105 }
4106 break;
4107 }
4108
4109 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4110 ASSERT(framebuffer);
4111
4112 if (framebuffer->id() == 0)
4113 {
4114 if (clientVersion < 3)
4115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 return false;
4118 }
4119
4120 switch (attachment)
4121 {
4122 case GL_BACK:
4123 case GL_DEPTH:
4124 case GL_STENCIL:
4125 break;
4126
4127 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131 }
4132 else
4133 {
4134 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4135 {
4136 // Valid attachment query
4137 }
4138 else
4139 {
4140 switch (attachment)
4141 {
4142 case GL_DEPTH_ATTACHMENT:
4143 case GL_STENCIL_ATTACHMENT:
4144 break;
4145
4146 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004147 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004149 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 return false;
4151 }
4152 break;
4153
4154 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 return false;
4157 }
4158 }
4159 }
4160
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004161 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 if (attachmentObject)
4163 {
4164 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4165 attachmentObject->type() == GL_TEXTURE ||
4166 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4167
4168 switch (pname)
4169 {
4170 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4171 if (attachmentObject->type() != GL_RENDERBUFFER &&
4172 attachmentObject->type() != GL_TEXTURE)
4173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177 break;
4178
4179 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4180 if (attachmentObject->type() != GL_TEXTURE)
4181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004183 return false;
4184 }
4185 break;
4186
4187 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4188 if (attachmentObject->type() != GL_TEXTURE)
4189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4196 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4197 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 return false;
4200 }
4201 break;
4202
4203 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4204 if (attachmentObject->type() != GL_TEXTURE)
4205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004207 return false;
4208 }
4209 break;
4210
4211 default:
4212 break;
4213 }
4214 }
4215 else
4216 {
4217 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4218 // is NONE, then querying any other pname will generate INVALID_ENUM.
4219
4220 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4221 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4222 // INVALID_OPERATION for all other pnames
4223
4224 switch (pname)
4225 {
4226 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4227 break;
4228
4229 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4230 if (clientVersion < 3)
4231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004232 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004233 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004234 return false;
4235 }
4236 break;
4237
4238 default:
4239 if (clientVersion < 3)
4240 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004241 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004242 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004243 return false;
4244 }
4245 else
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004248 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 }
4252 }
4253
Martin Radeve5285d22017-07-14 16:23:53 +03004254 if (numParams)
4255 {
4256 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4257 {
4258 // Only when the viewport offsets are queried we can have a varying number of output
4259 // parameters.
4260 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4261 *numParams = numViews * 2;
4262 }
4263 else
4264 {
4265 // For all other queries we can have only one output parameter.
4266 *numParams = 1;
4267 }
4268 }
4269
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 return true;
4271}
4272
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004273bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 GLenum target,
4275 GLenum attachment,
4276 GLenum pname,
4277 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004278 GLsizei *length,
4279 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004280{
4281 if (!ValidateRobustEntryPoint(context, bufSize))
4282 {
4283 return false;
4284 }
4285
Brandon Jonesd1049182018-03-28 10:02:20 -07004286 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004287 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004288 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004289 {
4290 return false;
4291 }
4292
Brandon Jonesd1049182018-03-28 10:02:20 -07004293 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004294 {
4295 return false;
4296 }
4297
Brandon Jonesd1049182018-03-28 10:02:20 -07004298 SetRobustLengthParam(length, numParams);
4299
Geoff Langff5b2d52016-09-07 11:32:23 -04004300 return true;
4301}
4302
Jamie Madill5b772312018-03-08 20:28:32 -05004303bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004304 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004305 GLenum pname,
4306 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004307 GLsizei *length,
4308 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004309{
4310 if (!ValidateRobustEntryPoint(context, bufSize))
4311 {
4312 return false;
4313 }
4314
Brandon Jonesd1049182018-03-28 10:02:20 -07004315 GLsizei numParams = 0;
4316
4317 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004318 {
4319 return false;
4320 }
4321
Brandon Jonesd1049182018-03-28 10:02:20 -07004322 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004323 {
4324 return false;
4325 }
4326
Brandon Jonesd1049182018-03-28 10:02:20 -07004327 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004328 return true;
4329}
4330
Jamie Madill5b772312018-03-08 20:28:32 -05004331bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004332 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004333 GLenum pname,
4334 GLsizei bufSize,
4335 GLsizei *length,
4336 GLint64 *params)
4337{
Brandon Jonesd1049182018-03-28 10:02:20 -07004338 GLsizei numParams = 0;
4339
Geoff Langebebe1c2016-10-14 12:01:31 -04004340 if (!ValidateRobustEntryPoint(context, bufSize))
4341 {
4342 return false;
4343 }
4344
Brandon Jonesd1049182018-03-28 10:02:20 -07004345 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004346 {
4347 return false;
4348 }
4349
Brandon Jonesd1049182018-03-28 10:02:20 -07004350 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004351 {
4352 return false;
4353 }
4354
Brandon Jonesd1049182018-03-28 10:02:20 -07004355 SetRobustLengthParam(length, numParams);
4356
Geoff Langff5b2d52016-09-07 11:32:23 -04004357 return true;
4358}
4359
Jamie Madill5b772312018-03-08 20:28:32 -05004360bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004361{
4362 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004363 if (numParams)
4364 {
4365 *numParams = 1;
4366 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004367
4368 Program *programObject = GetValidProgram(context, program);
4369 if (!programObject)
4370 {
4371 return false;
4372 }
4373
4374 switch (pname)
4375 {
4376 case GL_DELETE_STATUS:
4377 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004378 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004379 case GL_VALIDATE_STATUS:
4380 case GL_INFO_LOG_LENGTH:
4381 case GL_ATTACHED_SHADERS:
4382 case GL_ACTIVE_ATTRIBUTES:
4383 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4384 case GL_ACTIVE_UNIFORMS:
4385 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4386 break;
4387
4388 case GL_PROGRAM_BINARY_LENGTH:
4389 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004391 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4392 "requires GL_OES_get_program_binary or "
4393 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004394 return false;
4395 }
4396 break;
4397
4398 case GL_ACTIVE_UNIFORM_BLOCKS:
4399 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4400 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4401 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4402 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4403 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4404 if (context->getClientMajorVersion() < 3)
4405 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004407 return false;
4408 }
4409 break;
4410
Yunchao He61afff12017-03-14 15:34:03 +08004411 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004412 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004413 if (context->getClientVersion() < Version(3, 1))
4414 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004416 return false;
4417 }
4418 break;
4419
Jiawei Shao6ae51612018-02-23 14:03:25 +08004420 case GL_COMPUTE_WORK_GROUP_SIZE:
4421 if (context->getClientVersion() < Version(3, 1))
4422 {
4423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4424 return false;
4425 }
4426
4427 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4428 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4429 // program which has not been linked successfully, or which does not contain objects to
4430 // form a compute shader.
4431 if (!programObject->isLinked())
4432 {
4433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4434 return false;
4435 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004436 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004437 {
4438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4439 return false;
4440 }
4441 break;
4442
Jiawei Shao447bfac2018-03-14 14:23:40 +08004443 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4444 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4445 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4446 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4447 if (!context->getExtensions().geometryShader)
4448 {
4449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4450 return false;
4451 }
4452
4453 // [EXT_geometry_shader] Chapter 7.12
4454 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4455 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4456 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4457 // successfully, or which does not contain objects to form a geometry shader.
4458 if (!programObject->isLinked())
4459 {
4460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4461 return false;
4462 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004463 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004464 {
4465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4466 return false;
4467 }
4468 break;
4469
Geoff Langff5b2d52016-09-07 11:32:23 -04004470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004472 return false;
4473 }
4474
4475 return true;
4476}
4477
4478bool ValidateGetProgramivRobustANGLE(Context *context,
4479 GLuint program,
4480 GLenum pname,
4481 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004482 GLsizei *length,
4483 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004484{
4485 if (!ValidateRobustEntryPoint(context, bufSize))
4486 {
4487 return false;
4488 }
4489
Brandon Jonesd1049182018-03-28 10:02:20 -07004490 GLsizei numParams = 0;
4491
4492 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004493 {
4494 return false;
4495 }
4496
Brandon Jonesd1049182018-03-28 10:02:20 -07004497 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004498 {
4499 return false;
4500 }
4501
Brandon Jonesd1049182018-03-28 10:02:20 -07004502 SetRobustLengthParam(length, numParams);
4503
Geoff Langff5b2d52016-09-07 11:32:23 -04004504 return true;
4505}
4506
Geoff Lang740d9022016-10-07 11:20:52 -04004507bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4508 GLenum target,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 GLsizei *length,
4512 GLint *params)
4513{
4514 if (!ValidateRobustEntryPoint(context, bufSize))
4515 {
4516 return false;
4517 }
4518
Brandon Jonesd1049182018-03-28 10:02:20 -07004519 GLsizei numParams = 0;
4520
4521 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004522 {
4523 return false;
4524 }
4525
Brandon Jonesd1049182018-03-28 10:02:20 -07004526 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004527 {
4528 return false;
4529 }
4530
Brandon Jonesd1049182018-03-28 10:02:20 -07004531 SetRobustLengthParam(length, numParams);
4532
Geoff Lang740d9022016-10-07 11:20:52 -04004533 return true;
4534}
4535
Geoff Langd7d0ed32016-10-07 11:33:51 -04004536bool ValidateGetShaderivRobustANGLE(Context *context,
4537 GLuint shader,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 GLsizei *length,
4541 GLint *params)
4542{
4543 if (!ValidateRobustEntryPoint(context, bufSize))
4544 {
4545 return false;
4546 }
4547
Brandon Jonesd1049182018-03-28 10:02:20 -07004548 GLsizei numParams = 0;
4549
4550 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004556 {
4557 return false;
4558 }
4559
Brandon Jonesd1049182018-03-28 10:02:20 -07004560 SetRobustLengthParam(length, numParams);
4561
Geoff Langd7d0ed32016-10-07 11:33:51 -04004562 return true;
4563}
4564
Geoff Langc1984ed2016-10-07 12:41:00 -04004565bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004566 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004567 GLenum pname,
4568 GLsizei bufSize,
4569 GLsizei *length,
4570 GLfloat *params)
4571{
4572 if (!ValidateRobustEntryPoint(context, bufSize))
4573 {
4574 return false;
4575 }
4576
Brandon Jonesd1049182018-03-28 10:02:20 -07004577 GLsizei numParams = 0;
4578
4579 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004580 {
4581 return false;
4582 }
4583
Brandon Jonesd1049182018-03-28 10:02:20 -07004584 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004585 {
4586 return false;
4587 }
4588
Brandon Jonesd1049182018-03-28 10:02:20 -07004589 SetRobustLengthParam(length, numParams);
4590
Geoff Langc1984ed2016-10-07 12:41:00 -04004591 return true;
4592}
4593
Geoff Langc1984ed2016-10-07 12:41:00 -04004594bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004595 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004596 GLenum pname,
4597 GLsizei bufSize,
4598 GLsizei *length,
4599 GLint *params)
4600{
Brandon Jonesd1049182018-03-28 10:02:20 -07004601
Geoff Langc1984ed2016-10-07 12:41:00 -04004602 if (!ValidateRobustEntryPoint(context, bufSize))
4603 {
4604 return false;
4605 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004606 GLsizei numParams = 0;
4607 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004618 return true;
4619}
4620
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004621bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4622 TextureType target,
4623 GLenum pname,
4624 GLsizei bufSize,
4625 GLsizei *length,
4626 GLint *params)
4627{
4628 UNIMPLEMENTED();
4629 return false;
4630}
4631
4632bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4633 TextureType target,
4634 GLenum pname,
4635 GLsizei bufSize,
4636 GLsizei *length,
4637 GLuint *params)
4638{
4639 UNIMPLEMENTED();
4640 return false;
4641}
4642
Geoff Langc1984ed2016-10-07 12:41:00 -04004643bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004644 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004645 GLenum pname,
4646 GLsizei bufSize,
4647 const GLfloat *params)
4648{
4649 if (!ValidateRobustEntryPoint(context, bufSize))
4650 {
4651 return false;
4652 }
4653
4654 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4655}
4656
Geoff Langc1984ed2016-10-07 12:41:00 -04004657bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004658 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004659 GLenum pname,
4660 GLsizei bufSize,
4661 const GLint *params)
4662{
4663 if (!ValidateRobustEntryPoint(context, bufSize))
4664 {
4665 return false;
4666 }
4667
4668 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4669}
4670
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004671bool ValidateTexParameterIivRobustANGLE(Context *context,
4672 TextureType target,
4673 GLenum pname,
4674 GLsizei bufSize,
4675 const GLint *params)
4676{
4677 UNIMPLEMENTED();
4678 return false;
4679}
4680
4681bool ValidateTexParameterIuivRobustANGLE(Context *context,
4682 TextureType target,
4683 GLenum pname,
4684 GLsizei bufSize,
4685 const GLuint *params)
4686{
4687 UNIMPLEMENTED();
4688 return false;
4689}
4690
Geoff Langc1984ed2016-10-07 12:41:00 -04004691bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4692 GLuint sampler,
4693 GLenum pname,
4694 GLuint bufSize,
4695 GLsizei *length,
4696 GLfloat *params)
4697{
4698 if (!ValidateRobustEntryPoint(context, bufSize))
4699 {
4700 return false;
4701 }
4702
Brandon Jonesd1049182018-03-28 10:02:20 -07004703 GLsizei numParams = 0;
4704
4705 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004706 {
4707 return false;
4708 }
4709
Brandon Jonesd1049182018-03-28 10:02:20 -07004710 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004711 {
4712 return false;
4713 }
4714
Brandon Jonesd1049182018-03-28 10:02:20 -07004715 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004716 return true;
4717}
4718
Geoff Langc1984ed2016-10-07 12:41:00 -04004719bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4720 GLuint sampler,
4721 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004722 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004723 GLsizei *length,
4724 GLint *params)
4725{
4726 if (!ValidateRobustEntryPoint(context, bufSize))
4727 {
4728 return false;
4729 }
4730
Brandon Jonesd1049182018-03-28 10:02:20 -07004731 GLsizei numParams = 0;
4732
4733 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004734 {
4735 return false;
4736 }
4737
Brandon Jonesd1049182018-03-28 10:02:20 -07004738 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004739 {
4740 return false;
4741 }
4742
Brandon Jonesd1049182018-03-28 10:02:20 -07004743 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004744 return true;
4745}
4746
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004747bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4748 GLuint sampler,
4749 GLenum pname,
4750 GLsizei bufSize,
4751 GLsizei *length,
4752 GLint *params)
4753{
4754 UNIMPLEMENTED();
4755 return false;
4756}
4757
4758bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4759 GLuint sampler,
4760 GLenum pname,
4761 GLsizei bufSize,
4762 GLsizei *length,
4763 GLuint *params)
4764{
4765 UNIMPLEMENTED();
4766 return false;
4767}
4768
Geoff Langc1984ed2016-10-07 12:41:00 -04004769bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4770 GLuint sampler,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 const GLfloat *params)
4774{
4775 if (!ValidateRobustEntryPoint(context, bufSize))
4776 {
4777 return false;
4778 }
4779
4780 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4781}
4782
Geoff Langc1984ed2016-10-07 12:41:00 -04004783bool ValidateSamplerParameterivRobustANGLE(Context *context,
4784 GLuint sampler,
4785 GLenum pname,
4786 GLsizei bufSize,
4787 const GLint *params)
4788{
4789 if (!ValidateRobustEntryPoint(context, bufSize))
4790 {
4791 return false;
4792 }
4793
4794 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4795}
4796
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004797bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4798 GLuint sampler,
4799 GLenum pname,
4800 GLsizei bufSize,
4801 const GLint *param)
4802{
4803 UNIMPLEMENTED();
4804 return false;
4805}
4806
4807bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4808 GLuint sampler,
4809 GLenum pname,
4810 GLsizei bufSize,
4811 const GLuint *param)
4812{
4813 UNIMPLEMENTED();
4814 return false;
4815}
4816
Geoff Lang0b031062016-10-13 14:30:04 -04004817bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4818 GLuint index,
4819 GLenum pname,
4820 GLsizei bufSize,
4821 GLsizei *length,
4822 GLfloat *params)
4823{
4824 if (!ValidateRobustEntryPoint(context, bufSize))
4825 {
4826 return false;
4827 }
4828
Brandon Jonesd1049182018-03-28 10:02:20 -07004829 GLsizei writeLength = 0;
4830
4831 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004832 {
4833 return false;
4834 }
4835
Brandon Jonesd1049182018-03-28 10:02:20 -07004836 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004837 {
4838 return false;
4839 }
4840
Brandon Jonesd1049182018-03-28 10:02:20 -07004841 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004842 return true;
4843}
4844
Geoff Lang0b031062016-10-13 14:30:04 -04004845bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4846 GLuint index,
4847 GLenum pname,
4848 GLsizei bufSize,
4849 GLsizei *length,
4850 GLint *params)
4851{
4852 if (!ValidateRobustEntryPoint(context, bufSize))
4853 {
4854 return false;
4855 }
4856
Brandon Jonesd1049182018-03-28 10:02:20 -07004857 GLsizei writeLength = 0;
4858
4859 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004860 {
4861 return false;
4862 }
4863
Brandon Jonesd1049182018-03-28 10:02:20 -07004864 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004865 {
4866 return false;
4867 }
4868
Brandon Jonesd1049182018-03-28 10:02:20 -07004869 SetRobustLengthParam(length, writeLength);
4870
Geoff Lang0b031062016-10-13 14:30:04 -04004871 return true;
4872}
4873
Geoff Lang0b031062016-10-13 14:30:04 -04004874bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4875 GLuint index,
4876 GLenum pname,
4877 GLsizei bufSize,
4878 GLsizei *length,
4879 void **pointer)
4880{
4881 if (!ValidateRobustEntryPoint(context, bufSize))
4882 {
4883 return false;
4884 }
4885
Brandon Jonesd1049182018-03-28 10:02:20 -07004886 GLsizei writeLength = 0;
4887
4888 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004889 {
4890 return false;
4891 }
4892
Brandon Jonesd1049182018-03-28 10:02:20 -07004893 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004894 {
4895 return false;
4896 }
4897
Brandon Jonesd1049182018-03-28 10:02:20 -07004898 SetRobustLengthParam(length, writeLength);
4899
Geoff Lang0b031062016-10-13 14:30:04 -04004900 return true;
4901}
4902
Geoff Lang0b031062016-10-13 14:30:04 -04004903bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4904 GLuint index,
4905 GLenum pname,
4906 GLsizei bufSize,
4907 GLsizei *length,
4908 GLint *params)
4909{
4910 if (!ValidateRobustEntryPoint(context, bufSize))
4911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 GLsizei writeLength = 0;
4916
4917 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004923 {
4924 return false;
4925 }
4926
Brandon Jonesd1049182018-03-28 10:02:20 -07004927 SetRobustLengthParam(length, writeLength);
4928
Geoff Lang0b031062016-10-13 14:30:04 -04004929 return true;
4930}
4931
Geoff Lang0b031062016-10-13 14:30:04 -04004932bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4933 GLuint index,
4934 GLenum pname,
4935 GLsizei bufSize,
4936 GLsizei *length,
4937 GLuint *params)
4938{
4939 if (!ValidateRobustEntryPoint(context, bufSize))
4940 {
4941 return false;
4942 }
4943
Brandon Jonesd1049182018-03-28 10:02:20 -07004944 GLsizei writeLength = 0;
4945
4946 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004947 {
4948 return false;
4949 }
4950
Brandon Jonesd1049182018-03-28 10:02:20 -07004951 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004952 {
4953 return false;
4954 }
4955
Brandon Jonesd1049182018-03-28 10:02:20 -07004956 SetRobustLengthParam(length, writeLength);
4957
Geoff Lang0b031062016-10-13 14:30:04 -04004958 return true;
4959}
4960
Geoff Lang6899b872016-10-14 11:30:13 -04004961bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4962 GLuint program,
4963 GLuint uniformBlockIndex,
4964 GLenum pname,
4965 GLsizei bufSize,
4966 GLsizei *length,
4967 GLint *params)
4968{
4969 if (!ValidateRobustEntryPoint(context, bufSize))
4970 {
4971 return false;
4972 }
4973
Brandon Jonesd1049182018-03-28 10:02:20 -07004974 GLsizei writeLength = 0;
4975
4976 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4977 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004978 {
4979 return false;
4980 }
4981
Brandon Jonesd1049182018-03-28 10:02:20 -07004982 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 SetRobustLengthParam(length, writeLength);
4988
Geoff Lang6899b872016-10-14 11:30:13 -04004989 return true;
4990}
4991
Brandon Jones416aaf92018-04-10 08:10:16 -07004992bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004993 GLenum target,
4994 GLenum internalformat,
4995 GLenum pname,
4996 GLsizei bufSize,
4997 GLsizei *length,
4998 GLint *params)
4999{
5000 if (!ValidateRobustEntryPoint(context, bufSize))
5001 {
5002 return false;
5003 }
5004
Brandon Jonesd1049182018-03-28 10:02:20 -07005005 GLsizei numParams = 0;
5006
5007 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5008 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005009 {
5010 return false;
5011 }
5012
Brandon Jonesd1049182018-03-28 10:02:20 -07005013 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005014 {
5015 return false;
5016 }
5017
Brandon Jonesd1049182018-03-28 10:02:20 -07005018 SetRobustLengthParam(length, numParams);
5019
Geoff Lang0a9661f2016-10-20 10:59:20 -07005020 return true;
5021}
5022
Jamie Madill5b772312018-03-08 20:28:32 -05005023bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005024 GLuint attribIndex,
5025 GLint size,
5026 GLenum type,
5027 GLboolean pureInteger)
5028{
5029 const Caps &caps = context->getCaps();
5030 if (attribIndex >= caps.maxVertexAttributes)
5031 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005032 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005033 return false;
5034 }
5035
5036 if (size < 1 || size > 4)
5037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005039 return false;
Shao80957d92017-02-20 21:25:59 +08005040 }
5041
5042 switch (type)
5043 {
5044 case GL_BYTE:
5045 case GL_UNSIGNED_BYTE:
5046 case GL_SHORT:
5047 case GL_UNSIGNED_SHORT:
5048 break;
5049
5050 case GL_INT:
5051 case GL_UNSIGNED_INT:
5052 if (context->getClientMajorVersion() < 3)
5053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005054 context->handleError(InvalidEnum()
5055 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005056 return false;
5057 }
5058 break;
5059
5060 case GL_FIXED:
5061 case GL_FLOAT:
5062 if (pureInteger)
5063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005065 return false;
5066 }
5067 break;
5068
5069 case GL_HALF_FLOAT:
5070 if (context->getClientMajorVersion() < 3)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum()
5073 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005074 return false;
5075 }
5076 if (pureInteger)
5077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005079 return false;
5080 }
5081 break;
5082
5083 case GL_INT_2_10_10_10_REV:
5084 case GL_UNSIGNED_INT_2_10_10_10_REV:
5085 if (context->getClientMajorVersion() < 3)
5086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005087 context->handleError(InvalidEnum()
5088 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005089 return false;
5090 }
5091 if (pureInteger)
5092 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005094 return false;
5095 }
5096 if (size != 4)
5097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005098 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5099 "UNSIGNED_INT_2_10_10_10_REV and "
5100 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005101 return false;
5102 }
5103 break;
5104
5105 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005107 return false;
5108 }
5109
5110 return true;
5111}
5112
Geoff Lang76e65652017-03-27 14:58:02 -04005113// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5114// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5115// specified clear value and the type of a buffer that is being cleared generates an
5116// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005117bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005118 GLint drawbuffer,
5119 const GLenum *validComponentTypes,
5120 size_t validComponentTypeCount)
5121{
5122 const FramebufferAttachment *attachment =
5123 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5124 if (attachment)
5125 {
5126 GLenum componentType = attachment->getFormat().info->componentType;
5127 const GLenum *end = validComponentTypes + validComponentTypeCount;
5128 if (std::find(validComponentTypes, end, componentType) == end)
5129 {
5130 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005131 InvalidOperation()
5132 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005133 return false;
5134 }
5135 }
5136
5137 return true;
5138}
5139
Jamie Madill5b772312018-03-08 20:28:32 -05005140bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005141{
5142 if (!ValidateRobustEntryPoint(context, dataSize))
5143 {
5144 return false;
5145 }
5146
Jamie Madill43da7c42018-08-01 11:34:49 -04005147 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005148 if (pixelUnpackBuffer == nullptr)
5149 {
5150 if (dataSize < imageSize)
5151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005152 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005153 }
5154 }
5155 return true;
5156}
5157
Jamie Madill5b772312018-03-08 20:28:32 -05005158bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005159 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005160 GLenum pname,
5161 bool pointerVersion,
5162 GLsizei *numParams)
5163{
5164 if (numParams)
5165 {
5166 *numParams = 0;
5167 }
5168
Corentin Walleze4477002017-12-01 14:39:58 -05005169 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005172 return false;
5173 }
5174
5175 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5176 if (!buffer)
5177 {
5178 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
5183 const Extensions &extensions = context->getExtensions();
5184
5185 switch (pname)
5186 {
5187 case GL_BUFFER_USAGE:
5188 case GL_BUFFER_SIZE:
5189 break;
5190
5191 case GL_BUFFER_ACCESS_OES:
5192 if (!extensions.mapBuffer)
5193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidEnum()
5195 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005196 return false;
5197 }
5198 break;
5199
5200 case GL_BUFFER_MAPPED:
5201 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5202 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5203 !extensions.mapBufferRange)
5204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005205 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5206 "GL_OES_mapbuffer or "
5207 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005208 return false;
5209 }
5210 break;
5211
5212 case GL_BUFFER_MAP_POINTER:
5213 if (!pointerVersion)
5214 {
5215 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005216 InvalidEnum()
5217 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220 break;
5221
5222 case GL_BUFFER_ACCESS_FLAGS:
5223 case GL_BUFFER_MAP_OFFSET:
5224 case GL_BUFFER_MAP_LENGTH:
5225 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005227 context->handleError(InvalidEnum()
5228 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005229 return false;
5230 }
5231 break;
5232
5233 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005234 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 return false;
5236 }
5237
5238 // All buffer parameter queries return one value.
5239 if (numParams)
5240 {
5241 *numParams = 1;
5242 }
5243
5244 return true;
5245}
5246
5247bool ValidateGetRenderbufferParameterivBase(Context *context,
5248 GLenum target,
5249 GLenum pname,
5250 GLsizei *length)
5251{
5252 if (length)
5253 {
5254 *length = 0;
5255 }
5256
5257 if (target != GL_RENDERBUFFER)
5258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262
5263 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5264 if (renderbuffer == nullptr)
5265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269
5270 switch (pname)
5271 {
5272 case GL_RENDERBUFFER_WIDTH:
5273 case GL_RENDERBUFFER_HEIGHT:
5274 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5275 case GL_RENDERBUFFER_RED_SIZE:
5276 case GL_RENDERBUFFER_GREEN_SIZE:
5277 case GL_RENDERBUFFER_BLUE_SIZE:
5278 case GL_RENDERBUFFER_ALPHA_SIZE:
5279 case GL_RENDERBUFFER_DEPTH_SIZE:
5280 case GL_RENDERBUFFER_STENCIL_SIZE:
5281 break;
5282
5283 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5284 if (!context->getExtensions().framebufferMultisample)
5285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289 break;
5290
5291 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005292 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 if (length)
5297 {
5298 *length = 1;
5299 }
5300 return true;
5301}
5302
5303bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5304{
5305 if (length)
5306 {
5307 *length = 0;
5308 }
5309
5310 if (GetValidShader(context, shader) == nullptr)
5311 {
5312 return false;
5313 }
5314
5315 switch (pname)
5316 {
5317 case GL_SHADER_TYPE:
5318 case GL_DELETE_STATUS:
5319 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005320 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 case GL_INFO_LOG_LENGTH:
5322 case GL_SHADER_SOURCE_LENGTH:
5323 break;
5324
5325 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5326 if (!context->getExtensions().translatedShaderSource)
5327 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331 break;
5332
5333 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 return false;
5336 }
5337
5338 if (length)
5339 {
5340 *length = 1;
5341 }
5342 return true;
5343}
5344
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005345bool ValidateGetTexParameterBase(Context *context,
5346 TextureType target,
5347 GLenum pname,
5348 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005349{
5350 if (length)
5351 {
5352 *length = 0;
5353 }
5354
5355 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 if (context->getTargetTexture(target) == nullptr)
5362 {
5363 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005365 return false;
5366 }
5367
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005368 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5369 {
5370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5371 return false;
5372 }
5373
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 switch (pname)
5375 {
5376 case GL_TEXTURE_MAG_FILTER:
5377 case GL_TEXTURE_MIN_FILTER:
5378 case GL_TEXTURE_WRAP_S:
5379 case GL_TEXTURE_WRAP_T:
5380 break;
5381
5382 case GL_TEXTURE_USAGE_ANGLE:
5383 if (!context->getExtensions().textureUsage)
5384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005391 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 case GL_TEXTURE_IMMUTABLE_FORMAT:
5398 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5399 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 return false;
5402 }
5403 break;
5404
5405 case GL_TEXTURE_WRAP_R:
5406 case GL_TEXTURE_IMMUTABLE_LEVELS:
5407 case GL_TEXTURE_SWIZZLE_R:
5408 case GL_TEXTURE_SWIZZLE_G:
5409 case GL_TEXTURE_SWIZZLE_B:
5410 case GL_TEXTURE_SWIZZLE_A:
5411 case GL_TEXTURE_BASE_LEVEL:
5412 case GL_TEXTURE_MAX_LEVEL:
5413 case GL_TEXTURE_MIN_LOD:
5414 case GL_TEXTURE_MAX_LOD:
5415 case GL_TEXTURE_COMPARE_MODE:
5416 case GL_TEXTURE_COMPARE_FUNC:
5417 if (context->getClientMajorVersion() < 3)
5418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005419 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 return false;
5421 }
5422 break;
5423
5424 case GL_TEXTURE_SRGB_DECODE_EXT:
5425 if (!context->getExtensions().textureSRGBDecode)
5426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005427 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 return false;
5429 }
5430 break;
5431
Yunchao Hebacaa712018-01-30 14:01:39 +08005432 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5433 if (context->getClientVersion() < Version(3, 1))
5434 {
5435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5436 return false;
5437 }
5438 break;
5439
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005440 case GL_GENERATE_MIPMAP:
5441 case GL_TEXTURE_CROP_RECT_OES:
5442 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5443 // after GL_OES_draw_texture functionality implemented
5444 if (context->getClientMajorVersion() > 1)
5445 {
5446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5447 return false;
5448 }
5449 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454
5455 if (length)
5456 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005457 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 }
5459 return true;
5460}
5461
5462bool ValidateGetVertexAttribBase(Context *context,
5463 GLuint index,
5464 GLenum pname,
5465 GLsizei *length,
5466 bool pointer,
5467 bool pureIntegerEntryPoint)
5468{
5469 if (length)
5470 {
5471 *length = 0;
5472 }
5473
5474 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005476 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 return false;
5478 }
5479
5480 if (index >= context->getCaps().maxVertexAttributes)
5481 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005482 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005483 return false;
5484 }
5485
5486 if (pointer)
5487 {
5488 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493 }
5494 else
5495 {
5496 switch (pname)
5497 {
5498 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5499 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5500 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5501 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5502 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5503 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5504 case GL_CURRENT_VERTEX_ATTRIB:
5505 break;
5506
5507 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5508 static_assert(
5509 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5510 "ANGLE extension enums not equal to GL enums.");
5511 if (context->getClientMajorVersion() < 3 &&
5512 !context->getExtensions().instancedArrays)
5513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005514 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5515 "requires OpenGL ES 3.0 or "
5516 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519 break;
5520
5521 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5522 if (context->getClientMajorVersion() < 3)
5523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005524 context->handleError(
5525 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 return false;
5527 }
5528 break;
5529
5530 case GL_VERTEX_ATTRIB_BINDING:
5531 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5532 if (context->getClientVersion() < ES_3_1)
5533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005534 context->handleError(InvalidEnum()
5535 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005536 return false;
5537 }
5538 break;
5539
5540 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 return false;
5543 }
5544 }
5545
5546 if (length)
5547 {
5548 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5549 {
5550 *length = 4;
5551 }
5552 else
5553 {
5554 *length = 1;
5555 }
5556 }
5557
5558 return true;
5559}
5560
Jamie Madill4928b7c2017-06-20 12:57:39 -04005561bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005562 GLint x,
5563 GLint y,
5564 GLsizei width,
5565 GLsizei height,
5566 GLenum format,
5567 GLenum type,
5568 GLsizei bufSize,
5569 GLsizei *length,
5570 GLsizei *columns,
5571 GLsizei *rows,
5572 void *pixels)
5573{
5574 if (length != nullptr)
5575 {
5576 *length = 0;
5577 }
5578 if (rows != nullptr)
5579 {
5580 *rows = 0;
5581 }
5582 if (columns != nullptr)
5583 {
5584 *columns = 0;
5585 }
5586
5587 if (width < 0 || height < 0)
5588 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005589 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 return false;
5591 }
5592
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005593 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005594
Jamie Madill427064d2018-04-13 16:20:34 -04005595 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 return false;
5598 }
5599
Jamie Madille98b1b52018-03-08 09:47:23 -05005600 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005602 return false;
5603 }
5604
Jamie Madill690c8eb2018-03-12 15:20:03 -04005605 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 ASSERT(framebuffer);
5607
5608 if (framebuffer->getReadBufferState() == GL_NONE)
5609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005611 return false;
5612 }
5613
5614 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5615 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5616 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5617 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5618 // situation is an application error that would lead to a crash in ANGLE.
5619 if (readBuffer == nullptr)
5620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 return false;
5623 }
5624
Martin Radev28031682017-07-28 14:47:56 +03005625 // ANGLE_multiview, Revision 1:
5626 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005627 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5628 // in the current read framebuffer is more than one.
5629 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005630 {
5631 context->handleError(InvalidFramebufferOperation()
5632 << "Attempting to read from a multi-view framebuffer.");
5633 return false;
5634 }
5635
Geoff Lang280ba992017-04-18 16:30:58 -04005636 if (context->getExtensions().webglCompatibility)
5637 {
5638 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5639 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5640 // and type before validating the combination of format and type. However, the
5641 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5642 // verifies that GL_INVALID_OPERATION is generated.
5643 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5644 // dEQP/WebGL.
5645 if (!ValidReadPixelsFormatEnum(context, format))
5646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005648 return false;
5649 }
5650
5651 if (!ValidReadPixelsTypeEnum(context, type))
5652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005653 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005654 return false;
5655 }
5656 }
5657
Jamie Madill690c8eb2018-03-12 15:20:03 -04005658 GLenum currentFormat = GL_NONE;
5659 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5660
5661 GLenum currentType = GL_NONE;
5662 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5663
Jamie Madillbe849e42017-05-02 15:49:00 -04005664 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5665
5666 bool validFormatTypeCombination =
5667 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5668
5669 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5670 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005672 return false;
5673 }
5674
5675 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005676 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5678 {
5679 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005680 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005683 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5684 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5685 {
5686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5687 return false;
5688 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005689
5690 // .. the data would be packed to the buffer object such that the memory writes required
5691 // would exceed the data store size.
5692 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005693 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 const auto &pack = context->getGLState().getPackState();
5695
Jamie Madillca2ff382018-07-11 09:01:17 -04005696 GLuint endByte = 0;
5697 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 return false;
5701 }
5702
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 if (bufSize >= 0)
5704 {
5705 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5706 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 return false;
5709 }
5710 }
5711
5712 if (pixelPackBuffer != nullptr)
5713 {
5714 CheckedNumeric<size_t> checkedEndByte(endByte);
5715 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5716 checkedEndByte += checkedOffset;
5717
5718 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5719 {
5720 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005721 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005722 return false;
5723 }
5724 }
5725
5726 if (pixelPackBuffer == nullptr && length != nullptr)
5727 {
5728 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5729 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 return false;
5732 }
5733
5734 *length = static_cast<GLsizei>(endByte);
5735 }
5736
Geoff Langa953b522018-02-21 16:56:23 -05005737 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005738 angle::CheckedNumeric<int> clippedExtent(length);
5739 if (start < 0)
5740 {
5741 // "subtract" the area that is less than 0
5742 clippedExtent += start;
5743 }
5744
Geoff Langa953b522018-02-21 16:56:23 -05005745 angle::CheckedNumeric<int> readExtent = start;
5746 readExtent += length;
5747 if (!readExtent.IsValid())
5748 {
5749 return false;
5750 }
5751
5752 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005753 {
5754 // Subtract the region to the right of the read buffer
5755 clippedExtent -= (readExtent - bufferSize);
5756 }
5757
5758 if (!clippedExtent.IsValid())
5759 {
Geoff Langa953b522018-02-21 16:56:23 -05005760 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 }
5762
Geoff Langa953b522018-02-21 16:56:23 -05005763 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5764 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 };
5766
Geoff Langa953b522018-02-21 16:56:23 -05005767 GLsizei writtenColumns = 0;
5768 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5769 {
5770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5771 return false;
5772 }
5773
5774 GLsizei writtenRows = 0;
5775 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5776 {
5777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5778 return false;
5779 }
5780
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 if (columns != nullptr)
5782 {
Geoff Langa953b522018-02-21 16:56:23 -05005783 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 }
5785
5786 if (rows != nullptr)
5787 {
Geoff Langa953b522018-02-21 16:56:23 -05005788 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 }
5790
5791 return true;
5792}
5793
5794template <typename ParamType>
5795bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005796 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 GLenum pname,
5798 GLsizei bufSize,
5799 const ParamType *params)
5800{
5801 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806
5807 if (context->getTargetTexture(target) == nullptr)
5808 {
5809 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005810 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 return false;
5812 }
5813
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005814 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 if (bufSize >= 0 && bufSize < minBufSize)
5816 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005817 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 return false;
5819 }
5820
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005821 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5822 {
5823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5824 return false;
5825 }
5826
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 switch (pname)
5828 {
5829 case GL_TEXTURE_WRAP_R:
5830 case GL_TEXTURE_SWIZZLE_R:
5831 case GL_TEXTURE_SWIZZLE_G:
5832 case GL_TEXTURE_SWIZZLE_B:
5833 case GL_TEXTURE_SWIZZLE_A:
5834 case GL_TEXTURE_BASE_LEVEL:
5835 case GL_TEXTURE_MAX_LEVEL:
5836 case GL_TEXTURE_COMPARE_MODE:
5837 case GL_TEXTURE_COMPARE_FUNC:
5838 case GL_TEXTURE_MIN_LOD:
5839 case GL_TEXTURE_MAX_LOD:
5840 if (context->getClientMajorVersion() < 3)
5841 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005842 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 return false;
5844 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005845 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005847 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5848 "available without "
5849 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 return false;
5851 }
5852 break;
5853
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005854 case GL_GENERATE_MIPMAP:
5855 case GL_TEXTURE_CROP_RECT_OES:
5856 if (context->getClientMajorVersion() > 1)
5857 {
5858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5859 return false;
5860 }
5861 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005862 default:
5863 break;
5864 }
5865
Olli Etuahod310a432018-08-24 15:40:23 +03005866 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005867 {
5868 switch (pname)
5869 {
5870 case GL_TEXTURE_MIN_FILTER:
5871 case GL_TEXTURE_MAG_FILTER:
5872 case GL_TEXTURE_WRAP_S:
5873 case GL_TEXTURE_WRAP_T:
5874 case GL_TEXTURE_WRAP_R:
5875 case GL_TEXTURE_MIN_LOD:
5876 case GL_TEXTURE_MAX_LOD:
5877 case GL_TEXTURE_COMPARE_MODE:
5878 case GL_TEXTURE_COMPARE_FUNC:
5879 context->handleError(InvalidEnum()
5880 << "Invalid parameter for 2D multisampled textures.");
5881 return false;
5882 }
5883 }
5884
Jamie Madillbe849e42017-05-02 15:49:00 -04005885 switch (pname)
5886 {
5887 case GL_TEXTURE_WRAP_S:
5888 case GL_TEXTURE_WRAP_T:
5889 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005890 {
5891 bool restrictedWrapModes =
5892 target == TextureType::External || target == TextureType::Rectangle;
5893 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005894 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005895 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005896 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005897 }
5898 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005899
5900 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005901 {
5902 bool restrictedMinFilter =
5903 target == TextureType::External || target == TextureType::Rectangle;
5904 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005905 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005906 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005907 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005908 }
5909 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005910
5911 case GL_TEXTURE_MAG_FILTER:
5912 if (!ValidateTextureMagFilterValue(context, params))
5913 {
5914 return false;
5915 }
5916 break;
5917
5918 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005919 if (!context->getExtensions().textureUsage)
5920 {
5921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5922 return false;
5923 }
5924
Jamie Madillbe849e42017-05-02 15:49:00 -04005925 switch (ConvertToGLenum(params[0]))
5926 {
5927 case GL_NONE:
5928 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5929 break;
5930
5931 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005933 return false;
5934 }
5935 break;
5936
5937 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005938 {
5939 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5940 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005941 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005942 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005943 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005944 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5945 }
5946 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005947
5948 case GL_TEXTURE_MIN_LOD:
5949 case GL_TEXTURE_MAX_LOD:
5950 // any value is permissible
5951 break;
5952
5953 case GL_TEXTURE_COMPARE_MODE:
5954 if (!ValidateTextureCompareModeValue(context, params))
5955 {
5956 return false;
5957 }
5958 break;
5959
5960 case GL_TEXTURE_COMPARE_FUNC:
5961 if (!ValidateTextureCompareFuncValue(context, params))
5962 {
5963 return false;
5964 }
5965 break;
5966
5967 case GL_TEXTURE_SWIZZLE_R:
5968 case GL_TEXTURE_SWIZZLE_G:
5969 case GL_TEXTURE_SWIZZLE_B:
5970 case GL_TEXTURE_SWIZZLE_A:
5971 switch (ConvertToGLenum(params[0]))
5972 {
5973 case GL_RED:
5974 case GL_GREEN:
5975 case GL_BLUE:
5976 case GL_ALPHA:
5977 case GL_ZERO:
5978 case GL_ONE:
5979 break;
5980
5981 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 return false;
5984 }
5985 break;
5986
5987 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005988 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005990 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 return false;
5992 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005993 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005995 context->handleError(InvalidOperation()
5996 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 return false;
5998 }
Olli Etuahod310a432018-08-24 15:40:23 +03005999 if ((target == TextureType::_2DMultisample ||
6000 target == TextureType::_2DMultisampleArray) &&
6001 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006002 {
6003 context->handleError(InvalidOperation()
6004 << "Base level must be 0 for multisampled textures.");
6005 return false;
6006 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006007 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006008 {
6009 context->handleError(InvalidOperation()
6010 << "Base level must be 0 for rectangle textures.");
6011 return false;
6012 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006013 break;
6014
6015 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006016 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006018 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 return false;
6020 }
6021 break;
6022
6023 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6024 if (context->getClientVersion() < Version(3, 1))
6025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 return false;
6028 }
6029 switch (ConvertToGLenum(params[0]))
6030 {
6031 case GL_DEPTH_COMPONENT:
6032 case GL_STENCIL_INDEX:
6033 break;
6034
6035 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006037 return false;
6038 }
6039 break;
6040
6041 case GL_TEXTURE_SRGB_DECODE_EXT:
6042 if (!ValidateTextureSRGBDecodeValue(context, params))
6043 {
6044 return false;
6045 }
6046 break;
6047
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006048 case GL_GENERATE_MIPMAP:
6049 case GL_TEXTURE_CROP_RECT_OES:
6050 if (context->getClientMajorVersion() > 1)
6051 {
6052 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6053 return false;
6054 }
6055 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006056 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006057 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006058 return false;
6059 }
6060
6061 return true;
6062}
6063
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006064template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6065template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006066
Jamie Madill5b772312018-03-08 20:28:32 -05006067bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006068{
6069 if (index >= MAX_VERTEX_ATTRIBS)
6070 {
6071 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6072 return false;
6073 }
6074
6075 return true;
6076}
6077
6078bool ValidateGetActiveUniformBlockivBase(Context *context,
6079 GLuint program,
6080 GLuint uniformBlockIndex,
6081 GLenum pname,
6082 GLsizei *length)
6083{
6084 if (length)
6085 {
6086 *length = 0;
6087 }
6088
6089 if (context->getClientMajorVersion() < 3)
6090 {
6091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6092 return false;
6093 }
6094
6095 Program *programObject = GetValidProgram(context, program);
6096 if (!programObject)
6097 {
6098 return false;
6099 }
6100
6101 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6102 {
6103 context->handleError(InvalidValue()
6104 << "uniformBlockIndex exceeds active uniform block count.");
6105 return false;
6106 }
6107
6108 switch (pname)
6109 {
6110 case GL_UNIFORM_BLOCK_BINDING:
6111 case GL_UNIFORM_BLOCK_DATA_SIZE:
6112 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6113 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6114 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6115 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6116 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6117 break;
6118
6119 default:
6120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6121 return false;
6122 }
6123
6124 if (length)
6125 {
6126 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6127 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006128 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006129 programObject->getUniformBlockByIndex(uniformBlockIndex);
6130 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6131 }
6132 else
6133 {
6134 *length = 1;
6135 }
6136 }
6137
6138 return true;
6139}
6140
Jamie Madill9696d072017-08-26 23:19:57 -04006141template <typename ParamType>
6142bool ValidateSamplerParameterBase(Context *context,
6143 GLuint sampler,
6144 GLenum pname,
6145 GLsizei bufSize,
6146 ParamType *params)
6147{
6148 if (context->getClientMajorVersion() < 3)
6149 {
6150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6151 return false;
6152 }
6153
6154 if (!context->isSampler(sampler))
6155 {
6156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6157 return false;
6158 }
6159
6160 const GLsizei minBufSize = 1;
6161 if (bufSize >= 0 && bufSize < minBufSize)
6162 {
6163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6164 return false;
6165 }
6166
6167 switch (pname)
6168 {
6169 case GL_TEXTURE_WRAP_S:
6170 case GL_TEXTURE_WRAP_T:
6171 case GL_TEXTURE_WRAP_R:
6172 if (!ValidateTextureWrapModeValue(context, params, false))
6173 {
6174 return false;
6175 }
6176 break;
6177
6178 case GL_TEXTURE_MIN_FILTER:
6179 if (!ValidateTextureMinFilterValue(context, params, false))
6180 {
6181 return false;
6182 }
6183 break;
6184
6185 case GL_TEXTURE_MAG_FILTER:
6186 if (!ValidateTextureMagFilterValue(context, params))
6187 {
6188 return false;
6189 }
6190 break;
6191
6192 case GL_TEXTURE_MIN_LOD:
6193 case GL_TEXTURE_MAX_LOD:
6194 // any value is permissible
6195 break;
6196
6197 case GL_TEXTURE_COMPARE_MODE:
6198 if (!ValidateTextureCompareModeValue(context, params))
6199 {
6200 return false;
6201 }
6202 break;
6203
6204 case GL_TEXTURE_COMPARE_FUNC:
6205 if (!ValidateTextureCompareFuncValue(context, params))
6206 {
6207 return false;
6208 }
6209 break;
6210
6211 case GL_TEXTURE_SRGB_DECODE_EXT:
6212 if (!ValidateTextureSRGBDecodeValue(context, params))
6213 {
6214 return false;
6215 }
6216 break;
6217
Luc Ferron1b1a8642018-01-23 15:12:01 -05006218 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6219 {
6220 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6221 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6222 {
6223 return false;
6224 }
6225 }
6226 break;
6227
Jamie Madill9696d072017-08-26 23:19:57 -04006228 default:
6229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6230 return false;
6231 }
6232
6233 return true;
6234}
6235
6236template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6237template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6238
6239bool ValidateGetSamplerParameterBase(Context *context,
6240 GLuint sampler,
6241 GLenum pname,
6242 GLsizei *length)
6243{
6244 if (length)
6245 {
6246 *length = 0;
6247 }
6248
6249 if (context->getClientMajorVersion() < 3)
6250 {
6251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6252 return false;
6253 }
6254
6255 if (!context->isSampler(sampler))
6256 {
6257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6258 return false;
6259 }
6260
6261 switch (pname)
6262 {
6263 case GL_TEXTURE_WRAP_S:
6264 case GL_TEXTURE_WRAP_T:
6265 case GL_TEXTURE_WRAP_R:
6266 case GL_TEXTURE_MIN_FILTER:
6267 case GL_TEXTURE_MAG_FILTER:
6268 case GL_TEXTURE_MIN_LOD:
6269 case GL_TEXTURE_MAX_LOD:
6270 case GL_TEXTURE_COMPARE_MODE:
6271 case GL_TEXTURE_COMPARE_FUNC:
6272 break;
6273
Luc Ferron1b1a8642018-01-23 15:12:01 -05006274 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6275 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6276 {
6277 return false;
6278 }
6279 break;
6280
Jamie Madill9696d072017-08-26 23:19:57 -04006281 case GL_TEXTURE_SRGB_DECODE_EXT:
6282 if (!context->getExtensions().textureSRGBDecode)
6283 {
6284 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6285 return false;
6286 }
6287 break;
6288
6289 default:
6290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6291 return false;
6292 }
6293
6294 if (length)
6295 {
6296 *length = 1;
6297 }
6298 return true;
6299}
6300
6301bool ValidateGetInternalFormativBase(Context *context,
6302 GLenum target,
6303 GLenum internalformat,
6304 GLenum pname,
6305 GLsizei bufSize,
6306 GLsizei *numParams)
6307{
6308 if (numParams)
6309 {
6310 *numParams = 0;
6311 }
6312
6313 if (context->getClientMajorVersion() < 3)
6314 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006315 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006316 return false;
6317 }
6318
6319 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006320 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006321 {
6322 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6323 return false;
6324 }
6325
6326 switch (target)
6327 {
6328 case GL_RENDERBUFFER:
6329 break;
6330
6331 case GL_TEXTURE_2D_MULTISAMPLE:
6332 if (context->getClientVersion() < ES_3_1)
6333 {
Olli Etuahod310a432018-08-24 15:40:23 +03006334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006335 return false;
6336 }
6337 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006338 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6339 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006340 {
6341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6342 return false;
6343 }
6344 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006345 default:
6346 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6347 return false;
6348 }
6349
6350 if (bufSize < 0)
6351 {
6352 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6353 return false;
6354 }
6355
6356 GLsizei maxWriteParams = 0;
6357 switch (pname)
6358 {
6359 case GL_NUM_SAMPLE_COUNTS:
6360 maxWriteParams = 1;
6361 break;
6362
6363 case GL_SAMPLES:
6364 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6365 break;
6366
6367 default:
6368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6369 return false;
6370 }
6371
6372 if (numParams)
6373 {
6374 // glGetInternalFormativ will not overflow bufSize
6375 *numParams = std::min(bufSize, maxWriteParams);
6376 }
6377
6378 return true;
6379}
6380
Jamie Madille98b1b52018-03-08 09:47:23 -05006381bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6382{
Jamie Madill427064d2018-04-13 16:20:34 -04006383 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006384 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006386 return false;
6387 }
6388 return true;
6389}
6390
Lingfeng Yang038dd532018-03-29 17:31:52 -07006391bool ValidateMultitextureUnit(Context *context, GLenum texture)
6392{
6393 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6394 {
6395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6396 return false;
6397 }
6398 return true;
6399}
6400
Olli Etuahod310a432018-08-24 15:40:23 +03006401bool ValidateTexStorageMultisample(Context *context,
6402 TextureType target,
6403 GLsizei samples,
6404 GLint internalFormat,
6405 GLsizei width,
6406 GLsizei height)
6407{
6408 const Caps &caps = context->getCaps();
6409 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6410 static_cast<GLuint>(height) > caps.max2DTextureSize)
6411 {
6412 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6413 return false;
6414 }
6415
6416 if (samples == 0)
6417 {
6418 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6419 return false;
6420 }
6421
6422 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6423 if (!formatCaps.textureAttachment)
6424 {
6425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6426 return false;
6427 }
6428
6429 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6430 // is one of the unsized base internalformats listed in table 8.11.
6431 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6432 if (formatInfo.internalFormat == GL_NONE)
6433 {
6434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6435 return false;
6436 }
6437
6438 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6439 {
6440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6441 return false;
6442 }
6443
6444 Texture *texture = context->getTargetTexture(target);
6445 if (!texture || texture->id() == 0)
6446 {
6447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6448 return false;
6449 }
6450
6451 if (texture->getImmutableFormat())
6452 {
6453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6454 return false;
6455 }
6456 return true;
6457}
6458
Jamie Madillc29968b2016-01-20 11:17:23 -05006459} // namespace gl