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