blob: 5b4ccadd4e25f602a547e2ede42599ec0990aef0 [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
Jamie Madilld84b6732018-09-06 15:54:35 -04002569 VertexArray *vertexArray = state.getVertexArray();
2570 ASSERT(vertexArray);
2571
2572 if (!extensions.webglCompatibility && vertexArray->hasMappedEnabledArrayBuffer())
Jamie Madille7d80f32018-08-08 15:49:23 -04002573 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002574 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002575 }
2576
2577 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2578 // Section 6.10 of the WebGL 1.0 spec.
2579 Framebuffer *framebuffer = state.getDrawFramebuffer();
Jamie Madilld84b6732018-09-06 15:54:35 -04002580 ASSERT(framebuffer);
2581
Jamie Madille7d80f32018-08-08 15:49:23 -04002582 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2583 {
2584 ASSERT(framebuffer);
2585 const FramebufferAttachment *dsAttachment =
2586 framebuffer->getStencilOrDepthStencilAttachment();
2587 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2588 ASSERT(stencilBits <= 8);
2589
2590 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2591 if (depthStencilState.stencilTest && stencilBits > 0)
2592 {
2593 GLuint maxStencilValue = (1 << stencilBits) - 1;
2594
2595 bool differentRefs =
2596 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2597 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2598 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2599 (depthStencilState.stencilBackWritemask & maxStencilValue);
2600 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2601 (depthStencilState.stencilBackMask & maxStencilValue);
2602
2603 if (differentRefs || differentWritemasks || differentMasks)
2604 {
2605 if (!extensions.webglCompatibility)
2606 {
2607 WARN() << "This ANGLE implementation does not support separate front/back "
2608 "stencil writemasks, reference values, or stencil mask values.";
2609 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002610 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002611 }
2612 }
2613 }
2614
2615 if (!framebuffer->isComplete(context))
2616 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002617 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2618 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002619 }
2620
2621 if (context->getStateCache().hasAnyEnabledClientAttrib())
2622 {
2623 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2624 {
2625 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2626 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2627 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2628 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002629 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002630 }
2631
2632 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2633 {
2634 // This is an application error that would normally result in a crash, but we catch it
2635 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002636 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002637 }
2638 }
2639
2640 // If we are running GLES1, there is no current program.
2641 if (context->getClientVersion() >= Version(2, 0))
2642 {
2643 Program *program = state.getProgram();
2644 if (!program)
2645 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002646 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002647 }
2648
2649 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2650 // vertex shader stage or fragment shader stage is a undefined behaviour.
2651 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2652 // produce undefined result.
2653 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2654 !program->hasLinkedShaderStage(ShaderType::Fragment))
2655 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002656 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002657 }
2658
2659 if (!program->validateSamplers(nullptr, context->getCaps()))
2660 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002661 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002662 }
2663
2664 if (extensions.multiview)
2665 {
2666 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2667 const int framebufferNumViews = framebuffer->getNumViews();
2668 if (framebufferNumViews != programNumViews)
2669 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002670 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002671 }
2672
2673 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2674 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2675 framebufferNumViews > 1)
2676 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002677 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002678 }
2679
2680 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2681 state.isQueryActive(QueryType::TimeElapsed))
2682 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002683 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002684 }
2685 }
2686
2687 // Uniform buffer validation
2688 for (unsigned int uniformBlockIndex = 0;
2689 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2690 {
2691 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2692 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2693 const OffsetBindingPointer<Buffer> &uniformBuffer =
2694 state.getIndexedUniformBuffer(blockBinding);
2695
2696 if (uniformBuffer.get() == nullptr)
2697 {
2698 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002699 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002700 }
2701
2702 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2703 if (uniformBufferSize < uniformBlock.dataSize)
2704 {
2705 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002706 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002707 }
2708
2709 if (extensions.webglCompatibility &&
2710 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2711 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002712 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002713 }
2714 }
2715
2716 // Do some additonal WebGL-specific validation
2717 if (extensions.webglCompatibility)
2718 {
2719 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2720 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2721 transformFeedbackObject->buffersBoundForOtherUse())
2722 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002723 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002724 }
2725
2726 // Detect rendering feedback loops for WebGL.
2727 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2728 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002729 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731
2732 // Detect that the vertex shader input types match the attribute types
2733 if (!ValidateVertexShaderAttributeTypeMatch(context))
2734 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002735 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002736 }
2737
2738 // Detect that the color buffer types match the fragment shader output types
2739 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2740 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002741 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002742 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002743
2744 const VertexArray *vao = context->getGLState().getVertexArray();
2745 if (vao->hasTransformFeedbackBindingConflict(context))
2746 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002747 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002748 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002749 }
2750 }
2751
Jamie Madillb42162f2018-08-20 12:58:37 -04002752 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002753}
2754
Jamie Madill493f9572018-05-24 19:52:15 -04002755bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002756{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002757 const Extensions &extensions = context->getExtensions();
2758
Jamie Madill1aeb1312014-06-20 13:21:25 -04002759 switch (mode)
2760 {
Jamie Madill493f9572018-05-24 19:52:15 -04002761 case PrimitiveMode::Points:
2762 case PrimitiveMode::Lines:
2763 case PrimitiveMode::LineLoop:
2764 case PrimitiveMode::LineStrip:
2765 case PrimitiveMode::Triangles:
2766 case PrimitiveMode::TriangleStrip:
2767 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002768 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002769
Jamie Madill493f9572018-05-24 19:52:15 -04002770 case PrimitiveMode::LinesAdjacency:
2771 case PrimitiveMode::LineStripAdjacency:
2772 case PrimitiveMode::TrianglesAdjacency:
2773 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002774 if (!extensions.geometryShader)
2775 {
2776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2777 return false;
2778 }
2779 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002780 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002783 }
2784
Jamie Madill250d33f2014-06-06 17:09:03 -04002785 if (count < 0)
2786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002787 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002788 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002789 }
2790
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002791 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002792
Jamie Madilld84b6732018-09-06 15:54:35 -04002793 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
2794 if (drawStatesError)
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 {
Jamie Madilld84b6732018-09-06 15:54:35 -04002796 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
2797
Jamie Madillb42162f2018-08-20 12:58:37 -04002798 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2799 // Incomplete.
2800 GLenum errorCode =
2801 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2802 : GL_INVALID_OPERATION);
2803 context->handleError(Error(errorCode, errorMessage));
Jamie Madille7d80f32018-08-08 15:49:23 -04002804 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002805 }
2806
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002807 // If we are running GLES1, there is no current program.
2808 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002809 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002810 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002811 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002812
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002813 // Do geometry shader specific validations
2814 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002815 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002816 if (!IsCompatibleDrawModeWithGeometryShader(
2817 mode, program->getGeometryShaderInputPrimitiveType()))
2818 {
2819 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2820 IncompatibleDrawModeAgainstGeometryShader);
2821 return false;
2822 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002823 }
2824 }
2825
Jamie Madill9fdaa492018-02-16 10:52:11 -05002826 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002827}
2828
Jamie Madill5b772312018-03-08 20:28:32 -05002829bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002830 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002831 GLint first,
2832 GLsizei count,
2833 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002834{
Jamie Madillfd716582014-06-06 17:09:04 -04002835 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002837 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002838 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002839 }
2840
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002841 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002842 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002843 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002844 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002845 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002846 if (!ValidateTransformFeedbackPrimitiveMode(context,
2847 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002848 {
James Darpinian30b604d2018-03-12 17:26:57 -07002849 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2850 return false;
2851 }
2852
2853 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2854 {
2855 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2856 return false;
2857 }
Jamie Madillfd716582014-06-06 17:09:04 -04002858 }
2859
Jiajia Qind9671222016-11-29 16:30:31 +08002860 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002861 {
2862 return false;
2863 }
2864
Corentin Wallez71168a02016-12-19 15:11:18 -08002865 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 // - first < 0 has been checked as an error condition.
2867 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002868 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002870 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002871 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002872 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2873 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2874 {
2875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2876 return false;
2877 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002878
Jamie Madill2da53562018-08-01 11:34:47 -04002879 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002880 {
2881 return false;
2882 }
Jamie Madillfd716582014-06-06 17:09:04 -04002883 }
2884
2885 return true;
2886}
2887
He Yunchaoced53ae2016-11-29 15:00:51 +08002888bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002889 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002890 GLint first,
2891 GLsizei count,
2892 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002893{
Geoff Lang63c5a592017-09-27 14:08:16 -04002894 if (!context->getExtensions().instancedArrays)
2895 {
2896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2897 return false;
2898 }
2899
Corentin Wallez170efbf2017-05-02 13:45:01 -04002900 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002901 {
2902 return false;
2903 }
2904
Corentin Wallez0dc97812017-06-22 14:38:44 -04002905 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002906}
2907
Jamie Madill493f9572018-05-24 19:52:15 -04002908bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002909{
Jamie Madill250d33f2014-06-06 17:09:03 -04002910 switch (type)
2911 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002912 case GL_UNSIGNED_BYTE:
2913 case GL_UNSIGNED_SHORT:
2914 break;
2915 case GL_UNSIGNED_INT:
2916 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002919 return false;
2920 }
2921 break;
2922 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002925 }
2926
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002927 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002928
Jamie Madill43da7c42018-08-01 11:34:49 -04002929 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002930 if (curTransformFeedback && curTransformFeedback->isActive() &&
2931 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002932 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002933 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2934 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2935 if (context->getExtensions().geometryShader)
2936 {
2937 if (!ValidateTransformFeedbackPrimitiveMode(
2938 context, curTransformFeedback->getPrimitiveMode(), mode))
2939 {
2940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2941 return false;
2942 }
2943 }
2944 else
2945 {
2946 // It is an invalid operation to call DrawElements, DrawRangeElements or
2947 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2948 // 86)
2949 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2950 UnsupportedDrawModeForTransformFeedback);
2951 return false;
2952 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002953 }
2954
Jiajia Qind9671222016-11-29 16:30:31 +08002955 return true;
2956}
2957
Jamie Madill5b772312018-03-08 20:28:32 -05002958bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002959 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002960 GLsizei count,
2961 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002962 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002963 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002964{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002965 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002966 return false;
2967
2968 const State &state = context->getGLState();
2969
Corentin Wallez170efbf2017-05-02 13:45:01 -04002970 if (!ValidateDrawBase(context, mode, count))
2971 {
2972 return false;
2973 }
2974
Jamie Madill43da7c42018-08-01 11:34:49 -04002975 const VertexArray *vao = state.getVertexArray();
2976 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002977
Jamie Madill43da7c42018-08-01 11:34:49 -04002978 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002979
2980 if (context->getExtensions().webglCompatibility)
2981 {
2982 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2983 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2984 {
2985 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2986 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2987 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002988 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002989 return false;
2990 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002991
2992 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2993 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2994 // error is generated.
2995 if (reinterpret_cast<intptr_t>(indices) < 0)
2996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002998 return false;
2999 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003000 }
Jamie Madillcc73f242018-08-01 11:34:48 -04003001 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
3002 {
3003 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
3004 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3005 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3006 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3007 return false;
3008 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003009
3010 if (context->getExtensions().webglCompatibility ||
3011 !context->getGLState().areClientArraysEnabled())
3012 {
Brandon Jones2a018152018-06-08 15:59:26 -07003013 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003014 {
3015 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003016 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3017 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003019 return false;
3020 }
3021 }
3022
Jamie Madill9fdaa492018-02-16 10:52:11 -05003023 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003024 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003025 // This is an application error that would normally result in a crash, but we catch it and
3026 // return an error
3027 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3028 return false;
3029 }
3030
3031 if (count > 0 && elementArrayBuffer)
3032 {
3033 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3034 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3035 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3036 constexpr uint64_t kMaxTypeSize = 8;
3037 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3038 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3039 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3040
3041 uint64_t typeSize = typeBytes;
3042 uint64_t elementCount = static_cast<uint64_t>(count);
3043 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3044
3045 // Doing the multiplication here is overflow-safe
3046 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3047
3048 // The offset can be any value, check for overflows
3049 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3050 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003051 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3053 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003054 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003055
3056 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3057 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003058 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3060 return false;
3061 }
3062
3063 ASSERT(isPow2(typeSize) && typeSize > 0);
3064 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3065 {
3066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003067 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003068 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003069
3070 if (context->getExtensions().webglCompatibility &&
3071 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3072 {
3073 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3074 ElementArrayBufferBoundForTransformFeedback);
3075 return false;
3076 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003077 }
3078
Jamie Madill2da53562018-08-01 11:34:47 -04003079 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003080 {
3081 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003082 const DrawCallParams &params = context->getParams<DrawCallParams>();
3083 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3084 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003085
3086 // If we use an index greater than our maximum supported index range, return an error.
3087 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3088 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003089 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3092 return false;
3093 }
3094
Jamie Madill2da53562018-08-01 11:34:47 -04003095 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003096 {
3097 return false;
3098 }
3099
3100 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003101 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003102 }
3103
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003104 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003105}
3106
Jamie Madill5b772312018-03-08 20:28:32 -05003107bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003108 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003109 GLsizei count,
3110 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003111 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003112 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003113{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003114 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003115}
3116
Geoff Lang3edfe032015-09-04 16:38:24 -04003117bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003118 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003119 GLsizei count,
3120 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003121 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003122 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003123{
Geoff Lang63c5a592017-09-27 14:08:16 -04003124 if (!context->getExtensions().instancedArrays)
3125 {
3126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3127 return false;
3128 }
3129
Corentin Wallez170efbf2017-05-02 13:45:01 -04003130 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003131 {
3132 return false;
3133 }
3134
Corentin Wallez0dc97812017-06-22 14:38:44 -04003135 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003136}
3137
He Yunchaoced53ae2016-11-29 15:00:51 +08003138bool ValidateFramebufferTextureBase(Context *context,
3139 GLenum target,
3140 GLenum attachment,
3141 GLuint texture,
3142 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003143{
Geoff Lange8afa902017-09-27 15:00:43 -04003144 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003147 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003148 }
3149
3150 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003151 {
3152 return false;
3153 }
3154
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 if (texture != 0)
3156 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003157 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003158
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003159 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003161 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 }
3164
3165 if (level < 0)
3166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003167 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003168 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003169 }
3170 }
3171
Jamie Madill43da7c42018-08-01 11:34:49 -04003172 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003173 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003174
Jamie Madill84115c92015-04-23 15:00:07 -04003175 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003179 }
3180
3181 return true;
3182}
3183
Geoff Langb1196682014-07-23 13:47:29 -04003184bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003185{
3186 if (program == 0)
3187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003188 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003189 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003190 }
3191
Jamie Madill43da7c42018-08-01 11:34:49 -04003192 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003193 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003194 {
3195 return false;
3196 }
3197
Jamie Madill0063c512014-08-25 15:47:53 -04003198 if (!programObject || !programObject->isLinked())
3199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003201 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003202 }
3203
Geoff Lang7dd2e102014-11-10 15:19:26 -05003204 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003206 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003207 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003208 }
3209
Jamie Madill0063c512014-08-25 15:47:53 -04003210 return true;
3211}
3212
Geoff Langf41d0ee2016-10-07 13:04:23 -04003213static bool ValidateSizedGetUniform(Context *context,
3214 GLuint program,
3215 GLint location,
3216 GLsizei bufSize,
3217 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003218{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003219 if (length)
3220 {
3221 *length = 0;
3222 }
3223
Jamie Madill78f41802014-08-25 15:47:55 -04003224 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003225 {
Jamie Madill78f41802014-08-25 15:47:55 -04003226 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003227 }
3228
Geoff Langf41d0ee2016-10-07 13:04:23 -04003229 if (bufSize < 0)
3230 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003231 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003232 return false;
3233 }
3234
Jamie Madill43da7c42018-08-01 11:34:49 -04003235 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003236 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003237
Jamie Madill78f41802014-08-25 15:47:55 -04003238 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003239 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003240 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003241 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003242 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003244 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003245 }
3246
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 if (length)
3248 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003249 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003250 }
3251
Jamie Madill0063c512014-08-25 15:47:53 -04003252 return true;
3253}
3254
He Yunchaoced53ae2016-11-29 15:00:51 +08003255bool ValidateGetnUniformfvEXT(Context *context,
3256 GLuint program,
3257 GLint location,
3258 GLsizei bufSize,
3259 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003260{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003261 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003262}
3263
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003264bool ValidateGetnUniformfvRobustANGLE(Context *context,
3265 GLuint program,
3266 GLint location,
3267 GLsizei bufSize,
3268 GLsizei *length,
3269 GLfloat *params)
3270{
3271 UNIMPLEMENTED();
3272 return false;
3273}
3274
He Yunchaoced53ae2016-11-29 15:00:51 +08003275bool ValidateGetnUniformivEXT(Context *context,
3276 GLuint program,
3277 GLint location,
3278 GLsizei bufSize,
3279 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003280{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003281 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3282}
3283
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003284bool ValidateGetnUniformivRobustANGLE(Context *context,
3285 GLuint program,
3286 GLint location,
3287 GLsizei bufSize,
3288 GLsizei *length,
3289 GLint *params)
3290{
3291 UNIMPLEMENTED();
3292 return false;
3293}
3294
3295bool ValidateGetnUniformuivRobustANGLE(Context *context,
3296 GLuint program,
3297 GLint location,
3298 GLsizei bufSize,
3299 GLsizei *length,
3300 GLuint *params)
3301{
3302 UNIMPLEMENTED();
3303 return false;
3304}
3305
Geoff Langf41d0ee2016-10-07 13:04:23 -04003306bool ValidateGetUniformfvRobustANGLE(Context *context,
3307 GLuint program,
3308 GLint location,
3309 GLsizei bufSize,
3310 GLsizei *length,
3311 GLfloat *params)
3312{
3313 if (!ValidateRobustEntryPoint(context, bufSize))
3314 {
3315 return false;
3316 }
3317
Brandon Jonesd1049182018-03-28 10:02:20 -07003318 GLsizei writeLength = 0;
3319
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003321 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3322 {
3323 return false;
3324 }
3325
3326 SetRobustLengthParam(length, writeLength);
3327
3328 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003329}
3330
3331bool ValidateGetUniformivRobustANGLE(Context *context,
3332 GLuint program,
3333 GLint location,
3334 GLsizei bufSize,
3335 GLsizei *length,
3336 GLint *params)
3337{
3338 if (!ValidateRobustEntryPoint(context, bufSize))
3339 {
3340 return false;
3341 }
3342
Brandon Jonesd1049182018-03-28 10:02:20 -07003343 GLsizei writeLength = 0;
3344
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003346 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3347 {
3348 return false;
3349 }
3350
3351 SetRobustLengthParam(length, writeLength);
3352
3353 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003354}
3355
3356bool ValidateGetUniformuivRobustANGLE(Context *context,
3357 GLuint program,
3358 GLint location,
3359 GLsizei bufSize,
3360 GLsizei *length,
3361 GLuint *params)
3362{
3363 if (!ValidateRobustEntryPoint(context, bufSize))
3364 {
3365 return false;
3366 }
3367
3368 if (context->getClientMajorVersion() < 3)
3369 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003370 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003371 return false;
3372 }
3373
Brandon Jonesd1049182018-03-28 10:02:20 -07003374 GLsizei writeLength = 0;
3375
Geoff Langf41d0ee2016-10-07 13:04:23 -04003376 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003377 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3378 {
3379 return false;
3380 }
3381
3382 SetRobustLengthParam(length, writeLength);
3383
3384 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003385}
3386
He Yunchaoced53ae2016-11-29 15:00:51 +08003387bool ValidateDiscardFramebufferBase(Context *context,
3388 GLenum target,
3389 GLsizei numAttachments,
3390 const GLenum *attachments,
3391 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003392{
3393 if (numAttachments < 0)
3394 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003395 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003396 return false;
3397 }
3398
3399 for (GLsizei i = 0; i < numAttachments; ++i)
3400 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003401 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003402 {
3403 if (defaultFramebuffer)
3404 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003405 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003406 return false;
3407 }
3408
3409 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003411 context->handleError(InvalidOperation() << "Requested color attachment is "
3412 "greater than the maximum supported "
3413 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003414 return false;
3415 }
3416 }
3417 else
3418 {
3419 switch (attachments[i])
3420 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003421 case GL_DEPTH_ATTACHMENT:
3422 case GL_STENCIL_ATTACHMENT:
3423 case GL_DEPTH_STENCIL_ATTACHMENT:
3424 if (defaultFramebuffer)
3425 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003426 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3427 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003428 return false;
3429 }
3430 break;
3431 case GL_COLOR:
3432 case GL_DEPTH:
3433 case GL_STENCIL:
3434 if (!defaultFramebuffer)
3435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003436 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3437 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003438 return false;
3439 }
3440 break;
3441 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003443 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003444 }
3445 }
3446 }
3447
3448 return true;
3449}
3450
Austin Kinross6ee1e782015-05-29 17:05:37 -07003451bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3452{
Jamie Madill007530e2017-12-28 14:27:04 -05003453 if (!context->getExtensions().debugMarker)
3454 {
3455 // The debug marker calls should not set error state
3456 // However, it seems reasonable to set an error state if the extension is not enabled
3457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3458 return false;
3459 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003460
Jamie Madill007530e2017-12-28 14:27:04 -05003461 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003462 if (length < 0)
3463 {
3464 return false;
3465 }
3466
3467 if (marker == nullptr)
3468 {
3469 return false;
3470 }
3471
3472 return true;
3473}
3474
3475bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3476{
Jamie Madill007530e2017-12-28 14:27:04 -05003477 if (!context->getExtensions().debugMarker)
3478 {
3479 // The debug marker calls should not set error state
3480 // However, it seems reasonable to set an error state if the extension is not enabled
3481 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3482 return false;
3483 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003484
Jamie Madill007530e2017-12-28 14:27:04 -05003485 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003486 if (length < 0)
3487 {
3488 return false;
3489 }
3490
3491 if (length > 0 && marker == nullptr)
3492 {
3493 return false;
3494 }
3495
3496 return true;
3497}
3498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003499bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003500{
Geoff Langa8406172015-07-21 16:53:39 -04003501 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003504 return false;
3505 }
3506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003507 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003508 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003509 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003510 if (!context->getExtensions().eglImage)
3511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003512 context->handleError(InvalidEnum()
3513 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003514 }
3515 break;
3516
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003517 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003518 if (!context->getExtensions().eglImageExternal)
3519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3521 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003522 }
Geoff Langa8406172015-07-21 16:53:39 -04003523 break;
3524
3525 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003527 return false;
3528 }
3529
Rafael Cintron05a449a2018-06-20 18:08:04 -07003530 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003531
Jamie Madill61e16b42017-06-19 11:13:23 -04003532 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003533 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003536 return false;
3537 }
3538
Jamie Madill007530e2017-12-28 14:27:04 -05003539 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 context->handleError(InvalidOperation()
3542 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Yuly Novikov2eb54072018-08-22 16:41:26 -04003546 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 context->handleError(InvalidOperation()
3549 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003550 return false;
3551 }
3552
Geoff Langdcab33b2015-07-21 13:03:16 -04003553 return true;
3554}
3555
3556bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003557 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003558 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003559{
Geoff Langa8406172015-07-21 16:53:39 -04003560 if (!context->getExtensions().eglImage)
3561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003562 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003563 return false;
3564 }
3565
3566 switch (target)
3567 {
3568 case GL_RENDERBUFFER:
3569 break;
3570
3571 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003573 return false;
3574 }
3575
Rafael Cintron05a449a2018-06-20 18:08:04 -07003576 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003577
Jamie Madill61e16b42017-06-19 11:13:23 -04003578 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003579 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Yuly Novikov2eb54072018-08-22 16:41:26 -04003585 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidOperation()
3588 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003589 return false;
3590 }
3591
Geoff Langdcab33b2015-07-21 13:03:16 -04003592 return true;
3593}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003594
3595bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3596{
Geoff Lang36167ab2015-12-07 10:27:14 -05003597 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003598 {
3599 // The default VAO should always exist
3600 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003601 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003602 return false;
3603 }
3604
3605 return true;
3606}
3607
Geoff Langc5629752015-12-07 16:29:04 -05003608bool ValidateProgramBinaryBase(Context *context,
3609 GLuint program,
3610 GLenum binaryFormat,
3611 const void *binary,
3612 GLint length)
3613{
3614 Program *programObject = GetValidProgram(context, program);
3615 if (programObject == nullptr)
3616 {
3617 return false;
3618 }
3619
3620 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3621 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3622 programBinaryFormats.end())
3623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003625 return false;
3626 }
3627
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003628 if (context->hasActiveTransformFeedback(program))
3629 {
3630 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003631 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3632 "is associated with an active transform "
3633 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003634 return false;
3635 }
3636
Geoff Langc5629752015-12-07 16:29:04 -05003637 return true;
3638}
3639
3640bool ValidateGetProgramBinaryBase(Context *context,
3641 GLuint program,
3642 GLsizei bufSize,
3643 GLsizei *length,
3644 GLenum *binaryFormat,
3645 void *binary)
3646{
3647 Program *programObject = GetValidProgram(context, program);
3648 if (programObject == nullptr)
3649 {
3650 return false;
3651 }
3652
3653 if (!programObject->isLinked())
3654 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003656 return false;
3657 }
3658
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003659 if (context->getCaps().programBinaryFormats.empty())
3660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003661 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003662 return false;
3663 }
3664
Geoff Langc5629752015-12-07 16:29:04 -05003665 return true;
3666}
Jamie Madillc29968b2016-01-20 11:17:23 -05003667
Jamie Madill5b772312018-03-08 20:28:32 -05003668bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003669{
3670 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003671 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003672 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003673 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3674 return false;
3675 }
3676 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3677 {
3678 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003679 return false;
3680 }
3681
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003682 ASSERT(context->getGLState().getDrawFramebuffer());
3683 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003684 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3685
3686 // This should come first before the check for the default frame buffer
3687 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3688 // rather than INVALID_OPERATION
3689 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3690 {
3691 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3692
3693 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003694 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3695 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003696 {
3697 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003698 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3699 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3700 // 3.1 is still a bit ambiguous about the error, but future specs are
3701 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003703 return false;
3704 }
3705 else if (bufs[colorAttachment] >= maxColorAttachment)
3706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003707 context->handleError(InvalidOperation()
3708 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003709 return false;
3710 }
3711 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3712 frameBufferId != 0)
3713 {
3714 // INVALID_OPERATION-GL is bound to buffer and ith argument
3715 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation()
3717 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003718 return false;
3719 }
3720 }
3721
3722 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3723 // and n is not 1 or bufs is bound to value other than BACK and NONE
3724 if (frameBufferId == 0)
3725 {
3726 if (n != 1)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation()
3729 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003730 return false;
3731 }
3732
3733 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(
3736 InvalidOperation()
3737 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003738 return false;
3739 }
3740 }
3741
3742 return true;
3743}
3744
Geoff Lang496c02d2016-10-20 11:38:11 -07003745bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003746 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003747 GLenum pname,
3748 GLsizei *length,
3749 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003750{
Geoff Lang496c02d2016-10-20 11:38:11 -07003751 if (length)
3752 {
3753 *length = 0;
3754 }
3755
3756 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3757 {
3758 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 InvalidOperation()
3760 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003761 return false;
3762 }
3763
Corentin Walleze4477002017-12-01 14:39:58 -05003764 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003765 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003766 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003767 return false;
3768 }
3769
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003772 case GL_BUFFER_MAP_POINTER:
3773 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003774
Geoff Lang496c02d2016-10-20 11:38:11 -07003775 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003777 return false;
3778 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003779
3780 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3781 // target bound to zero generate an INVALID_OPERATION error."
3782 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003785 context->handleError(InvalidOperation()
3786 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 return false;
3788 }
3789
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 if (length)
3791 {
3792 *length = 1;
3793 }
3794
Olli Etuaho4f667482016-03-30 15:56:35 +03003795 return true;
3796}
3797
Corentin Wallez336129f2017-10-17 15:55:40 -04003798bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003799{
Corentin Walleze4477002017-12-01 14:39:58 -05003800 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003801 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003802 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 return false;
3804 }
3805
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003806 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003807
3808 if (buffer == nullptr || !buffer->isMapped())
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 return false;
3812 }
3813
3814 return true;
3815}
3816
3817bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003818 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 GLintptr offset,
3820 GLsizeiptr length,
3821 GLbitfield access)
3822{
Corentin Walleze4477002017-12-01 14:39:58 -05003823 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003826 return false;
3827 }
3828
Brandon Jones6cad5662017-06-14 13:25:13 -07003829 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003831 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3832 return false;
3833 }
3834
3835 if (length < 0)
3836 {
3837 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 return false;
3839 }
3840
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003841 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003842
3843 if (!buffer)
3844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003845 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
3849 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003850 CheckedNumeric<size_t> checkedOffset(offset);
3851 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003852
Jamie Madille2e406c2016-06-02 13:04:10 -04003853 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 return false;
3857 }
3858
3859 // Check for invalid bits in the mask
3860 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3861 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3862 GL_MAP_UNSYNCHRONIZED_BIT;
3863
3864 if (access & ~(allAccessBits))
3865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidValue()
3867 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
3871 if (length == 0)
3872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003873 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 return false;
3875 }
3876
3877 if (buffer->isMapped())
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 return false;
3881 }
3882
3883 // Check for invalid bit combinations
3884 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidOperation()
3887 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
3891 GLbitfield writeOnlyBits =
3892 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3893
3894 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidOperation()
3897 << "Invalid access bits when mapping buffer for reading: 0x"
3898 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003904 context->handleError(
3905 InvalidOperation()
3906 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 return false;
3908 }
Geoff Lang79f71042017-08-14 16:43:43 -04003909
3910 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003911}
3912
3913bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003914 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003915 GLintptr offset,
3916 GLsizeiptr length)
3917{
Brandon Jones6cad5662017-06-14 13:25:13 -07003918 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003920 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3921 return false;
3922 }
3923
3924 if (length < 0)
3925 {
3926 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
3929
Corentin Walleze4477002017-12-01 14:39:58 -05003930 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
3935
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003936 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003937
3938 if (buffer == nullptr)
3939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003940 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 return false;
3942 }
3943
3944 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003946 context->handleError(InvalidOperation()
3947 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003948 return false;
3949 }
3950
3951 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003952 CheckedNumeric<size_t> checkedOffset(offset);
3953 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003954
Jamie Madille2e406c2016-06-02 13:04:10 -04003955 if (!checkedSize.IsValid() ||
3956 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidValue()
3959 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003960 return false;
3961 }
3962
3963 return true;
3964}
3965
Olli Etuaho41997e72016-03-10 13:38:39 +02003966bool ValidateGenOrDelete(Context *context, GLint n)
3967{
3968 if (n < 0)
3969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003971 return false;
3972 }
3973 return true;
3974}
3975
Jamie Madill5b772312018-03-08 20:28:32 -05003976bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003977{
3978 if (!context->getExtensions().robustClientMemory)
3979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidOperation()
3981 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003982 return false;
3983 }
3984
3985 if (bufSize < 0)
3986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003987 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003988 return false;
3989 }
3990
3991 return true;
3992}
3993
Jamie Madill5b772312018-03-08 20:28:32 -05003994bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003995{
3996 if (bufSize < numParams)
3997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003998 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3999 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004000 return false;
4001 }
4002
4003 return true;
4004}
4005
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004006bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004007 GLenum target,
4008 GLenum attachment,
4009 GLenum pname,
4010 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004011{
Geoff Lange8afa902017-09-27 15:00:43 -04004012 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004015 return false;
4016 }
4017
4018 int clientVersion = context->getClientMajorVersion();
4019
4020 switch (pname)
4021 {
4022 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4023 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4024 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4025 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4026 break;
4027
Martin Radeve5285d22017-07-14 16:23:53 +03004028 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4031 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4032 if (clientVersion < 3 || !context->getExtensions().multiview)
4033 {
4034 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4035 return false;
4036 }
4037 break;
4038
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4040 if (clientVersion < 3 && !context->getExtensions().sRGB)
4041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004042 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 return false;
4044 }
4045 break;
4046
4047 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4052 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4053 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4054 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4055 if (clientVersion < 3)
4056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004057 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 return false;
4059 }
4060 break;
4061
Jiawei Shaoa8802472018-05-28 11:17:47 +08004062 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4063 if (!context->getExtensions().geometryShader)
4064 {
4065 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4066 return false;
4067 }
4068 break;
4069
Geoff Langff5b2d52016-09-07 11:32:23 -04004070 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004071 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 return false;
4073 }
4074
4075 // Determine if the attachment is a valid enum
4076 switch (attachment)
4077 {
4078 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 case GL_DEPTH:
4080 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 if (clientVersion < 3)
4082 {
Geoff Langfa125c92017-10-24 13:01:46 -04004083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return false;
4085 }
4086 break;
4087
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004088 case GL_DEPTH_STENCIL_ATTACHMENT:
4089 if (clientVersion < 3 && !context->isWebGL1())
4090 {
4091 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4092 return false;
4093 }
4094 break;
4095
Geoff Langfa125c92017-10-24 13:01:46 -04004096 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 case GL_DEPTH_ATTACHMENT:
4098 case GL_STENCIL_ATTACHMENT:
4099 break;
4100
4101 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004102 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4103 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4105 {
Geoff Langfa125c92017-10-24 13:01:46 -04004106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 return false;
4108 }
4109 break;
4110 }
4111
4112 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4113 ASSERT(framebuffer);
4114
4115 if (framebuffer->id() == 0)
4116 {
4117 if (clientVersion < 3)
4118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122
4123 switch (attachment)
4124 {
4125 case GL_BACK:
4126 case GL_DEPTH:
4127 case GL_STENCIL:
4128 break;
4129
4130 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004132 return false;
4133 }
4134 }
4135 else
4136 {
4137 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4138 {
4139 // Valid attachment query
4140 }
4141 else
4142 {
4143 switch (attachment)
4144 {
4145 case GL_DEPTH_ATTACHMENT:
4146 case GL_STENCIL_ATTACHMENT:
4147 break;
4148
4149 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004150 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004152 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004153 return false;
4154 }
4155 break;
4156
4157 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 }
4162 }
4163
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004164 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 if (attachmentObject)
4166 {
4167 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4168 attachmentObject->type() == GL_TEXTURE ||
4169 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4170
4171 switch (pname)
4172 {
4173 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4174 if (attachmentObject->type() != GL_RENDERBUFFER &&
4175 attachmentObject->type() != GL_TEXTURE)
4176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 return false;
4179 }
4180 break;
4181
4182 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4183 if (attachmentObject->type() != GL_TEXTURE)
4184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004186 return false;
4187 }
4188 break;
4189
4190 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4191 if (attachmentObject->type() != GL_TEXTURE)
4192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004194 return false;
4195 }
4196 break;
4197
4198 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4199 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 return false;
4203 }
4204 break;
4205
4206 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4207 if (attachmentObject->type() != GL_TEXTURE)
4208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004210 return false;
4211 }
4212 break;
4213
4214 default:
4215 break;
4216 }
4217 }
4218 else
4219 {
4220 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4221 // is NONE, then querying any other pname will generate INVALID_ENUM.
4222
4223 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4224 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4225 // INVALID_OPERATION for all other pnames
4226
4227 switch (pname)
4228 {
4229 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4230 break;
4231
4232 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4233 if (clientVersion < 3)
4234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004235 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004236 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004237 return false;
4238 }
4239 break;
4240
4241 default:
4242 if (clientVersion < 3)
4243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004244 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004245 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 else
4249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004250 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004251 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004252 return false;
4253 }
4254 }
4255 }
4256
Martin Radeve5285d22017-07-14 16:23:53 +03004257 if (numParams)
4258 {
4259 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4260 {
4261 // Only when the viewport offsets are queried we can have a varying number of output
4262 // parameters.
4263 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4264 *numParams = numViews * 2;
4265 }
4266 else
4267 {
4268 // For all other queries we can have only one output parameter.
4269 *numParams = 1;
4270 }
4271 }
4272
Geoff Langff5b2d52016-09-07 11:32:23 -04004273 return true;
4274}
4275
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004276bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004277 GLenum target,
4278 GLenum attachment,
4279 GLenum pname,
4280 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004281 GLsizei *length,
4282 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
Brandon Jonesd1049182018-03-28 10:02:20 -07004289 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004290 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004291 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 {
4293 return false;
4294 }
4295
Brandon Jonesd1049182018-03-28 10:02:20 -07004296 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004297 {
4298 return false;
4299 }
4300
Brandon Jonesd1049182018-03-28 10:02:20 -07004301 SetRobustLengthParam(length, numParams);
4302
Geoff Langff5b2d52016-09-07 11:32:23 -04004303 return true;
4304}
4305
Jamie Madill5b772312018-03-08 20:28:32 -05004306bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004307 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004308 GLenum pname,
4309 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004310 GLsizei *length,
4311 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004312{
4313 if (!ValidateRobustEntryPoint(context, bufSize))
4314 {
4315 return false;
4316 }
4317
Brandon Jonesd1049182018-03-28 10:02:20 -07004318 GLsizei numParams = 0;
4319
4320 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004321 {
4322 return false;
4323 }
4324
Brandon Jonesd1049182018-03-28 10:02:20 -07004325 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004326 {
4327 return false;
4328 }
4329
Brandon Jonesd1049182018-03-28 10:02:20 -07004330 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004331 return true;
4332}
4333
Jamie Madill5b772312018-03-08 20:28:32 -05004334bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004335 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004336 GLenum pname,
4337 GLsizei bufSize,
4338 GLsizei *length,
4339 GLint64 *params)
4340{
Brandon Jonesd1049182018-03-28 10:02:20 -07004341 GLsizei numParams = 0;
4342
Geoff Langebebe1c2016-10-14 12:01:31 -04004343 if (!ValidateRobustEntryPoint(context, bufSize))
4344 {
4345 return false;
4346 }
4347
Brandon Jonesd1049182018-03-28 10:02:20 -07004348 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004349 {
4350 return false;
4351 }
4352
Brandon Jonesd1049182018-03-28 10:02:20 -07004353 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004354 {
4355 return false;
4356 }
4357
Brandon Jonesd1049182018-03-28 10:02:20 -07004358 SetRobustLengthParam(length, numParams);
4359
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 return true;
4361}
4362
Jamie Madill5b772312018-03-08 20:28:32 -05004363bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004364{
4365 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004366 if (numParams)
4367 {
4368 *numParams = 1;
4369 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004370
4371 Program *programObject = GetValidProgram(context, program);
4372 if (!programObject)
4373 {
4374 return false;
4375 }
4376
4377 switch (pname)
4378 {
4379 case GL_DELETE_STATUS:
4380 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004381 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004382 case GL_VALIDATE_STATUS:
4383 case GL_INFO_LOG_LENGTH:
4384 case GL_ATTACHED_SHADERS:
4385 case GL_ACTIVE_ATTRIBUTES:
4386 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4387 case GL_ACTIVE_UNIFORMS:
4388 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4389 break;
4390
4391 case GL_PROGRAM_BINARY_LENGTH:
4392 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004394 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4395 "requires GL_OES_get_program_binary or "
4396 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004397 return false;
4398 }
4399 break;
4400
4401 case GL_ACTIVE_UNIFORM_BLOCKS:
4402 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4403 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4404 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4405 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4406 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4407 if (context->getClientMajorVersion() < 3)
4408 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004410 return false;
4411 }
4412 break;
4413
Yunchao He61afff12017-03-14 15:34:03 +08004414 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004415 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004416 if (context->getClientVersion() < Version(3, 1))
4417 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004419 return false;
4420 }
4421 break;
4422
Jiawei Shao6ae51612018-02-23 14:03:25 +08004423 case GL_COMPUTE_WORK_GROUP_SIZE:
4424 if (context->getClientVersion() < Version(3, 1))
4425 {
4426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4427 return false;
4428 }
4429
4430 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4431 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4432 // program which has not been linked successfully, or which does not contain objects to
4433 // form a compute shader.
4434 if (!programObject->isLinked())
4435 {
4436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4437 return false;
4438 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004439 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004440 {
4441 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4442 return false;
4443 }
4444 break;
4445
Jiawei Shao447bfac2018-03-14 14:23:40 +08004446 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4447 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4448 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4449 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4450 if (!context->getExtensions().geometryShader)
4451 {
4452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4453 return false;
4454 }
4455
4456 // [EXT_geometry_shader] Chapter 7.12
4457 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4458 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4459 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4460 // successfully, or which does not contain objects to form a geometry shader.
4461 if (!programObject->isLinked())
4462 {
4463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4464 return false;
4465 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004466 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004467 {
4468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4469 return false;
4470 }
4471 break;
4472
Geoff Langff5b2d52016-09-07 11:32:23 -04004473 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004475 return false;
4476 }
4477
4478 return true;
4479}
4480
4481bool ValidateGetProgramivRobustANGLE(Context *context,
4482 GLuint program,
4483 GLenum pname,
4484 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004485 GLsizei *length,
4486 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
Brandon Jonesd1049182018-03-28 10:02:20 -07004493 GLsizei numParams = 0;
4494
4495 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004496 {
4497 return false;
4498 }
4499
Brandon Jonesd1049182018-03-28 10:02:20 -07004500 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004501 {
4502 return false;
4503 }
4504
Brandon Jonesd1049182018-03-28 10:02:20 -07004505 SetRobustLengthParam(length, numParams);
4506
Geoff Langff5b2d52016-09-07 11:32:23 -04004507 return true;
4508}
4509
Geoff Lang740d9022016-10-07 11:20:52 -04004510bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4511 GLenum target,
4512 GLenum pname,
4513 GLsizei bufSize,
4514 GLsizei *length,
4515 GLint *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
Brandon Jonesd1049182018-03-28 10:02:20 -07004522 GLsizei numParams = 0;
4523
4524 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004525 {
4526 return false;
4527 }
4528
Brandon Jonesd1049182018-03-28 10:02:20 -07004529 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004530 {
4531 return false;
4532 }
4533
Brandon Jonesd1049182018-03-28 10:02:20 -07004534 SetRobustLengthParam(length, numParams);
4535
Geoff Lang740d9022016-10-07 11:20:52 -04004536 return true;
4537}
4538
Geoff Langd7d0ed32016-10-07 11:33:51 -04004539bool ValidateGetShaderivRobustANGLE(Context *context,
4540 GLuint shader,
4541 GLenum pname,
4542 GLsizei bufSize,
4543 GLsizei *length,
4544 GLint *params)
4545{
4546 if (!ValidateRobustEntryPoint(context, bufSize))
4547 {
4548 return false;
4549 }
4550
Brandon Jonesd1049182018-03-28 10:02:20 -07004551 GLsizei numParams = 0;
4552
4553 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004554 {
4555 return false;
4556 }
4557
Brandon Jonesd1049182018-03-28 10:02:20 -07004558 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004559 {
4560 return false;
4561 }
4562
Brandon Jonesd1049182018-03-28 10:02:20 -07004563 SetRobustLengthParam(length, numParams);
4564
Geoff Langd7d0ed32016-10-07 11:33:51 -04004565 return true;
4566}
4567
Geoff Langc1984ed2016-10-07 12:41:00 -04004568bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004569 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004570 GLenum pname,
4571 GLsizei bufSize,
4572 GLsizei *length,
4573 GLfloat *params)
4574{
4575 if (!ValidateRobustEntryPoint(context, bufSize))
4576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 GLsizei numParams = 0;
4581
4582 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004583 {
4584 return false;
4585 }
4586
Brandon Jonesd1049182018-03-28 10:02:20 -07004587 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 {
4589 return false;
4590 }
4591
Brandon Jonesd1049182018-03-28 10:02:20 -07004592 SetRobustLengthParam(length, numParams);
4593
Geoff Langc1984ed2016-10-07 12:41:00 -04004594 return true;
4595}
4596
Geoff Langc1984ed2016-10-07 12:41:00 -04004597bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004598 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004599 GLenum pname,
4600 GLsizei bufSize,
4601 GLsizei *length,
4602 GLint *params)
4603{
Brandon Jonesd1049182018-03-28 10:02:20 -07004604
Geoff Langc1984ed2016-10-07 12:41:00 -04004605 if (!ValidateRobustEntryPoint(context, bufSize))
4606 {
4607 return false;
4608 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 GLsizei numParams = 0;
4610 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004611 {
4612 return false;
4613 }
4614
Brandon Jonesd1049182018-03-28 10:02:20 -07004615 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004621 return true;
4622}
4623
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004624bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4625 TextureType target,
4626 GLenum pname,
4627 GLsizei bufSize,
4628 GLsizei *length,
4629 GLint *params)
4630{
4631 UNIMPLEMENTED();
4632 return false;
4633}
4634
4635bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4636 TextureType target,
4637 GLenum pname,
4638 GLsizei bufSize,
4639 GLsizei *length,
4640 GLuint *params)
4641{
4642 UNIMPLEMENTED();
4643 return false;
4644}
4645
Geoff Langc1984ed2016-10-07 12:41:00 -04004646bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004647 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 GLenum pname,
4649 GLsizei bufSize,
4650 const GLfloat *params)
4651{
4652 if (!ValidateRobustEntryPoint(context, bufSize))
4653 {
4654 return false;
4655 }
4656
4657 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4658}
4659
Geoff Langc1984ed2016-10-07 12:41:00 -04004660bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004661 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004662 GLenum pname,
4663 GLsizei bufSize,
4664 const GLint *params)
4665{
4666 if (!ValidateRobustEntryPoint(context, bufSize))
4667 {
4668 return false;
4669 }
4670
4671 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4672}
4673
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004674bool ValidateTexParameterIivRobustANGLE(Context *context,
4675 TextureType target,
4676 GLenum pname,
4677 GLsizei bufSize,
4678 const GLint *params)
4679{
4680 UNIMPLEMENTED();
4681 return false;
4682}
4683
4684bool ValidateTexParameterIuivRobustANGLE(Context *context,
4685 TextureType target,
4686 GLenum pname,
4687 GLsizei bufSize,
4688 const GLuint *params)
4689{
4690 UNIMPLEMENTED();
4691 return false;
4692}
4693
Geoff Langc1984ed2016-10-07 12:41:00 -04004694bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4695 GLuint sampler,
4696 GLenum pname,
4697 GLuint bufSize,
4698 GLsizei *length,
4699 GLfloat *params)
4700{
4701 if (!ValidateRobustEntryPoint(context, bufSize))
4702 {
4703 return false;
4704 }
4705
Brandon Jonesd1049182018-03-28 10:02:20 -07004706 GLsizei numParams = 0;
4707
4708 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004709 {
4710 return false;
4711 }
4712
Brandon Jonesd1049182018-03-28 10:02:20 -07004713 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004714 {
4715 return false;
4716 }
4717
Brandon Jonesd1049182018-03-28 10:02:20 -07004718 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 return true;
4720}
4721
Geoff Langc1984ed2016-10-07 12:41:00 -04004722bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4723 GLuint sampler,
4724 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004725 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004726 GLsizei *length,
4727 GLint *params)
4728{
4729 if (!ValidateRobustEntryPoint(context, bufSize))
4730 {
4731 return false;
4732 }
4733
Brandon Jonesd1049182018-03-28 10:02:20 -07004734 GLsizei numParams = 0;
4735
4736 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004737 {
4738 return false;
4739 }
4740
Brandon Jonesd1049182018-03-28 10:02:20 -07004741 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004742 {
4743 return false;
4744 }
4745
Brandon Jonesd1049182018-03-28 10:02:20 -07004746 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004747 return true;
4748}
4749
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004750bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4751 GLuint sampler,
4752 GLenum pname,
4753 GLsizei bufSize,
4754 GLsizei *length,
4755 GLint *params)
4756{
4757 UNIMPLEMENTED();
4758 return false;
4759}
4760
4761bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4762 GLuint sampler,
4763 GLenum pname,
4764 GLsizei bufSize,
4765 GLsizei *length,
4766 GLuint *params)
4767{
4768 UNIMPLEMENTED();
4769 return false;
4770}
4771
Geoff Langc1984ed2016-10-07 12:41:00 -04004772bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4773 GLuint sampler,
4774 GLenum pname,
4775 GLsizei bufSize,
4776 const GLfloat *params)
4777{
4778 if (!ValidateRobustEntryPoint(context, bufSize))
4779 {
4780 return false;
4781 }
4782
4783 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4784}
4785
Geoff Langc1984ed2016-10-07 12:41:00 -04004786bool ValidateSamplerParameterivRobustANGLE(Context *context,
4787 GLuint sampler,
4788 GLenum pname,
4789 GLsizei bufSize,
4790 const GLint *params)
4791{
4792 if (!ValidateRobustEntryPoint(context, bufSize))
4793 {
4794 return false;
4795 }
4796
4797 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4798}
4799
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004800bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4801 GLuint sampler,
4802 GLenum pname,
4803 GLsizei bufSize,
4804 const GLint *param)
4805{
4806 UNIMPLEMENTED();
4807 return false;
4808}
4809
4810bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4811 GLuint sampler,
4812 GLenum pname,
4813 GLsizei bufSize,
4814 const GLuint *param)
4815{
4816 UNIMPLEMENTED();
4817 return false;
4818}
4819
Geoff Lang0b031062016-10-13 14:30:04 -04004820bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4821 GLuint index,
4822 GLenum pname,
4823 GLsizei bufSize,
4824 GLsizei *length,
4825 GLfloat *params)
4826{
4827 if (!ValidateRobustEntryPoint(context, bufSize))
4828 {
4829 return false;
4830 }
4831
Brandon Jonesd1049182018-03-28 10:02:20 -07004832 GLsizei writeLength = 0;
4833
4834 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004835 {
4836 return false;
4837 }
4838
Brandon Jonesd1049182018-03-28 10:02:20 -07004839 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004840 {
4841 return false;
4842 }
4843
Brandon Jonesd1049182018-03-28 10:02:20 -07004844 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004845 return true;
4846}
4847
Geoff Lang0b031062016-10-13 14:30:04 -04004848bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4849 GLuint index,
4850 GLenum pname,
4851 GLsizei bufSize,
4852 GLsizei *length,
4853 GLint *params)
4854{
4855 if (!ValidateRobustEntryPoint(context, bufSize))
4856 {
4857 return false;
4858 }
4859
Brandon Jonesd1049182018-03-28 10:02:20 -07004860 GLsizei writeLength = 0;
4861
4862 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004863 {
4864 return false;
4865 }
4866
Brandon Jonesd1049182018-03-28 10:02:20 -07004867 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004868 {
4869 return false;
4870 }
4871
Brandon Jonesd1049182018-03-28 10:02:20 -07004872 SetRobustLengthParam(length, writeLength);
4873
Geoff Lang0b031062016-10-13 14:30:04 -04004874 return true;
4875}
4876
Geoff Lang0b031062016-10-13 14:30:04 -04004877bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4878 GLuint index,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 GLsizei *length,
4882 void **pointer)
4883{
4884 if (!ValidateRobustEntryPoint(context, bufSize))
4885 {
4886 return false;
4887 }
4888
Brandon Jonesd1049182018-03-28 10:02:20 -07004889 GLsizei writeLength = 0;
4890
4891 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004892 {
4893 return false;
4894 }
4895
Brandon Jonesd1049182018-03-28 10:02:20 -07004896 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004897 {
4898 return false;
4899 }
4900
Brandon Jonesd1049182018-03-28 10:02:20 -07004901 SetRobustLengthParam(length, writeLength);
4902
Geoff Lang0b031062016-10-13 14:30:04 -04004903 return true;
4904}
4905
Geoff Lang0b031062016-10-13 14:30:04 -04004906bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4907 GLuint index,
4908 GLenum pname,
4909 GLsizei bufSize,
4910 GLsizei *length,
4911 GLint *params)
4912{
4913 if (!ValidateRobustEntryPoint(context, bufSize))
4914 {
4915 return false;
4916 }
4917
Brandon Jonesd1049182018-03-28 10:02:20 -07004918 GLsizei writeLength = 0;
4919
4920 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004921 {
4922 return false;
4923 }
4924
Brandon Jonesd1049182018-03-28 10:02:20 -07004925 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004926 {
4927 return false;
4928 }
4929
Brandon Jonesd1049182018-03-28 10:02:20 -07004930 SetRobustLengthParam(length, writeLength);
4931
Geoff Lang0b031062016-10-13 14:30:04 -04004932 return true;
4933}
4934
Geoff Lang0b031062016-10-13 14:30:04 -04004935bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4936 GLuint index,
4937 GLenum pname,
4938 GLsizei bufSize,
4939 GLsizei *length,
4940 GLuint *params)
4941{
4942 if (!ValidateRobustEntryPoint(context, bufSize))
4943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 GLsizei writeLength = 0;
4948
4949 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004950 {
4951 return false;
4952 }
4953
Brandon Jonesd1049182018-03-28 10:02:20 -07004954 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004955 {
4956 return false;
4957 }
4958
Brandon Jonesd1049182018-03-28 10:02:20 -07004959 SetRobustLengthParam(length, writeLength);
4960
Geoff Lang0b031062016-10-13 14:30:04 -04004961 return true;
4962}
4963
Geoff Lang6899b872016-10-14 11:30:13 -04004964bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4965 GLuint program,
4966 GLuint uniformBlockIndex,
4967 GLenum pname,
4968 GLsizei bufSize,
4969 GLsizei *length,
4970 GLint *params)
4971{
4972 if (!ValidateRobustEntryPoint(context, bufSize))
4973 {
4974 return false;
4975 }
4976
Brandon Jonesd1049182018-03-28 10:02:20 -07004977 GLsizei writeLength = 0;
4978
4979 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4980 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004981 {
4982 return false;
4983 }
4984
Brandon Jonesd1049182018-03-28 10:02:20 -07004985 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004986 {
4987 return false;
4988 }
4989
Brandon Jonesd1049182018-03-28 10:02:20 -07004990 SetRobustLengthParam(length, writeLength);
4991
Geoff Lang6899b872016-10-14 11:30:13 -04004992 return true;
4993}
4994
Brandon Jones416aaf92018-04-10 08:10:16 -07004995bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004996 GLenum target,
4997 GLenum internalformat,
4998 GLenum pname,
4999 GLsizei bufSize,
5000 GLsizei *length,
5001 GLint *params)
5002{
5003 if (!ValidateRobustEntryPoint(context, bufSize))
5004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 GLsizei numParams = 0;
5009
5010 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5011 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005012 {
5013 return false;
5014 }
5015
Brandon Jonesd1049182018-03-28 10:02:20 -07005016 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005017 {
5018 return false;
5019 }
5020
Brandon Jonesd1049182018-03-28 10:02:20 -07005021 SetRobustLengthParam(length, numParams);
5022
Geoff Lang0a9661f2016-10-20 10:59:20 -07005023 return true;
5024}
5025
Jamie Madill5b772312018-03-08 20:28:32 -05005026bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005027 GLuint attribIndex,
5028 GLint size,
5029 GLenum type,
5030 GLboolean pureInteger)
5031{
5032 const Caps &caps = context->getCaps();
5033 if (attribIndex >= caps.maxVertexAttributes)
5034 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005035 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005036 return false;
5037 }
5038
5039 if (size < 1 || size > 4)
5040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005041 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005042 return false;
Shao80957d92017-02-20 21:25:59 +08005043 }
5044
5045 switch (type)
5046 {
5047 case GL_BYTE:
5048 case GL_UNSIGNED_BYTE:
5049 case GL_SHORT:
5050 case GL_UNSIGNED_SHORT:
5051 break;
5052
5053 case GL_INT:
5054 case GL_UNSIGNED_INT:
5055 if (context->getClientMajorVersion() < 3)
5056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005057 context->handleError(InvalidEnum()
5058 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005059 return false;
5060 }
5061 break;
5062
5063 case GL_FIXED:
5064 case GL_FLOAT:
5065 if (pureInteger)
5066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005068 return false;
5069 }
5070 break;
5071
5072 case GL_HALF_FLOAT:
5073 if (context->getClientMajorVersion() < 3)
5074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005075 context->handleError(InvalidEnum()
5076 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005077 return false;
5078 }
5079 if (pureInteger)
5080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005082 return false;
5083 }
5084 break;
5085
5086 case GL_INT_2_10_10_10_REV:
5087 case GL_UNSIGNED_INT_2_10_10_10_REV:
5088 if (context->getClientMajorVersion() < 3)
5089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005090 context->handleError(InvalidEnum()
5091 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005092 return false;
5093 }
5094 if (pureInteger)
5095 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005097 return false;
5098 }
5099 if (size != 4)
5100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005101 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5102 "UNSIGNED_INT_2_10_10_10_REV and "
5103 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005104 return false;
5105 }
5106 break;
5107
5108 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005110 return false;
5111 }
5112
5113 return true;
5114}
5115
Geoff Lang76e65652017-03-27 14:58:02 -04005116// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5117// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5118// specified clear value and the type of a buffer that is being cleared generates an
5119// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005120bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005121 GLint drawbuffer,
5122 const GLenum *validComponentTypes,
5123 size_t validComponentTypeCount)
5124{
5125 const FramebufferAttachment *attachment =
5126 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5127 if (attachment)
5128 {
5129 GLenum componentType = attachment->getFormat().info->componentType;
5130 const GLenum *end = validComponentTypes + validComponentTypeCount;
5131 if (std::find(validComponentTypes, end, componentType) == end)
5132 {
5133 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005134 InvalidOperation()
5135 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005136 return false;
5137 }
5138 }
5139
5140 return true;
5141}
5142
Jamie Madill5b772312018-03-08 20:28:32 -05005143bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005144{
5145 if (!ValidateRobustEntryPoint(context, dataSize))
5146 {
5147 return false;
5148 }
5149
Jamie Madill43da7c42018-08-01 11:34:49 -04005150 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005151 if (pixelUnpackBuffer == nullptr)
5152 {
5153 if (dataSize < imageSize)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005156 }
5157 }
5158 return true;
5159}
5160
Jamie Madill5b772312018-03-08 20:28:32 -05005161bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005162 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005163 GLenum pname,
5164 bool pointerVersion,
5165 GLsizei *numParams)
5166{
5167 if (numParams)
5168 {
5169 *numParams = 0;
5170 }
5171
Corentin Walleze4477002017-12-01 14:39:58 -05005172 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177
5178 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5179 if (!buffer)
5180 {
5181 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005183 return false;
5184 }
5185
5186 const Extensions &extensions = context->getExtensions();
5187
5188 switch (pname)
5189 {
5190 case GL_BUFFER_USAGE:
5191 case GL_BUFFER_SIZE:
5192 break;
5193
5194 case GL_BUFFER_ACCESS_OES:
5195 if (!extensions.mapBuffer)
5196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005197 context->handleError(InvalidEnum()
5198 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005199 return false;
5200 }
5201 break;
5202
5203 case GL_BUFFER_MAPPED:
5204 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5205 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5206 !extensions.mapBufferRange)
5207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005208 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5209 "GL_OES_mapbuffer or "
5210 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 return false;
5212 }
5213 break;
5214
5215 case GL_BUFFER_MAP_POINTER:
5216 if (!pointerVersion)
5217 {
5218 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005219 InvalidEnum()
5220 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005221 return false;
5222 }
5223 break;
5224
5225 case GL_BUFFER_ACCESS_FLAGS:
5226 case GL_BUFFER_MAP_OFFSET:
5227 case GL_BUFFER_MAP_LENGTH:
5228 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005230 context->handleError(InvalidEnum()
5231 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234 break;
5235
5236 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 return false;
5239 }
5240
5241 // All buffer parameter queries return one value.
5242 if (numParams)
5243 {
5244 *numParams = 1;
5245 }
5246
5247 return true;
5248}
5249
5250bool ValidateGetRenderbufferParameterivBase(Context *context,
5251 GLenum target,
5252 GLenum pname,
5253 GLsizei *length)
5254{
5255 if (length)
5256 {
5257 *length = 0;
5258 }
5259
5260 if (target != GL_RENDERBUFFER)
5261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5267 if (renderbuffer == nullptr)
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
5273 switch (pname)
5274 {
5275 case GL_RENDERBUFFER_WIDTH:
5276 case GL_RENDERBUFFER_HEIGHT:
5277 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5278 case GL_RENDERBUFFER_RED_SIZE:
5279 case GL_RENDERBUFFER_GREEN_SIZE:
5280 case GL_RENDERBUFFER_BLUE_SIZE:
5281 case GL_RENDERBUFFER_ALPHA_SIZE:
5282 case GL_RENDERBUFFER_DEPTH_SIZE:
5283 case GL_RENDERBUFFER_STENCIL_SIZE:
5284 break;
5285
5286 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5287 if (!context->getExtensions().framebufferMultisample)
5288 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005289 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005290 return false;
5291 }
5292 break;
5293
5294 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
5298
5299 if (length)
5300 {
5301 *length = 1;
5302 }
5303 return true;
5304}
5305
5306bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5307{
5308 if (length)
5309 {
5310 *length = 0;
5311 }
5312
5313 if (GetValidShader(context, shader) == nullptr)
5314 {
5315 return false;
5316 }
5317
5318 switch (pname)
5319 {
5320 case GL_SHADER_TYPE:
5321 case GL_DELETE_STATUS:
5322 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005323 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005324 case GL_INFO_LOG_LENGTH:
5325 case GL_SHADER_SOURCE_LENGTH:
5326 break;
5327
5328 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5329 if (!context->getExtensions().translatedShaderSource)
5330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005331 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334 break;
5335
5336 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340
5341 if (length)
5342 {
5343 *length = 1;
5344 }
5345 return true;
5346}
5347
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005348bool ValidateGetTexParameterBase(Context *context,
5349 TextureType target,
5350 GLenum pname,
5351 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005352{
5353 if (length)
5354 {
5355 *length = 0;
5356 }
5357
5358 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
5364 if (context->getTargetTexture(target) == nullptr)
5365 {
5366 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005367 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 return false;
5369 }
5370
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005371 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5372 {
5373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5374 return false;
5375 }
5376
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 switch (pname)
5378 {
5379 case GL_TEXTURE_MAG_FILTER:
5380 case GL_TEXTURE_MIN_FILTER:
5381 case GL_TEXTURE_WRAP_S:
5382 case GL_TEXTURE_WRAP_T:
5383 break;
5384
5385 case GL_TEXTURE_USAGE_ANGLE:
5386 if (!context->getExtensions().textureUsage)
5387 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005389 return false;
5390 }
5391 break;
5392
5393 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005394 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005395 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 return false;
5397 }
5398 break;
5399
5400 case GL_TEXTURE_IMMUTABLE_FORMAT:
5401 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5402 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 return false;
5405 }
5406 break;
5407
5408 case GL_TEXTURE_WRAP_R:
5409 case GL_TEXTURE_IMMUTABLE_LEVELS:
5410 case GL_TEXTURE_SWIZZLE_R:
5411 case GL_TEXTURE_SWIZZLE_G:
5412 case GL_TEXTURE_SWIZZLE_B:
5413 case GL_TEXTURE_SWIZZLE_A:
5414 case GL_TEXTURE_BASE_LEVEL:
5415 case GL_TEXTURE_MAX_LEVEL:
5416 case GL_TEXTURE_MIN_LOD:
5417 case GL_TEXTURE_MAX_LOD:
5418 case GL_TEXTURE_COMPARE_MODE:
5419 case GL_TEXTURE_COMPARE_FUNC:
5420 if (context->getClientMajorVersion() < 3)
5421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005422 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 return false;
5424 }
5425 break;
5426
5427 case GL_TEXTURE_SRGB_DECODE_EXT:
5428 if (!context->getExtensions().textureSRGBDecode)
5429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005430 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005431 return false;
5432 }
5433 break;
5434
Yunchao Hebacaa712018-01-30 14:01:39 +08005435 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5436 if (context->getClientVersion() < Version(3, 1))
5437 {
5438 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5439 return false;
5440 }
5441 break;
5442
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005443 case GL_GENERATE_MIPMAP:
5444 case GL_TEXTURE_CROP_RECT_OES:
5445 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5446 // after GL_OES_draw_texture functionality implemented
5447 if (context->getClientMajorVersion() > 1)
5448 {
5449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5450 return false;
5451 }
5452 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
5458 if (length)
5459 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005460 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 }
5462 return true;
5463}
5464
5465bool ValidateGetVertexAttribBase(Context *context,
5466 GLuint index,
5467 GLenum pname,
5468 GLsizei *length,
5469 bool pointer,
5470 bool pureIntegerEntryPoint)
5471{
5472 if (length)
5473 {
5474 *length = 0;
5475 }
5476
5477 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005479 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005480 return false;
5481 }
5482
5483 if (index >= context->getCaps().maxVertexAttributes)
5484 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005485 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 return false;
5487 }
5488
5489 if (pointer)
5490 {
5491 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 return false;
5495 }
5496 }
5497 else
5498 {
5499 switch (pname)
5500 {
5501 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5502 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5503 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5504 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5505 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5506 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5507 case GL_CURRENT_VERTEX_ATTRIB:
5508 break;
5509
5510 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5511 static_assert(
5512 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5513 "ANGLE extension enums not equal to GL enums.");
5514 if (context->getClientMajorVersion() < 3 &&
5515 !context->getExtensions().instancedArrays)
5516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005517 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5518 "requires OpenGL ES 3.0 or "
5519 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 return false;
5521 }
5522 break;
5523
5524 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5525 if (context->getClientMajorVersion() < 3)
5526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005527 context->handleError(
5528 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531 break;
5532
5533 case GL_VERTEX_ATTRIB_BINDING:
5534 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5535 if (context->getClientVersion() < ES_3_1)
5536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005537 context->handleError(InvalidEnum()
5538 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005539 return false;
5540 }
5541 break;
5542
5543 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547 }
5548
5549 if (length)
5550 {
5551 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5552 {
5553 *length = 4;
5554 }
5555 else
5556 {
5557 *length = 1;
5558 }
5559 }
5560
5561 return true;
5562}
5563
Jamie Madill4928b7c2017-06-20 12:57:39 -04005564bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 GLint x,
5566 GLint y,
5567 GLsizei width,
5568 GLsizei height,
5569 GLenum format,
5570 GLenum type,
5571 GLsizei bufSize,
5572 GLsizei *length,
5573 GLsizei *columns,
5574 GLsizei *rows,
5575 void *pixels)
5576{
5577 if (length != nullptr)
5578 {
5579 *length = 0;
5580 }
5581 if (rows != nullptr)
5582 {
5583 *rows = 0;
5584 }
5585 if (columns != nullptr)
5586 {
5587 *columns = 0;
5588 }
5589
5590 if (width < 0 || height < 0)
5591 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005592 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005596 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005597
Jamie Madill427064d2018-04-13 16:20:34 -04005598 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602
Jamie Madille98b1b52018-03-08 09:47:23 -05005603 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005605 return false;
5606 }
5607
Jamie Madill690c8eb2018-03-12 15:20:03 -04005608 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 ASSERT(framebuffer);
5610
5611 if (framebuffer->getReadBufferState() == GL_NONE)
5612 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 return false;
5615 }
5616
5617 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5618 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5619 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5620 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5621 // situation is an application error that would lead to a crash in ANGLE.
5622 if (readBuffer == nullptr)
5623 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627
Martin Radev28031682017-07-28 14:47:56 +03005628 // ANGLE_multiview, Revision 1:
5629 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005630 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5631 // in the current read framebuffer is more than one.
5632 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005633 {
5634 context->handleError(InvalidFramebufferOperation()
5635 << "Attempting to read from a multi-view framebuffer.");
5636 return false;
5637 }
5638
Geoff Lang280ba992017-04-18 16:30:58 -04005639 if (context->getExtensions().webglCompatibility)
5640 {
5641 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5642 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5643 // and type before validating the combination of format and type. However, the
5644 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5645 // verifies that GL_INVALID_OPERATION is generated.
5646 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5647 // dEQP/WebGL.
5648 if (!ValidReadPixelsFormatEnum(context, format))
5649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005650 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005651 return false;
5652 }
5653
5654 if (!ValidReadPixelsTypeEnum(context, type))
5655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005657 return false;
5658 }
5659 }
5660
Jamie Madill690c8eb2018-03-12 15:20:03 -04005661 GLenum currentFormat = GL_NONE;
5662 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5663
5664 GLenum currentType = GL_NONE;
5665 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5666
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5668
5669 bool validFormatTypeCombination =
5670 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5671
5672 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5673 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005675 return false;
5676 }
5677
5678 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005679 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5681 {
5682 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005683 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 return false;
5685 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005686 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5687 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5688 {
5689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5690 return false;
5691 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005692
5693 // .. the data would be packed to the buffer object such that the memory writes required
5694 // would exceed the data store size.
5695 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005696 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005697 const auto &pack = context->getGLState().getPackState();
5698
Jamie Madillca2ff382018-07-11 09:01:17 -04005699 GLuint endByte = 0;
5700 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005701 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 return false;
5704 }
5705
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 if (bufSize >= 0)
5707 {
5708 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5709 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713 }
5714
5715 if (pixelPackBuffer != nullptr)
5716 {
5717 CheckedNumeric<size_t> checkedEndByte(endByte);
5718 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5719 checkedEndByte += checkedOffset;
5720
5721 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5722 {
5723 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 return false;
5726 }
5727 }
5728
5729 if (pixelPackBuffer == nullptr && length != nullptr)
5730 {
5731 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5732 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 return false;
5735 }
5736
5737 *length = static_cast<GLsizei>(endByte);
5738 }
5739
Geoff Langa953b522018-02-21 16:56:23 -05005740 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005741 angle::CheckedNumeric<int> clippedExtent(length);
5742 if (start < 0)
5743 {
5744 // "subtract" the area that is less than 0
5745 clippedExtent += start;
5746 }
5747
Geoff Langa953b522018-02-21 16:56:23 -05005748 angle::CheckedNumeric<int> readExtent = start;
5749 readExtent += length;
5750 if (!readExtent.IsValid())
5751 {
5752 return false;
5753 }
5754
5755 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005756 {
5757 // Subtract the region to the right of the read buffer
5758 clippedExtent -= (readExtent - bufferSize);
5759 }
5760
5761 if (!clippedExtent.IsValid())
5762 {
Geoff Langa953b522018-02-21 16:56:23 -05005763 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005764 }
5765
Geoff Langa953b522018-02-21 16:56:23 -05005766 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5767 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 };
5769
Geoff Langa953b522018-02-21 16:56:23 -05005770 GLsizei writtenColumns = 0;
5771 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5774 return false;
5775 }
5776
5777 GLsizei writtenRows = 0;
5778 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5779 {
5780 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5781 return false;
5782 }
5783
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 if (columns != nullptr)
5785 {
Geoff Langa953b522018-02-21 16:56:23 -05005786 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 }
5788
5789 if (rows != nullptr)
5790 {
Geoff Langa953b522018-02-21 16:56:23 -05005791 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005792 }
5793
5794 return true;
5795}
5796
5797template <typename ParamType>
5798bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005799 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 GLenum pname,
5801 GLsizei bufSize,
5802 const ParamType *params)
5803{
5804 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
5810 if (context->getTargetTexture(target) == nullptr)
5811 {
5812 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005813 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 return false;
5815 }
5816
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005817 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 if (bufSize >= 0 && bufSize < minBufSize)
5819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005820 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005824 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5825 {
5826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5827 return false;
5828 }
5829
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 switch (pname)
5831 {
5832 case GL_TEXTURE_WRAP_R:
5833 case GL_TEXTURE_SWIZZLE_R:
5834 case GL_TEXTURE_SWIZZLE_G:
5835 case GL_TEXTURE_SWIZZLE_B:
5836 case GL_TEXTURE_SWIZZLE_A:
5837 case GL_TEXTURE_BASE_LEVEL:
5838 case GL_TEXTURE_MAX_LEVEL:
5839 case GL_TEXTURE_COMPARE_MODE:
5840 case GL_TEXTURE_COMPARE_FUNC:
5841 case GL_TEXTURE_MIN_LOD:
5842 case GL_TEXTURE_MAX_LOD:
5843 if (context->getClientMajorVersion() < 3)
5844 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005848 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005850 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5851 "available without "
5852 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005853 return false;
5854 }
5855 break;
5856
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005857 case GL_GENERATE_MIPMAP:
5858 case GL_TEXTURE_CROP_RECT_OES:
5859 if (context->getClientMajorVersion() > 1)
5860 {
5861 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5862 return false;
5863 }
5864 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 default:
5866 break;
5867 }
5868
Olli Etuahod310a432018-08-24 15:40:23 +03005869 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005870 {
5871 switch (pname)
5872 {
5873 case GL_TEXTURE_MIN_FILTER:
5874 case GL_TEXTURE_MAG_FILTER:
5875 case GL_TEXTURE_WRAP_S:
5876 case GL_TEXTURE_WRAP_T:
5877 case GL_TEXTURE_WRAP_R:
5878 case GL_TEXTURE_MIN_LOD:
5879 case GL_TEXTURE_MAX_LOD:
5880 case GL_TEXTURE_COMPARE_MODE:
5881 case GL_TEXTURE_COMPARE_FUNC:
5882 context->handleError(InvalidEnum()
5883 << "Invalid parameter for 2D multisampled textures.");
5884 return false;
5885 }
5886 }
5887
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 switch (pname)
5889 {
5890 case GL_TEXTURE_WRAP_S:
5891 case GL_TEXTURE_WRAP_T:
5892 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005893 {
5894 bool restrictedWrapModes =
5895 target == TextureType::External || target == TextureType::Rectangle;
5896 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005898 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005900 }
5901 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005902
5903 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005904 {
5905 bool restrictedMinFilter =
5906 target == TextureType::External || target == TextureType::Rectangle;
5907 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005908 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005909 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005910 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005911 }
5912 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005913
5914 case GL_TEXTURE_MAG_FILTER:
5915 if (!ValidateTextureMagFilterValue(context, params))
5916 {
5917 return false;
5918 }
5919 break;
5920
5921 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005922 if (!context->getExtensions().textureUsage)
5923 {
5924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5925 return false;
5926 }
5927
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 switch (ConvertToGLenum(params[0]))
5929 {
5930 case GL_NONE:
5931 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5932 break;
5933
5934 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 return false;
5937 }
5938 break;
5939
5940 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005941 {
5942 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5943 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005944 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005945 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005947 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5948 }
5949 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005950
5951 case GL_TEXTURE_MIN_LOD:
5952 case GL_TEXTURE_MAX_LOD:
5953 // any value is permissible
5954 break;
5955
5956 case GL_TEXTURE_COMPARE_MODE:
5957 if (!ValidateTextureCompareModeValue(context, params))
5958 {
5959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_COMPARE_FUNC:
5964 if (!ValidateTextureCompareFuncValue(context, params))
5965 {
5966 return false;
5967 }
5968 break;
5969
5970 case GL_TEXTURE_SWIZZLE_R:
5971 case GL_TEXTURE_SWIZZLE_G:
5972 case GL_TEXTURE_SWIZZLE_B:
5973 case GL_TEXTURE_SWIZZLE_A:
5974 switch (ConvertToGLenum(params[0]))
5975 {
5976 case GL_RED:
5977 case GL_GREEN:
5978 case GL_BLUE:
5979 case GL_ALPHA:
5980 case GL_ZERO:
5981 case GL_ONE:
5982 break;
5983
5984 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005985 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005986 return false;
5987 }
5988 break;
5989
5990 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005991 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005993 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 return false;
5995 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005996 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005998 context->handleError(InvalidOperation()
5999 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006000 return false;
6001 }
Olli Etuahod310a432018-08-24 15:40:23 +03006002 if ((target == TextureType::_2DMultisample ||
6003 target == TextureType::_2DMultisampleArray) &&
6004 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006005 {
6006 context->handleError(InvalidOperation()
6007 << "Base level must be 0 for multisampled textures.");
6008 return false;
6009 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006010 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006011 {
6012 context->handleError(InvalidOperation()
6013 << "Base level must be 0 for rectangle textures.");
6014 return false;
6015 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006016 break;
6017
6018 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006019 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006021 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006022 return false;
6023 }
6024 break;
6025
6026 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6027 if (context->getClientVersion() < Version(3, 1))
6028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006029 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006030 return false;
6031 }
6032 switch (ConvertToGLenum(params[0]))
6033 {
6034 case GL_DEPTH_COMPONENT:
6035 case GL_STENCIL_INDEX:
6036 break;
6037
6038 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006039 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 return false;
6041 }
6042 break;
6043
6044 case GL_TEXTURE_SRGB_DECODE_EXT:
6045 if (!ValidateTextureSRGBDecodeValue(context, params))
6046 {
6047 return false;
6048 }
6049 break;
6050
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006051 case GL_GENERATE_MIPMAP:
6052 case GL_TEXTURE_CROP_RECT_OES:
6053 if (context->getClientMajorVersion() > 1)
6054 {
6055 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6056 return false;
6057 }
6058 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006059 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006061 return false;
6062 }
6063
6064 return true;
6065}
6066
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006067template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6068template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006069
Jamie Madill5b772312018-03-08 20:28:32 -05006070bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006071{
6072 if (index >= MAX_VERTEX_ATTRIBS)
6073 {
6074 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6075 return false;
6076 }
6077
6078 return true;
6079}
6080
6081bool ValidateGetActiveUniformBlockivBase(Context *context,
6082 GLuint program,
6083 GLuint uniformBlockIndex,
6084 GLenum pname,
6085 GLsizei *length)
6086{
6087 if (length)
6088 {
6089 *length = 0;
6090 }
6091
6092 if (context->getClientMajorVersion() < 3)
6093 {
6094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6095 return false;
6096 }
6097
6098 Program *programObject = GetValidProgram(context, program);
6099 if (!programObject)
6100 {
6101 return false;
6102 }
6103
6104 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6105 {
6106 context->handleError(InvalidValue()
6107 << "uniformBlockIndex exceeds active uniform block count.");
6108 return false;
6109 }
6110
6111 switch (pname)
6112 {
6113 case GL_UNIFORM_BLOCK_BINDING:
6114 case GL_UNIFORM_BLOCK_DATA_SIZE:
6115 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6116 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6117 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6118 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6119 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6120 break;
6121
6122 default:
6123 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6124 return false;
6125 }
6126
6127 if (length)
6128 {
6129 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6130 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006131 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006132 programObject->getUniformBlockByIndex(uniformBlockIndex);
6133 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6134 }
6135 else
6136 {
6137 *length = 1;
6138 }
6139 }
6140
6141 return true;
6142}
6143
Jamie Madill9696d072017-08-26 23:19:57 -04006144template <typename ParamType>
6145bool ValidateSamplerParameterBase(Context *context,
6146 GLuint sampler,
6147 GLenum pname,
6148 GLsizei bufSize,
6149 ParamType *params)
6150{
6151 if (context->getClientMajorVersion() < 3)
6152 {
6153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6154 return false;
6155 }
6156
6157 if (!context->isSampler(sampler))
6158 {
6159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6160 return false;
6161 }
6162
6163 const GLsizei minBufSize = 1;
6164 if (bufSize >= 0 && bufSize < minBufSize)
6165 {
6166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6167 return false;
6168 }
6169
6170 switch (pname)
6171 {
6172 case GL_TEXTURE_WRAP_S:
6173 case GL_TEXTURE_WRAP_T:
6174 case GL_TEXTURE_WRAP_R:
6175 if (!ValidateTextureWrapModeValue(context, params, false))
6176 {
6177 return false;
6178 }
6179 break;
6180
6181 case GL_TEXTURE_MIN_FILTER:
6182 if (!ValidateTextureMinFilterValue(context, params, false))
6183 {
6184 return false;
6185 }
6186 break;
6187
6188 case GL_TEXTURE_MAG_FILTER:
6189 if (!ValidateTextureMagFilterValue(context, params))
6190 {
6191 return false;
6192 }
6193 break;
6194
6195 case GL_TEXTURE_MIN_LOD:
6196 case GL_TEXTURE_MAX_LOD:
6197 // any value is permissible
6198 break;
6199
6200 case GL_TEXTURE_COMPARE_MODE:
6201 if (!ValidateTextureCompareModeValue(context, params))
6202 {
6203 return false;
6204 }
6205 break;
6206
6207 case GL_TEXTURE_COMPARE_FUNC:
6208 if (!ValidateTextureCompareFuncValue(context, params))
6209 {
6210 return false;
6211 }
6212 break;
6213
6214 case GL_TEXTURE_SRGB_DECODE_EXT:
6215 if (!ValidateTextureSRGBDecodeValue(context, params))
6216 {
6217 return false;
6218 }
6219 break;
6220
Luc Ferron1b1a8642018-01-23 15:12:01 -05006221 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6222 {
6223 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6224 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6225 {
6226 return false;
6227 }
6228 }
6229 break;
6230
Jamie Madill9696d072017-08-26 23:19:57 -04006231 default:
6232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6233 return false;
6234 }
6235
6236 return true;
6237}
6238
6239template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6240template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6241
6242bool ValidateGetSamplerParameterBase(Context *context,
6243 GLuint sampler,
6244 GLenum pname,
6245 GLsizei *length)
6246{
6247 if (length)
6248 {
6249 *length = 0;
6250 }
6251
6252 if (context->getClientMajorVersion() < 3)
6253 {
6254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6255 return false;
6256 }
6257
6258 if (!context->isSampler(sampler))
6259 {
6260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6261 return false;
6262 }
6263
6264 switch (pname)
6265 {
6266 case GL_TEXTURE_WRAP_S:
6267 case GL_TEXTURE_WRAP_T:
6268 case GL_TEXTURE_WRAP_R:
6269 case GL_TEXTURE_MIN_FILTER:
6270 case GL_TEXTURE_MAG_FILTER:
6271 case GL_TEXTURE_MIN_LOD:
6272 case GL_TEXTURE_MAX_LOD:
6273 case GL_TEXTURE_COMPARE_MODE:
6274 case GL_TEXTURE_COMPARE_FUNC:
6275 break;
6276
Luc Ferron1b1a8642018-01-23 15:12:01 -05006277 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6278 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6279 {
6280 return false;
6281 }
6282 break;
6283
Jamie Madill9696d072017-08-26 23:19:57 -04006284 case GL_TEXTURE_SRGB_DECODE_EXT:
6285 if (!context->getExtensions().textureSRGBDecode)
6286 {
6287 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6288 return false;
6289 }
6290 break;
6291
6292 default:
6293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6294 return false;
6295 }
6296
6297 if (length)
6298 {
6299 *length = 1;
6300 }
6301 return true;
6302}
6303
6304bool ValidateGetInternalFormativBase(Context *context,
6305 GLenum target,
6306 GLenum internalformat,
6307 GLenum pname,
6308 GLsizei bufSize,
6309 GLsizei *numParams)
6310{
6311 if (numParams)
6312 {
6313 *numParams = 0;
6314 }
6315
6316 if (context->getClientMajorVersion() < 3)
6317 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006319 return false;
6320 }
6321
6322 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006323 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006324 {
6325 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6326 return false;
6327 }
6328
6329 switch (target)
6330 {
6331 case GL_RENDERBUFFER:
6332 break;
6333
6334 case GL_TEXTURE_2D_MULTISAMPLE:
6335 if (context->getClientVersion() < ES_3_1)
6336 {
Olli Etuahod310a432018-08-24 15:40:23 +03006337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006338 return false;
6339 }
6340 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006341 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6342 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006343 {
6344 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6345 return false;
6346 }
6347 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006348 default:
6349 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6350 return false;
6351 }
6352
6353 if (bufSize < 0)
6354 {
6355 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6356 return false;
6357 }
6358
6359 GLsizei maxWriteParams = 0;
6360 switch (pname)
6361 {
6362 case GL_NUM_SAMPLE_COUNTS:
6363 maxWriteParams = 1;
6364 break;
6365
6366 case GL_SAMPLES:
6367 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6368 break;
6369
6370 default:
6371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6372 return false;
6373 }
6374
6375 if (numParams)
6376 {
6377 // glGetInternalFormativ will not overflow bufSize
6378 *numParams = std::min(bufSize, maxWriteParams);
6379 }
6380
6381 return true;
6382}
6383
Jamie Madille98b1b52018-03-08 09:47:23 -05006384bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6385{
Jamie Madill427064d2018-04-13 16:20:34 -04006386 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006387 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006389 return false;
6390 }
6391 return true;
6392}
6393
Lingfeng Yang038dd532018-03-29 17:31:52 -07006394bool ValidateMultitextureUnit(Context *context, GLenum texture)
6395{
6396 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6397 {
6398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6399 return false;
6400 }
6401 return true;
6402}
6403
Olli Etuahod310a432018-08-24 15:40:23 +03006404bool ValidateTexStorageMultisample(Context *context,
6405 TextureType target,
6406 GLsizei samples,
6407 GLint internalFormat,
6408 GLsizei width,
6409 GLsizei height)
6410{
6411 const Caps &caps = context->getCaps();
6412 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6413 static_cast<GLuint>(height) > caps.max2DTextureSize)
6414 {
6415 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6416 return false;
6417 }
6418
6419 if (samples == 0)
6420 {
6421 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6422 return false;
6423 }
6424
6425 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6426 if (!formatCaps.textureAttachment)
6427 {
6428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6429 return false;
6430 }
6431
6432 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6433 // is one of the unsized base internalformats listed in table 8.11.
6434 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6435 if (formatInfo.internalFormat == GL_NONE)
6436 {
6437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6438 return false;
6439 }
6440
6441 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6442 {
6443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6444 return false;
6445 }
6446
6447 Texture *texture = context->getTargetTexture(target);
6448 if (!texture || texture->id() == 0)
6449 {
6450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6451 return false;
6452 }
6453
6454 if (texture->getImmutableFormat())
6455 {
6456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6457 return false;
6458 }
6459 return true;
6460}
6461
Jamie Madillc29968b2016-01-20 11:17:23 -05006462} // namespace gl