blob: eedc1af9ff3ed87285910e991dd4463a8d24fd66 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madill2da53562018-08-01 11:34:47 -040082bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040083{
Jamie Madill51af38b2018-04-15 08:50:56 -040084 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040085 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040086
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040087 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
88 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040090 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -040091 }
James Darpiniane8a93c62018-01-04 18:02:24 -080092
Jamie Madill88602e62018-08-08 12:49:30 -040093 // An overflow can happen when adding the offset. Check against a special constant.
94 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow ||
96 context->getStateCache().getInstancedVertexElementLimit() ==
97 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040098 {
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
100 return false;
101 }
102
103 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
104 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill5b772312018-03-08 20:28:32 -0500109bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400110{
111 switch (type)
112 {
113 // Types referenced in Table 3.4 of the ES 2.0.25 spec
114 case GL_UNSIGNED_BYTE:
115 case GL_UNSIGNED_SHORT_4_4_4_4:
116 case GL_UNSIGNED_SHORT_5_5_5_1:
117 case GL_UNSIGNED_SHORT_5_6_5:
118 return context->getClientVersion() >= ES_2_0;
119
120 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
121 case GL_BYTE:
122 case GL_INT:
123 case GL_SHORT:
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_10F_11F_11F_REV:
126 case GL_UNSIGNED_INT_24_8:
127 case GL_UNSIGNED_INT_2_10_10_10_REV:
128 case GL_UNSIGNED_INT_5_9_9_9_REV:
129 case GL_UNSIGNED_SHORT:
130 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
131 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
132 return context->getClientVersion() >= ES_3_0;
133
134 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400135 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
136 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400137
138 case GL_HALF_FLOAT:
139 return context->getClientVersion() >= ES_3_0 ||
140 context->getExtensions().textureHalfFloat;
141
142 case GL_HALF_FLOAT_OES:
143 return context->getExtensions().colorBufferHalfFloat;
144
145 default:
146 return false;
147 }
148}
149
Jamie Madill5b772312018-03-08 20:28:32 -0500150bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400151{
152 switch (format)
153 {
154 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
155 case GL_RGBA:
156 case GL_RGB:
157 case GL_ALPHA:
158 return context->getClientVersion() >= ES_2_0;
159
160 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
161 case GL_RG:
162 case GL_RED:
163 case GL_RGBA_INTEGER:
164 case GL_RGB_INTEGER:
165 case GL_RG_INTEGER:
166 case GL_RED_INTEGER:
167 return context->getClientVersion() >= ES_3_0;
168
169 case GL_SRGB_ALPHA_EXT:
170 case GL_SRGB_EXT:
171 return context->getExtensions().sRGB;
172
173 case GL_BGRA_EXT:
174 return context->getExtensions().readFormatBGRA;
175
176 default:
177 return false;
178 }
179}
180
Jamie Madill5b772312018-03-08 20:28:32 -0500181bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400182 GLenum framebufferComponentType,
183 GLenum format,
184 GLenum type)
185{
186 switch (framebufferComponentType)
187 {
188 case GL_UNSIGNED_NORMALIZED:
189 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
190 // ReadPixels with BGRA even if the extension is not present
191 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
192 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
193 type == GL_UNSIGNED_BYTE);
194
195 case GL_SIGNED_NORMALIZED:
196 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
197
198 case GL_INT:
199 return (format == GL_RGBA_INTEGER && type == GL_INT);
200
201 case GL_UNSIGNED_INT:
202 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
203
204 case GL_FLOAT:
205 return (format == GL_RGBA && type == GL_FLOAT);
206
207 default:
208 UNREACHABLE();
209 return false;
210 }
211}
212
Geoff Langc1984ed2016-10-07 12:41:00 -0400213template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400214bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400215{
216 switch (ConvertToGLenum(params[0]))
217 {
218 case GL_CLAMP_TO_EDGE:
219 break;
220
221 case GL_REPEAT:
222 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400223 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400224 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400225 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400227 return false;
228 }
229 break;
230
231 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400233 return false;
234 }
235
236 return true;
237}
238
239template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400240bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400241{
242 switch (ConvertToGLenum(params[0]))
243 {
244 case GL_NEAREST:
245 case GL_LINEAR:
246 break;
247
248 case GL_NEAREST_MIPMAP_NEAREST:
249 case GL_LINEAR_MIPMAP_NEAREST:
250 case GL_NEAREST_MIPMAP_LINEAR:
251 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400252 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400253 {
254 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400256 return false;
257 }
258 break;
259
260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400262 return false;
263 }
264
265 return true;
266}
267
268template <typename ParamType>
269bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
270{
271 switch (ConvertToGLenum(params[0]))
272 {
273 case GL_NEAREST:
274 case GL_LINEAR:
275 break;
276
277 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
286bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
287{
288 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_NONE:
292 case GL_COMPARE_REF_TO_TEXTURE:
293 break;
294
295 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 return false;
298 }
299
300 return true;
301}
302
303template <typename ParamType>
304bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
305{
306 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
307 switch (ConvertToGLenum(params[0]))
308 {
309 case GL_LEQUAL:
310 case GL_GEQUAL:
311 case GL_LESS:
312 case GL_GREATER:
313 case GL_EQUAL:
314 case GL_NOTEQUAL:
315 case GL_ALWAYS:
316 case GL_NEVER:
317 break;
318
319 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400321 return false;
322 }
323
324 return true;
325}
326
327template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700328bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
329{
330 if (!context->getExtensions().textureSRGBDecode)
331 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700333 return false;
334 }
335
336 switch (ConvertToGLenum(params[0]))
337 {
338 case GL_DECODE_EXT:
339 case GL_SKIP_DECODE_EXT:
340 break;
341
342 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700344 return false;
345 }
346
347 return true;
348}
349
Luc Ferron1b1a8642018-01-23 15:12:01 -0500350bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
351{
352 if (!context->getExtensions().textureFilterAnisotropic)
353 {
354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
355 return false;
356 }
357
358 return true;
359}
360
361bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
362{
363 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
364 {
365 return false;
366 }
367
368 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
369
370 if (paramValue < 1 || paramValue > largest)
371 {
372 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
373 return false;
374 }
375
376 return true;
377}
378
Jamie Madill5b772312018-03-08 20:28:32 -0500379bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400380{
381 const Program *program = context->getGLState().getProgram();
382 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
383
Jamie Madille7d80f32018-08-08 15:49:23 -0400384 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
385 framebuffer->getDrawBufferTypeMask().to_ulong(),
386 program->getActiveOutputVariables().to_ulong(),
387 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400388}
389
Jamie Madill5b772312018-03-08 20:28:32 -0500390bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400391{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700392 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400393 const Program *program = context->getGLState().getProgram();
394 const VertexArray *vao = context->getGLState().getVertexArray();
395
Brandon Jonesc405ae72017-12-06 14:15:03 -0800396 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
397 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
398 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
399
400 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
401 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
402 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
403
Jamie Madille7d80f32018-08-08 15:49:23 -0400404 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
405 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
406 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400407}
408
Jamie Madill493f9572018-05-24 19:52:15 -0400409bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
410 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800411{
412 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400413 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800414 {
Jamie Madill493f9572018-05-24 19:52:15 -0400415 case PrimitiveMode::Points:
416 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
417 case PrimitiveMode::Lines:
418 case PrimitiveMode::LineStrip:
419 case PrimitiveMode::LineLoop:
420 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
421 case PrimitiveMode::LinesAdjacency:
422 case PrimitiveMode::LineStripAdjacency:
423 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
424 case PrimitiveMode::Triangles:
425 case PrimitiveMode::TriangleFan:
426 case PrimitiveMode::TriangleStrip:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
428 case PrimitiveMode::TrianglesAdjacency:
429 case PrimitiveMode::TriangleStripAdjacency:
430 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800431 default:
432 UNREACHABLE();
433 return false;
434 }
435}
436
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700437// GLES1 texture parameters are a small subset of the others
438bool IsValidGLES1TextureParameter(GLenum pname)
439{
440 switch (pname)
441 {
442 case GL_TEXTURE_MAG_FILTER:
443 case GL_TEXTURE_MIN_FILTER:
444 case GL_TEXTURE_WRAP_S:
445 case GL_TEXTURE_WRAP_T:
446 case GL_TEXTURE_WRAP_R:
447 case GL_GENERATE_MIPMAP:
448 case GL_TEXTURE_CROP_RECT_OES:
449 return true;
450 default:
451 return false;
452 }
453}
Geoff Langf41a7152016-09-19 15:11:17 -0400454} // anonymous namespace
455
Brandon Jonesd1049182018-03-28 10:02:20 -0700456void SetRobustLengthParam(GLsizei *length, GLsizei value)
457{
458 if (length)
459 {
460 *length = value;
461 }
462}
463
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500464bool IsETC2EACFormat(const GLenum format)
465{
466 // ES 3.1, Table 8.19
467 switch (format)
468 {
469 case GL_COMPRESSED_R11_EAC:
470 case GL_COMPRESSED_SIGNED_R11_EAC:
471 case GL_COMPRESSED_RG11_EAC:
472 case GL_COMPRESSED_SIGNED_RG11_EAC:
473 case GL_COMPRESSED_RGB8_ETC2:
474 case GL_COMPRESSED_SRGB8_ETC2:
475 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
476 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
477 case GL_COMPRESSED_RGBA8_ETC2_EAC:
478 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
479 return true;
480
481 default:
482 return false;
483 }
484}
485
Jamie Madill5b772312018-03-08 20:28:32 -0500486bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400487{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800488 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800490 case TextureType::_2D:
491 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800492 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400493
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800494 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400495 return context->getExtensions().textureRectangle;
496
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800497 case TextureType::_3D:
498 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800499 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500500
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 return (context->getClientVersion() >= Version(3, 1));
Olli Etuahod310a432018-08-24 15:40:23 +0300503 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300504 return context->getExtensions().textureStorageMultisample2DArray;
Geoff Lang3b573612016-10-31 14:08:10 -0400505
He Yunchaoced53ae2016-11-29 15:00:51 +0800506 default:
507 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500508 }
Jamie Madill35d15012013-10-07 10:46:37 -0400509}
510
Jamie Madill5b772312018-03-08 20:28:32 -0500511bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500512{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500514 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800515 case TextureType::_2D:
516 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500517 return true;
518
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800519 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400520 return context->getExtensions().textureRectangle;
521
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500522 default:
523 return false;
524 }
525}
526
Jamie Madill5b772312018-03-08 20:28:32 -0500527bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528{
529 switch (target)
530 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800531 case TextureType::_3D:
532 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300533 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534
535 default:
536 return false;
537 }
538}
539
Ian Ewellbda75592016-04-18 17:25:54 -0400540// Most texture GL calls are not compatible with external textures, so we have a separate validation
541// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500542bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400543{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800544 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400545 (context->getExtensions().eglImageExternal ||
546 context->getExtensions().eglStreamConsumerExternal);
547}
548
Shannon Woods4dfed832014-03-17 20:03:39 -0400549// This function differs from ValidTextureTarget in that the target must be
550// usable as the destination of a 2D operation-- so a cube face is valid, but
551// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400552// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500553bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400554{
555 switch (target)
556 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800557 case TextureTarget::_2D:
558 case TextureTarget::CubeMapNegativeX:
559 case TextureTarget::CubeMapNegativeY:
560 case TextureTarget::CubeMapNegativeZ:
561 case TextureTarget::CubeMapPositiveX:
562 case TextureTarget::CubeMapPositiveY:
563 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800564 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400566 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800567 default:
568 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500569 }
570}
571
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800572bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400573 PrimitiveMode transformFeedbackPrimitiveMode,
574 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800575{
576 ASSERT(context);
577
578 if (!context->getExtensions().geometryShader)
579 {
580 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
581 // that does not match the current transform feedback object's draw mode (if transform
582 // feedback is active), (3.0.2, section 2.14, pg 86)
583 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
584 }
585
586 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400587 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800588 {
Jamie Madill493f9572018-05-24 19:52:15 -0400589 case PrimitiveMode::Points:
590 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
591 case PrimitiveMode::Lines:
592 case PrimitiveMode::LineStrip:
593 case PrimitiveMode::LineLoop:
594 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
595 case PrimitiveMode::Triangles:
596 case PrimitiveMode::TriangleFan:
597 case PrimitiveMode::TriangleStrip:
598 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800599 default:
600 UNREACHABLE();
601 return false;
602 }
603}
604
Jamie Madill5b772312018-03-08 20:28:32 -0500605bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400606 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400607 GLsizei count,
608 GLenum type,
609 const GLvoid *indices,
610 GLsizei primcount)
611{
612 if (primcount < 0)
613 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700614 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400615 return false;
616 }
617
618 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
619 {
620 return false;
621 }
622
Jamie Madill9fdaa492018-02-16 10:52:11 -0500623 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400624}
625
626bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400627 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400628 GLint first,
629 GLsizei count,
630 GLsizei primcount)
631{
632 if (primcount < 0)
633 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700634 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 return false;
636 }
637
638 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
639 {
640 return false;
641 }
642
Jamie Madill9fdaa492018-02-16 10:52:11 -0500643 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400644}
645
Jamie Madill5b772312018-03-08 20:28:32 -0500646bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400647{
648 // Verify there is at least one active attribute with a divisor of zero
649 const State &state = context->getGLState();
650
651 Program *program = state.getProgram();
652
653 const auto &attribs = state.getVertexArray()->getVertexAttributes();
654 const auto &bindings = state.getVertexArray()->getVertexBindings();
655 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
656 {
657 const VertexAttribute &attrib = attribs[attributeIndex];
658 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300659 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400660 {
661 return true;
662 }
663 }
664
Brandon Jonesafa75152017-07-21 13:11:29 -0700665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400666 return false;
667}
668
Jamie Madill5b772312018-03-08 20:28:32 -0500669bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500670{
671 switch (target)
672 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800673 case TextureType::_3D:
674 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800675 return true;
676 default:
677 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400678 }
679}
680
Jamie Madill5b772312018-03-08 20:28:32 -0500681bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800682{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800683 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800684 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800685 case TextureType::_2D:
686 case TextureType::_2DArray:
687 case TextureType::_2DMultisample:
688 case TextureType::CubeMap:
689 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800690 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800691 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400692 return context->getExtensions().textureRectangle;
Olli Etuahod310a432018-08-24 15:40:23 +0300693 case TextureType::_2DMultisampleArray:
Olli Etuaho064458a2018-08-30 14:02:02 +0300694 return context->getExtensions().textureStorageMultisample2DArray;
He Yunchao11b038b2016-11-22 21:24:04 +0800695 default:
696 return false;
697 }
698}
699
Jamie Madill5b772312018-03-08 20:28:32 -0500700bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500701{
He Yunchaoced53ae2016-11-29 15:00:51 +0800702 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
703 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400704 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500705
706 switch (target)
707 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_FRAMEBUFFER:
709 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400710
He Yunchaoced53ae2016-11-29 15:00:51 +0800711 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400713 return (context->getExtensions().framebufferBlit ||
714 context->getClientMajorVersion() >= 3);
715
He Yunchaoced53ae2016-11-29 15:00:51 +0800716 default:
717 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500718 }
719}
720
Jamie Madill5b772312018-03-08 20:28:32 -0500721bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400722{
Jamie Madillc29968b2016-01-20 11:17:23 -0500723 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400724 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800725 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400726 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800727 case TextureType::_2D:
728 case TextureType::_2DArray:
729 case TextureType::_2DMultisample:
Olli Etuahod310a432018-08-24 15:40:23 +0300730 case TextureType::_2DMultisampleArray:
731 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
732 // level-of-detail" for multisample textures should be. Could maybe make it zero.
Jamie Madillc29968b2016-01-20 11:17:23 -0500733 maxDimension = caps.max2DTextureSize;
734 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800735 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 maxDimension = caps.maxCubeMapTextureSize;
737 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800738 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400739 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800740 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 maxDimension = caps.max3DTextureSize;
742 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 default:
744 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400745 }
746
Jamie Madill43da7c42018-08-01 11:34:49 -0400747 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400748}
749
Jamie Madill5b772312018-03-08 20:28:32 -0500750bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800751 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700752 GLint level,
753 GLsizei width,
754 GLsizei height,
755 GLsizei depth,
756 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400757{
Brandon Jones6cad5662017-06-14 13:25:13 -0700758 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400759 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700760 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400761 return false;
762 }
Austin Kinross08528e12015-10-07 16:24:40 -0700763 // TexSubImage parameters can be NPOT without textureNPOT extension,
764 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500765 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500766 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500767 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400768 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400769 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700770 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400771 return false;
772 }
773
774 if (!ValidMipLevel(context, target, level))
775 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700776 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400777 return false;
778 }
779
780 return true;
781}
782
Geoff Lang966c9402017-04-18 12:38:27 -0400783bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
784{
785 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
786 (size % blockSize == 0);
787}
788
Jamie Madill5b772312018-03-08 20:28:32 -0500789bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500790 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400791 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500792 GLsizei width,
793 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400794{
Jamie Madill43da7c42018-08-01 11:34:49 -0400795 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400796 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400797 {
798 return false;
799 }
800
Geoff Lang966c9402017-04-18 12:38:27 -0400801 if (width < 0 || height < 0)
802 {
803 return false;
804 }
805
806 if (CompressedTextureFormatRequiresExactSize(internalFormat))
807 {
808 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
809 // block size for level 0 but WebGL disallows this.
810 bool smallerThanBlockSizeAllowed =
811 level > 0 || !context->getExtensions().webglCompatibility;
812
813 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
814 smallerThanBlockSizeAllowed) ||
815 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
816 smallerThanBlockSizeAllowed))
817 {
818 return false;
819 }
820 }
821
822 return true;
823}
824
Jamie Madill5b772312018-03-08 20:28:32 -0500825bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400826 GLenum internalFormat,
827 GLint xoffset,
828 GLint yoffset,
829 GLsizei width,
830 GLsizei height,
831 size_t textureWidth,
832 size_t textureHeight)
833{
Jamie Madill43da7c42018-08-01 11:34:49 -0400834 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400835 if (!formatInfo.compressed)
836 {
837 return false;
838 }
839
Geoff Lang44ff5a72017-02-03 15:15:43 -0500840 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400841 {
842 return false;
843 }
844
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500845 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400846 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500847 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400848 yoffset % formatInfo.compressedBlockHeight != 0)
849 {
850 return false;
851 }
852
853 // Allowed to either have data that is a multiple of block size or is smaller than the block
854 // size but fills the entire mip
855 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
856 static_cast<size_t>(width) == textureWidth &&
857 static_cast<size_t>(height) == textureHeight;
858 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
859 (height % formatInfo.compressedBlockHeight) == 0;
860 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400861 {
862 return false;
863 }
864 }
865
Geoff Langd4f180b2013-09-24 13:57:44 -0400866 return true;
867}
868
Jamie Madill5b772312018-03-08 20:28:32 -0500869bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800870 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400871 GLsizei width,
872 GLsizei height,
873 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400874 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400875 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400876 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400877 GLsizei imageSize)
878{
Jamie Madill43da7c42018-08-01 11:34:49 -0400879 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400880 if (pixelUnpackBuffer == nullptr && imageSize < 0)
881 {
882 // Checks are not required
883 return true;
884 }
885
886 // ...the data would be unpacked from the buffer object such that the memory reads required
887 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400888 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400889 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400890 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 const auto &unpack = context->getGLState().getUnpackState();
892
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800893 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400894 GLuint endByte = 0;
895 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400896 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400898 return false;
899 }
900
Geoff Langff5b2d52016-09-07 11:32:23 -0400901 if (pixelUnpackBuffer)
902 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400903 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400904 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
905 checkedEndByte += checkedOffset;
906
907 if (!checkedEndByte.IsValid() ||
908 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
909 {
910 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400912 return false;
913 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800914 if (context->getExtensions().webglCompatibility &&
915 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
916 {
917 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
918 PixelUnpackBufferBoundForTransformFeedback);
919 return false;
920 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400921 }
922 else
923 {
924 ASSERT(imageSize >= 0);
925 if (pixels == nullptr && imageSize != 0)
926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation()
928 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400929 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400930 }
931
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400932 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500934 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 return false;
936 }
937 }
938
939 return true;
940}
941
Corentin Wallezad3ae902018-03-09 13:40:42 -0500942bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500943{
Geoff Lang37dde692014-01-31 16:34:54 -0500944 switch (queryType)
945 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500946 case QueryType::AnySamples:
947 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400948 return context->getClientMajorVersion() >= 3 ||
949 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500950 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500952 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800953 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500954 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800955 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500956 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800957 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800958 default:
959 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500960 }
961}
962
Jamie Madill5b772312018-03-08 20:28:32 -0500963bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 GLenum type,
965 GLboolean normalized,
966 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400967 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400968 bool pureInteger)
969{
970 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400971 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
972 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
973 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
974 // parameter exceeds 255.
975 constexpr GLsizei kMaxWebGLStride = 255;
976 if (stride > kMaxWebGLStride)
977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500978 context->handleError(InvalidValue()
979 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400980 return false;
981 }
982
983 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
984 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
985 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
986 // or an INVALID_OPERATION error is generated.
987 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
988 size_t typeSize = GetVertexFormatTypeSize(internalType);
989
990 ASSERT(isPow2(typeSize) && typeSize > 0);
991 size_t sizeMask = (typeSize - 1);
992 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
993 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400995 return false;
996 }
997
998 if ((stride & sizeMask) != 0)
999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 return false;
1002 }
1003
1004 return true;
1005}
1006
Jamie Madill5b772312018-03-08 20:28:32 -05001007Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001008{
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1010 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1011 // or program object and INVALID_OPERATION if the provided name identifies an object
1012 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001013
Dian Xiang769769a2015-09-09 15:20:08 -07001014 Program *validProgram = context->getProgram(id);
1015
1016 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001017 {
Dian Xiang769769a2015-09-09 15:20:08 -07001018 if (context->getShader(id))
1019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001021 }
1022 else
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001025 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001026 }
Dian Xiang769769a2015-09-09 15:20:08 -07001027
1028 return validProgram;
1029}
1030
Jamie Madill5b772312018-03-08 20:28:32 -05001031Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001032{
1033 // See ValidProgram for spec details.
1034
1035 Shader *validShader = context->getShader(id);
1036
1037 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038 {
Dian Xiang769769a2015-09-09 15:20:08 -07001039 if (context->getProgram(id))
1040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001042 }
1043 else
1044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001045 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001046 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 }
Dian Xiang769769a2015-09-09 15:20:08 -07001048
1049 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001050}
1051
Jamie Madill43da7c42018-08-01 11:34:49 -04001052bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001053{
Geoff Langfa125c92017-10-24 13:01:46 -04001054 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001055 {
Geoff Langfa125c92017-10-24 13:01:46 -04001056 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1057 {
1058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1059 return false;
1060 }
Jamie Madillb4472272014-07-03 10:38:55 -04001061
Geoff Langfa125c92017-10-24 13:01:46 -04001062 // Color attachment 0 is validated below because it is always valid
1063 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001064 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001065 {
Geoff Langfa125c92017-10-24 13:01:46 -04001066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001067 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001068 }
1069 }
1070 else
1071 {
1072 switch (attachment)
1073 {
Geoff Langfa125c92017-10-24 13:01:46 -04001074 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 case GL_DEPTH_ATTACHMENT:
1076 case GL_STENCIL_ATTACHMENT:
1077 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001078
He Yunchaoced53ae2016-11-29 15:00:51 +08001079 case GL_DEPTH_STENCIL_ATTACHMENT:
1080 if (!context->getExtensions().webglCompatibility &&
1081 context->getClientMajorVersion() < 3)
1082 {
Geoff Langfa125c92017-10-24 13:01:46 -04001083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001084 return false;
1085 }
1086 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001087
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001090 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001091 }
1092 }
1093
1094 return true;
1095}
1096
Jamie Madill5b772312018-03-08 20:28:32 -05001097bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 GLenum target,
1099 GLsizei samples,
1100 GLenum internalformat,
1101 GLsizei width,
1102 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001103{
1104 switch (target)
1105 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 case GL_RENDERBUFFER:
1107 break;
1108 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 }
1112
1113 if (width < 0 || height < 0 || samples < 0)
1114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001116 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 }
1118
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001119 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1120 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1121
1122 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001123 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001125 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 }
1128
1129 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1130 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001131 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001132 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001133 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001137 }
1138
Geoff Langaae65a42014-05-26 12:43:44 -04001139 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001145 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 if (handle == 0)
1147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
1152 return true;
1153}
1154
Jamie Madill43da7c42018-08-01 11:34:49 -04001155bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001156 GLenum target,
1157 GLenum attachment,
1158 GLenum renderbuffertarget,
1159 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001160{
Geoff Lange8afa902017-09-27 15:00:43 -04001161 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001163 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001165 }
1166
Jamie Madill43da7c42018-08-01 11:34:49 -04001167 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001168
Jamie Madill84115c92015-04-23 15:00:07 -04001169 ASSERT(framebuffer);
1170 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001174 }
1175
Jamie Madillb4472272014-07-03 10:38:55 -04001176 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001177 {
Jamie Madillb4472272014-07-03 10:38:55 -04001178 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001179 }
1180
Jamie Madillab9d82c2014-01-21 16:38:14 -05001181 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1182 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1183 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1184 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1185 if (renderbuffer != 0)
1186 {
1187 if (!context->getRenderbuffer(renderbuffer))
1188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001190 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001191 }
1192 }
1193
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001194 return true;
1195}
1196
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001197bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001198 GLint srcX0,
1199 GLint srcY0,
1200 GLint srcX1,
1201 GLint srcY1,
1202 GLint dstX0,
1203 GLint dstY0,
1204 GLint dstX1,
1205 GLint dstY1,
1206 GLbitfield mask,
1207 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001208{
1209 switch (filter)
1210 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001211 case GL_NEAREST:
1212 break;
1213 case GL_LINEAR:
1214 break;
1215 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001218 }
1219
1220 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1221 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001222 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001224 }
1225
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1227 // color buffer, leaving only nearest being unfiltered from above
1228 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1229 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 }
1233
Jamie Madill51f40ec2016-06-15 14:06:00 -04001234 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001235 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1236 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001237
1238 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001240 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001241 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001242 }
1243
Jamie Madill427064d2018-04-13 16:20:34 -04001244 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001245 {
Jamie Madill48faf802014-11-06 15:27:22 -05001246 return false;
1247 }
1248
Jamie Madill427064d2018-04-13 16:20:34 -04001249 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001250 {
Jamie Madill48faf802014-11-06 15:27:22 -05001251 return false;
1252 }
1253
Qin Jiajiaaef92162018-02-27 13:51:44 +08001254 if (readFramebuffer->id() == drawFramebuffer->id())
1255 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001257 return false;
1258 }
1259
Jamie Madille98b1b52018-03-08 09:47:23 -05001260 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 {
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001265 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1266 // always run it in order to avoid triggering driver bugs.
1267 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1268 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001269 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001270 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1271 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001272 }
1273
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1275
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276 if (mask & GL_COLOR_BUFFER_BIT)
1277 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001278 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001279 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280
He Yunchao66a41a22016-12-15 16:45:05 +08001281 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001283 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284
Geoff Langa15472a2015-08-11 11:48:03 -04001285 for (size_t drawbufferIdx = 0;
1286 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 {
Geoff Langa15472a2015-08-11 11:48:03 -04001288 const FramebufferAttachment *attachment =
1289 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1290 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001292 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293
Geoff Langb2f3d052013-08-13 12:49:27 -04001294 // The GL ES 3.0.2 spec (pg 193) states that:
1295 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001296 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1297 // as well
1298 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1299 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001300 // Changes with EXT_color_buffer_float:
1301 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001302 GLenum readComponentType = readFormat.info->componentType;
1303 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001304 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001305 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001306 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001307 drawComponentType == GL_SIGNED_NORMALIZED);
1308
1309 if (extensions.colorBufferFloat)
1310 {
1311 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1312 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1313
1314 if (readFixedOrFloat != drawFixedOrFloat)
1315 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001316 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1317 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001318 return false;
1319 }
1320 }
1321 else if (readFixedPoint != drawFixedPoint)
1322 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001323 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1324 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001325 return false;
1326 }
1327
1328 if (readComponentType == GL_UNSIGNED_INT &&
1329 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001331 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1332 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335
Jamie Madill6163c752015-12-07 16:32:59 -05001336 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1339 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001340 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 }
1342
Jamie Madilla3944d42016-07-22 22:13:26 -04001343 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001344 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001346 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1347 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001348 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 }
Geoff Lange4915782017-04-12 15:19:07 -04001350
1351 if (context->getExtensions().webglCompatibility &&
1352 *readColorBuffer == *attachment)
1353 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001354 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001355 return false;
1356 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 }
1358 }
1359
Jamie Madilla3944d42016-07-22 22:13:26 -04001360 if ((readFormat.info->componentType == GL_INT ||
1361 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1362 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
He Yunchao66a41a22016-12-15 16:45:05 +08001368 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1369 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1370 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1371 // situation is an application error that would lead to a crash in ANGLE.
1372 else if (drawFramebuffer->hasEnabledDrawBuffer())
1373 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001374 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001375 return false;
1376 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001380 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1381 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001383 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001385 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001386 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001387 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001388 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001390 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 {
Kenneth Russell69382852017-07-21 16:38:44 -04001392 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001394 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1395 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001399 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001401 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1402 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
Geoff Lange4915782017-04-12 15:19:07 -04001405
1406 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1407 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
He Yunchao66a41a22016-12-15 16:45:05 +08001412 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1413 else if (drawBuffer)
1414 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001416 return false;
1417 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
1419 }
1420
Martin Radeva3ed4572017-07-27 18:29:37 +03001421 // ANGLE_multiview, Revision 1:
1422 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001423 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1424 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1425 // views in the current read framebuffer is more than one.
1426 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001427 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001428 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001429 return false;
1430 }
1431 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001433 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001434 return false;
1435 }
1436
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 return true;
1438}
1439
Jamie Madill4928b7c2017-06-20 12:57:39 -04001440bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001441 GLint x,
1442 GLint y,
1443 GLsizei width,
1444 GLsizei height,
1445 GLenum format,
1446 GLenum type,
1447 GLsizei bufSize,
1448 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001449 GLsizei *columns,
1450 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001451 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001452{
1453 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001454 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 return false;
1456 }
1457
Brandon Jonesd1049182018-03-28 10:02:20 -07001458 GLsizei writeLength = 0;
1459 GLsizei writeColumns = 0;
1460 GLsizei writeRows = 0;
1461
1462 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1463 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001464 {
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001466 }
1467
Brandon Jonesd1049182018-03-28 10:02:20 -07001468 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001469 {
Geoff Langb1196682014-07-23 13:47:29 -04001470 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001471 }
1472
Brandon Jonesd1049182018-03-28 10:02:20 -07001473 SetRobustLengthParam(length, writeLength);
1474 SetRobustLengthParam(columns, writeColumns);
1475 SetRobustLengthParam(rows, writeRows);
1476
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 return true;
1478}
1479
1480bool ValidateReadnPixelsEXT(Context *context,
1481 GLint x,
1482 GLint y,
1483 GLsizei width,
1484 GLsizei height,
1485 GLenum format,
1486 GLenum type,
1487 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001488 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001489{
1490 if (bufSize < 0)
1491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001492 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Geoff Lang62fce5b2016-09-30 10:46:35 -04001496 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001497 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001498}
Jamie Madill26e91952014-03-05 15:01:27 -05001499
Jamie Madill4928b7c2017-06-20 12:57:39 -04001500bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001501 GLint x,
1502 GLint y,
1503 GLsizei width,
1504 GLsizei height,
1505 GLenum format,
1506 GLenum type,
1507 GLsizei bufSize,
1508 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001509 GLsizei *columns,
1510 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001511 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001512{
Brandon Jonesd1049182018-03-28 10:02:20 -07001513 GLsizei writeLength = 0;
1514 GLsizei writeColumns = 0;
1515 GLsizei writeRows = 0;
1516
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001518 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001519 return false;
1520 }
1521
Brandon Jonesd1049182018-03-28 10:02:20 -07001522 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1523 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001524 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001525 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001526 }
1527
Brandon Jonesd1049182018-03-28 10:02:20 -07001528 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529 {
1530 return false;
1531 }
1532
Brandon Jonesd1049182018-03-28 10:02:20 -07001533 SetRobustLengthParam(length, writeLength);
1534 SetRobustLengthParam(columns, writeColumns);
1535 SetRobustLengthParam(rows, writeRows);
1536
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001538}
1539
Jamie Madill43da7c42018-08-01 11:34:49 -04001540bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001541{
1542 if (!context->getExtensions().occlusionQueryBoolean &&
1543 !context->getExtensions().disjointTimerQuery)
1544 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001546 return false;
1547 }
1548
Olli Etuaho41997e72016-03-10 13:38:39 +02001549 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550}
1551
Jamie Madill43da7c42018-08-01 11:34:49 -04001552bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001553{
1554 if (!context->getExtensions().occlusionQueryBoolean &&
1555 !context->getExtensions().disjointTimerQuery)
1556 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001557 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001558 return false;
1559 }
1560
Olli Etuaho41997e72016-03-10 13:38:39 +02001561 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562}
1563
Jamie Madill43da7c42018-08-01 11:34:49 -04001564bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001565{
1566 if (!context->getExtensions().occlusionQueryBoolean &&
1567 !context->getExtensions().disjointTimerQuery)
1568 {
1569 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1570 return false;
1571 }
1572
1573 return true;
1574}
1575
Jamie Madill43da7c42018-08-01 11:34:49 -04001576bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001577{
1578 if (!ValidQueryType(context, target))
1579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001581 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001582 }
1583
1584 if (id == 0)
1585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001586 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001587 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001588 }
1589
1590 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1591 // of zero, if the active query object name for <target> is non-zero (for the
1592 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1593 // the active query for either target is non-zero), if <id> is the name of an
1594 // existing query object whose type does not match <target>, or if <id> is the
1595 // active query object name for any query type, the error INVALID_OPERATION is
1596 // generated.
1597
1598 // Ensure no other queries are active
1599 // NOTE: If other queries than occlusion are supported, we will need to check
1600 // separately that:
1601 // a) The query ID passed is not the current active query for any target/type
1602 // b) There are no active queries for the requested target (and in the case
1603 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1604 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001605
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001606 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001610 }
1611
1612 Query *queryObject = context->getQuery(id, true, target);
1613
1614 // check that name was obtained with glGenQueries
1615 if (!queryObject)
1616 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001619 }
1620
1621 // check for type mismatch
1622 if (queryObject->getType() != target)
1623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001624 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001626 }
1627
1628 return true;
1629}
1630
Jamie Madill43da7c42018-08-01 11:34:49 -04001631bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632{
1633 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001634 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001637 return false;
1638 }
1639
1640 return ValidateBeginQueryBase(context, target, id);
1641}
1642
Jamie Madill43da7c42018-08-01 11:34:49 -04001643bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001644{
1645 if (!ValidQueryType(context, target))
1646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001649 }
1650
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001651 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001652
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001657 }
1658
Jamie Madill45c785d2014-05-13 14:09:34 -04001659 return true;
1660}
1661
Jamie Madill43da7c42018-08-01 11:34:49 -04001662bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663{
1664 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001665 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668 return false;
1669 }
1670
1671 return ValidateEndQueryBase(context, target);
1672}
1673
Corentin Wallezad3ae902018-03-09 13:40:42 -05001674bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675{
1676 if (!context->getExtensions().disjointTimerQuery)
1677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001678 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679 return false;
1680 }
1681
Corentin Wallezad3ae902018-03-09 13:40:42 -05001682 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685 return false;
1686 }
1687
1688 Query *queryObject = context->getQuery(id, true, target);
1689 if (queryObject == nullptr)
1690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 return false;
1693 }
1694
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001695 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001698 return false;
1699 }
1700
1701 return true;
1702}
1703
Corentin Wallezad3ae902018-03-09 13:40:42 -05001704bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705{
Geoff Lang2186c382016-10-14 10:54:54 -04001706 if (numParams)
1707 {
1708 *numParams = 0;
1709 }
1710
Corentin Wallezad3ae902018-03-09 13:40:42 -05001711 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001713 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 return false;
1715 }
1716
1717 switch (pname)
1718 {
1719 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001720 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001722 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725 break;
1726 case GL_QUERY_COUNTER_BITS_EXT:
1727 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001728 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733 break;
1734 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return false;
1737 }
1738
Geoff Lang2186c382016-10-14 10:54:54 -04001739 if (numParams)
1740 {
1741 // All queries return only one value
1742 *numParams = 1;
1743 }
1744
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return true;
1746}
1747
Corentin Wallezad3ae902018-03-09 13:40:42 -05001748bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749{
1750 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001751 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 return false;
1755 }
1756
Geoff Lang2186c382016-10-14 10:54:54 -04001757 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758}
1759
Geoff Lang2186c382016-10-14 10:54:54 -04001760bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001761 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001762 GLenum pname,
1763 GLsizei bufSize,
1764 GLsizei *length,
1765 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766{
Geoff Lang2186c382016-10-14 10:54:54 -04001767 if (!ValidateRobustEntryPoint(context, bufSize))
1768 {
1769 return false;
1770 }
1771
Brandon Jonesd1049182018-03-28 10:02:20 -07001772 GLsizei numParams = 0;
1773
1774 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001775 {
1776 return false;
1777 }
1778
Brandon Jonesd1049182018-03-28 10:02:20 -07001779 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001780 {
1781 return false;
1782 }
1783
Brandon Jonesd1049182018-03-28 10:02:20 -07001784 SetRobustLengthParam(length, numParams);
1785
Geoff Lang2186c382016-10-14 10:54:54 -04001786 return true;
1787}
1788
1789bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1790{
1791 if (numParams)
1792 {
1793 *numParams = 0;
1794 }
1795
Corentin Wallezad3ae902018-03-09 13:40:42 -05001796 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797
1798 if (!queryObject)
1799 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 return false;
1802 }
1803
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001804 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return false;
1808 }
1809
1810 switch (pname)
1811 {
1812 case GL_QUERY_RESULT_EXT:
1813 case GL_QUERY_RESULT_AVAILABLE_EXT:
1814 break;
1815
1816 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001817 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818 return false;
1819 }
1820
Geoff Lang2186c382016-10-14 10:54:54 -04001821 if (numParams)
1822 {
1823 *numParams = 1;
1824 }
1825
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 return true;
1827}
1828
1829bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1830{
1831 if (!context->getExtensions().disjointTimerQuery)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 return false;
1835 }
Geoff Lang2186c382016-10-14 10:54:54 -04001836 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1837}
1838
1839bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1840 GLuint id,
1841 GLenum pname,
1842 GLsizei bufSize,
1843 GLsizei *length,
1844 GLint *params)
1845{
1846 if (!context->getExtensions().disjointTimerQuery)
1847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001848 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001849 return false;
1850 }
1851
1852 if (!ValidateRobustEntryPoint(context, bufSize))
1853 {
1854 return false;
1855 }
1856
Brandon Jonesd1049182018-03-28 10:02:20 -07001857 GLsizei numParams = 0;
1858
1859 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001860 {
1861 return false;
1862 }
1863
Brandon Jonesd1049182018-03-28 10:02:20 -07001864 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001865 {
1866 return false;
1867 }
1868
Brandon Jonesd1049182018-03-28 10:02:20 -07001869 SetRobustLengthParam(length, numParams);
1870
Geoff Lang2186c382016-10-14 10:54:54 -04001871 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001872}
1873
1874bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1875{
1876 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001877 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001880 return false;
1881 }
Geoff Lang2186c382016-10-14 10:54:54 -04001882 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1883}
1884
1885bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1886 GLuint id,
1887 GLenum pname,
1888 GLsizei bufSize,
1889 GLsizei *length,
1890 GLuint *params)
1891{
1892 if (!context->getExtensions().disjointTimerQuery &&
1893 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001895 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001896 return false;
1897 }
1898
1899 if (!ValidateRobustEntryPoint(context, bufSize))
1900 {
1901 return false;
1902 }
1903
Brandon Jonesd1049182018-03-28 10:02:20 -07001904 GLsizei numParams = 0;
1905
1906 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001907 {
1908 return false;
1909 }
1910
Brandon Jonesd1049182018-03-28 10:02:20 -07001911 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001912 {
1913 return false;
1914 }
1915
Brandon Jonesd1049182018-03-28 10:02:20 -07001916 SetRobustLengthParam(length, numParams);
1917
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919}
1920
1921bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1922{
1923 if (!context->getExtensions().disjointTimerQuery)
1924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926 return false;
1927 }
Geoff Lang2186c382016-10-14 10:54:54 -04001928 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1929}
1930
1931bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1932 GLuint id,
1933 GLenum pname,
1934 GLsizei bufSize,
1935 GLsizei *length,
1936 GLint64 *params)
1937{
1938 if (!context->getExtensions().disjointTimerQuery)
1939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001941 return false;
1942 }
1943
1944 if (!ValidateRobustEntryPoint(context, bufSize))
1945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 GLsizei numParams = 0;
1950
1951 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001952 {
1953 return false;
1954 }
1955
Brandon Jonesd1049182018-03-28 10:02:20 -07001956 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001957 {
1958 return false;
1959 }
1960
Brandon Jonesd1049182018-03-28 10:02:20 -07001961 SetRobustLengthParam(length, numParams);
1962
Geoff Lang2186c382016-10-14 10:54:54 -04001963 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964}
1965
1966bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1967{
1968 if (!context->getExtensions().disjointTimerQuery)
1969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971 return false;
1972 }
Geoff Lang2186c382016-10-14 10:54:54 -04001973 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1974}
1975
1976bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1977 GLuint id,
1978 GLenum pname,
1979 GLsizei bufSize,
1980 GLsizei *length,
1981 GLuint64 *params)
1982{
1983 if (!context->getExtensions().disjointTimerQuery)
1984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001986 return false;
1987 }
1988
1989 if (!ValidateRobustEntryPoint(context, bufSize))
1990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 GLsizei numParams = 0;
1995
1996 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001997 {
1998 return false;
1999 }
2000
Brandon Jonesd1049182018-03-28 10:02:20 -07002001 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002002 {
2003 return false;
2004 }
2005
Brandon Jonesd1049182018-03-28 10:02:20 -07002006 SetRobustLengthParam(length, numParams);
2007
Geoff Lang2186c382016-10-14 10:54:54 -04002008 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009}
2010
Jamie Madill5b772312018-03-08 20:28:32 -05002011bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002012 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002013 GLint location,
2014 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002015 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002016{
Jiajia Qin5451d532017-11-16 17:16:34 +08002017 // TODO(Jiajia): Add image uniform check in future.
2018 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002019 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002020 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002021 return false;
2022 }
2023
Jiajia Qin5451d532017-11-16 17:16:34 +08002024 if (!program)
2025 {
2026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2027 return false;
2028 }
2029
2030 if (!program->isLinked())
2031 {
2032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2033 return false;
2034 }
2035
2036 if (location == -1)
2037 {
2038 // Silently ignore the uniform command
2039 return false;
2040 }
2041
2042 const auto &uniformLocations = program->getUniformLocations();
2043 size_t castedLocation = static_cast<size_t>(location);
2044 if (castedLocation >= uniformLocations.size())
2045 {
2046 context->handleError(InvalidOperation() << "Invalid uniform location");
2047 return false;
2048 }
2049
2050 const auto &uniformLocation = uniformLocations[castedLocation];
2051 if (uniformLocation.ignored)
2052 {
2053 // Silently ignore the uniform command
2054 return false;
2055 }
2056
2057 if (!uniformLocation.used())
2058 {
2059 context->handleError(InvalidOperation());
2060 return false;
2061 }
2062
2063 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2064
2065 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002066 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 {
2068 context->handleError(InvalidOperation());
2069 return false;
2070 }
2071
2072 *uniformOut = &uniform;
2073 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002074}
2075
Jamie Madill5b772312018-03-08 20:28:32 -05002076bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 GLenum uniformType,
2078 GLsizei count,
2079 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002080{
Jiajia Qin5451d532017-11-16 17:16:34 +08002081 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2082 // It is compatible with INT or BOOL.
2083 // Do these cheap tests first, for a little extra speed.
2084 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002085 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002086 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002087 }
2088
Jiajia Qin5451d532017-11-16 17:16:34 +08002089 if (IsSamplerType(uniformType))
2090 {
2091 // Check that the values are in range.
2092 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2093 for (GLsizei i = 0; i < count; ++i)
2094 {
2095 if (value[i] < 0 || value[i] >= max)
2096 {
2097 context->handleError(InvalidValue() << "sampler uniform value out of range");
2098 return false;
2099 }
2100 }
2101 return true;
2102 }
2103
2104 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2105 return false;
2106}
2107
Jamie Madill5b772312018-03-08 20:28:32 -05002108bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002109{
2110 // Check that the value type is compatible with uniform type.
2111 // Do the cheaper test first, for a little extra speed.
2112 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2113 {
2114 return true;
2115 }
2116
2117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2118 return false;
2119}
2120
Jamie Madill5b772312018-03-08 20:28:32 -05002121bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002122{
2123 // Check that the value type is compatible with uniform type.
2124 if (valueType == uniformType)
2125 {
2126 return true;
2127 }
2128
2129 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2130 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002131}
2132
Jamie Madill5b772312018-03-08 20:28:32 -05002133bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002134{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002135 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002136 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002137 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2138 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002139}
2140
Jamie Madill5b772312018-03-08 20:28:32 -05002141bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002142{
2143 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002144 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002145 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2146 ValidateUniform1ivValue(context, uniform->type, count, value);
2147}
2148
Jamie Madill5b772312018-03-08 20:28:32 -05002149bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002150 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002151 GLint location,
2152 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002153 GLboolean transpose)
2154{
Geoff Lang92019432017-11-20 13:09:34 -05002155 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002157 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002158 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002159 }
2160
Jamie Madill62d31cb2015-09-11 13:25:51 -04002161 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002162 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002163 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2164 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165}
2166
Jamie Madill5b772312018-03-08 20:28:32 -05002167bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002168{
2169 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002172 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002173 }
2174
Jamie Madill0af26e12015-03-05 19:54:33 -05002175 const Caps &caps = context->getCaps();
2176
Jamie Madill893ab082014-05-16 16:56:10 -04002177 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2178 {
2179 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2180
Jamie Madill0af26e12015-03-05 19:54:33 -05002181 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002184 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002185 }
2186 }
2187
2188 switch (pname)
2189 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002190 case GL_TEXTURE_BINDING_2D:
2191 case GL_TEXTURE_BINDING_CUBE_MAP:
2192 case GL_TEXTURE_BINDING_3D:
2193 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002194 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002195 break;
Olli Etuahod310a432018-08-24 15:40:23 +03002196 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
Olli Etuaho064458a2018-08-30 14:02:02 +03002197 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03002198 {
2199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
2200 return false;
2201 }
2202 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002203 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2204 if (!context->getExtensions().textureRectangle)
2205 {
2206 context->handleError(InvalidEnum()
2207 << "ANGLE_texture_rectangle extension not present");
2208 return false;
2209 }
2210 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2212 if (!context->getExtensions().eglStreamConsumerExternal &&
2213 !context->getExtensions().eglImageExternal)
2214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2216 "nor GL_OES_EGL_image_external "
2217 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002218 return false;
2219 }
2220 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002221
He Yunchaoced53ae2016-11-29 15:00:51 +08002222 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2223 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002224 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002225 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2226 ASSERT(readFramebuffer);
2227
Jamie Madill427064d2018-04-13 16:20:34 -04002228 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002229 {
Geoff Langb1196682014-07-23 13:47:29 -04002230 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002231 }
2232
Jamie Madille98b1b52018-03-08 09:47:23 -05002233 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002236 return false;
2237 }
2238
Jamie Madille98b1b52018-03-08 09:47:23 -05002239 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002240 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002242 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002243 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002244 }
2245 }
2246 break;
2247
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 default:
2249 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002250 }
2251
2252 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002253 if (*numParams == 0)
2254 {
2255 return false;
2256 }
2257
2258 return true;
2259}
2260
Brandon Jonesd1049182018-03-28 10:02:20 -07002261bool ValidateGetBooleanvRobustANGLE(Context *context,
2262 GLenum pname,
2263 GLsizei bufSize,
2264 GLsizei *length,
2265 GLboolean *params)
2266{
2267 GLenum nativeType;
2268 unsigned int numParams = 0;
2269
2270 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2271 {
2272 return false;
2273 }
2274
2275 SetRobustLengthParam(length, numParams);
2276
2277 return true;
2278}
2279
2280bool ValidateGetFloatvRobustANGLE(Context *context,
2281 GLenum pname,
2282 GLsizei bufSize,
2283 GLsizei *length,
2284 GLfloat *params)
2285{
2286 GLenum nativeType;
2287 unsigned int numParams = 0;
2288
2289 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2290 {
2291 return false;
2292 }
2293
2294 SetRobustLengthParam(length, numParams);
2295
2296 return true;
2297}
2298
2299bool ValidateGetIntegervRobustANGLE(Context *context,
2300 GLenum pname,
2301 GLsizei bufSize,
2302 GLsizei *length,
2303 GLint *data)
2304{
2305 GLenum nativeType;
2306 unsigned int numParams = 0;
2307
2308 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2309 {
2310 return false;
2311 }
2312
2313 SetRobustLengthParam(length, numParams);
2314
2315 return true;
2316}
2317
2318bool ValidateGetInteger64vRobustANGLE(Context *context,
2319 GLenum pname,
2320 GLsizei bufSize,
2321 GLsizei *length,
2322 GLint64 *data)
2323{
2324 GLenum nativeType;
2325 unsigned int numParams = 0;
2326
2327 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2328 {
2329 return false;
2330 }
2331
2332 if (nativeType == GL_INT_64_ANGLEX)
2333 {
2334 CastStateValues(context, nativeType, pname, numParams, data);
2335 return false;
2336 }
2337
2338 SetRobustLengthParam(length, numParams);
2339 return true;
2340}
2341
Jamie Madill5b772312018-03-08 20:28:32 -05002342bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002343 GLenum pname,
2344 GLsizei bufSize,
2345 GLenum *nativeType,
2346 unsigned int *numParams)
2347{
2348 if (!ValidateRobustEntryPoint(context, bufSize))
2349 {
2350 return false;
2351 }
2352
2353 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2354 {
2355 return false;
2356 }
2357
2358 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002359 {
2360 return false;
2361 }
2362
2363 return true;
2364}
2365
Jamie Madill5b772312018-03-08 20:28:32 -05002366bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002367 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002368 GLint level,
2369 GLenum internalformat,
2370 bool isSubImage,
2371 GLint xoffset,
2372 GLint yoffset,
2373 GLint zoffset,
2374 GLint x,
2375 GLint y,
2376 GLsizei width,
2377 GLsizei height,
2378 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002379 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002380{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002381 TextureType texType = TextureTargetToType(target);
2382
Brandon Jones6cad5662017-06-14 13:25:13 -07002383 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002385 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2386 return false;
2387 }
2388
2389 if (width < 0 || height < 0)
2390 {
2391 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002392 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 }
2394
He Yunchaoced53ae2016-11-29 15:00:51 +08002395 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2396 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
2402 if (border != 0)
2403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 }
2407
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002408 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002409 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002410 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002411 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002412 }
2413
Jamie Madill43da7c42018-08-01 11:34:49 -04002414 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002415 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002416 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 {
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002419 }
2420
Jamie Madille98b1b52018-03-08 09:47:23 -05002421 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002422 {
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
Martin Radev138064f2016-07-15 12:03:41 +03002426 if (readFramebuffer->getReadBufferState() == GL_NONE)
2427 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002429 return false;
2430 }
2431
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002432 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2433 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002434 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002435 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002436 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2437 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002440 return false;
2441 }
2442
Martin Radev04e2c3b2017-07-27 16:54:35 +03002443 // ANGLE_multiview spec, Revision 1:
2444 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2445 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002446 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2447 // framebuffer is more than one.
2448 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002449 {
2450 context->handleError(InvalidFramebufferOperation()
2451 << "The active read framebuffer object has multiview attachments.");
2452 return false;
2453 }
2454
Jamie Madill43da7c42018-08-01 11:34:49 -04002455 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002456
Geoff Langaae65a42014-05-26 12:43:44 -04002457 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002458 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002460 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002461 maxDimension = caps.max2DTextureSize;
2462 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002463
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002464 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002465 maxDimension = caps.maxCubeMapTextureSize;
2466 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002467
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002468 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002469 maxDimension = caps.maxRectangleTextureSize;
2470 break;
2471
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002472 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002473 maxDimension = caps.max2DTextureSize;
2474 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002475
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002476 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002477 maxDimension = caps.max3DTextureSize;
2478 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002479
He Yunchaoced53ae2016-11-29 15:00:51 +08002480 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002482 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002483 }
2484
Jamie Madill43da7c42018-08-01 11:34:49 -04002485 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002486 if (!texture)
2487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
Geoff Lang69cce582015-09-17 13:20:36 -04002492 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002494 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496 }
2497
Jamie Madill43da7c42018-08-01 11:34:49 -04002498 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002499 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002500 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002501
Geoff Lang966c9402017-04-18 12:38:27 -04002502 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002505 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 }
2507
2508 if (isSubImage)
2509 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002510 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2511 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2512 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002514 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 }
2517 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002518 else
2519 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002520 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002524 }
2525
Geoff Langeb66a6e2016-10-31 13:06:12 -04002526 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002529 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002530 }
2531
2532 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002533 if (static_cast<int>(width) > maxLevelDimension ||
2534 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002538 }
2539 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002540
Jamie Madill0c8abca2016-07-22 20:21:26 -04002541 if (textureFormatOut)
2542 {
2543 *textureFormatOut = texture->getFormat(target, level);
2544 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002545
2546 // Detect texture copying feedback loops for WebGL.
2547 if (context->getExtensions().webglCompatibility)
2548 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002549 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002550 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002552 return false;
2553 }
2554 }
2555
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 return true;
2557}
2558
Jamie Madillb42162f2018-08-20 12:58:37 -04002559// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2560// completeness check.
2561const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002562{
2563 const Extensions &extensions = context->getExtensions();
2564 const State &state = context->getGLState();
2565
2566 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2567 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2568 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2569 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
2570 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002571 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002572 }
2573
2574 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2575 // Section 6.10 of the WebGL 1.0 spec.
2576 Framebuffer *framebuffer = state.getDrawFramebuffer();
2577 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2578 {
2579 ASSERT(framebuffer);
2580 const FramebufferAttachment *dsAttachment =
2581 framebuffer->getStencilOrDepthStencilAttachment();
2582 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2583 ASSERT(stencilBits <= 8);
2584
2585 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2586 if (depthStencilState.stencilTest && stencilBits > 0)
2587 {
2588 GLuint maxStencilValue = (1 << stencilBits) - 1;
2589
2590 bool differentRefs =
2591 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2592 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2593 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2594 (depthStencilState.stencilBackWritemask & maxStencilValue);
2595 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2596 (depthStencilState.stencilBackMask & maxStencilValue);
2597
2598 if (differentRefs || differentWritemasks || differentMasks)
2599 {
2600 if (!extensions.webglCompatibility)
2601 {
2602 WARN() << "This ANGLE implementation does not support separate front/back "
2603 "stencil writemasks, reference values, or stencil mask values.";
2604 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002605 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002606 }
2607 }
2608 }
2609
2610 if (!framebuffer->isComplete(context))
2611 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002612 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2613 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002614 }
2615
2616 if (context->getStateCache().hasAnyEnabledClientAttrib())
2617 {
2618 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2619 {
2620 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2621 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2622 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2623 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002624 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002625 }
2626
2627 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2628 {
2629 // This is an application error that would normally result in a crash, but we catch it
2630 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002631 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002632 }
2633 }
2634
2635 // If we are running GLES1, there is no current program.
2636 if (context->getClientVersion() >= Version(2, 0))
2637 {
2638 Program *program = state.getProgram();
2639 if (!program)
2640 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002641 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002642 }
2643
2644 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2645 // vertex shader stage or fragment shader stage is a undefined behaviour.
2646 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2647 // produce undefined result.
2648 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2649 !program->hasLinkedShaderStage(ShaderType::Fragment))
2650 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002651 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002652 }
2653
2654 if (!program->validateSamplers(nullptr, context->getCaps()))
2655 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002656 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002657 }
2658
2659 if (extensions.multiview)
2660 {
2661 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2662 const int framebufferNumViews = framebuffer->getNumViews();
2663 if (framebufferNumViews != programNumViews)
2664 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002665 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002666 }
2667
2668 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2669 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2670 framebufferNumViews > 1)
2671 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002672 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002673 }
2674
2675 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2676 state.isQueryActive(QueryType::TimeElapsed))
2677 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002678 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002679 }
2680 }
2681
2682 // Uniform buffer validation
2683 for (unsigned int uniformBlockIndex = 0;
2684 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2685 {
2686 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2687 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2688 const OffsetBindingPointer<Buffer> &uniformBuffer =
2689 state.getIndexedUniformBuffer(blockBinding);
2690
2691 if (uniformBuffer.get() == nullptr)
2692 {
2693 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002694 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002695 }
2696
2697 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2698 if (uniformBufferSize < uniformBlock.dataSize)
2699 {
2700 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002701 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002702 }
2703
2704 if (extensions.webglCompatibility &&
2705 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2706 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002707 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002708 }
2709 }
2710
2711 // Do some additonal WebGL-specific validation
2712 if (extensions.webglCompatibility)
2713 {
2714 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2715 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2716 transformFeedbackObject->buffersBoundForOtherUse())
2717 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002718 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002719 }
2720
2721 // Detect rendering feedback loops for WebGL.
2722 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2723 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002724 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002725 }
2726
2727 // Detect that the vertex shader input types match the attribute types
2728 if (!ValidateVertexShaderAttributeTypeMatch(context))
2729 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002730 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002731 }
2732
2733 // Detect that the color buffer types match the fragment shader output types
2734 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2735 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002736 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002737 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002738
2739 const VertexArray *vao = context->getGLState().getVertexArray();
2740 if (vao->hasTransformFeedbackBindingConflict(context))
2741 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002742 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002743 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002744 }
2745 }
2746
Jamie Madillb42162f2018-08-20 12:58:37 -04002747 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002748}
2749
Jamie Madill493f9572018-05-24 19:52:15 -04002750bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002751{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002752 const Extensions &extensions = context->getExtensions();
2753
Jamie Madill1aeb1312014-06-20 13:21:25 -04002754 switch (mode)
2755 {
Jamie Madill493f9572018-05-24 19:52:15 -04002756 case PrimitiveMode::Points:
2757 case PrimitiveMode::Lines:
2758 case PrimitiveMode::LineLoop:
2759 case PrimitiveMode::LineStrip:
2760 case PrimitiveMode::Triangles:
2761 case PrimitiveMode::TriangleStrip:
2762 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002763 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002764
Jamie Madill493f9572018-05-24 19:52:15 -04002765 case PrimitiveMode::LinesAdjacency:
2766 case PrimitiveMode::LineStripAdjacency:
2767 case PrimitiveMode::TrianglesAdjacency:
2768 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002769 if (!extensions.geometryShader)
2770 {
2771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2772 return false;
2773 }
2774 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002775 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002778 }
2779
Jamie Madill250d33f2014-06-06 17:09:03 -04002780 if (count < 0)
2781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002782 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002783 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002784 }
2785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002786 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002787
Jamie Madillb42162f2018-08-20 12:58:37 -04002788 const char *errorMessage = ValidateDrawStates(context);
2789 if (errorMessage)
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002791 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2792 // Incomplete.
2793 GLenum errorCode =
2794 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2795 : GL_INVALID_OPERATION);
2796 context->handleError(Error(errorCode, errorMessage));
Jamie Madille7d80f32018-08-08 15:49:23 -04002797 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002798 }
2799
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002800 // If we are running GLES1, there is no current program.
2801 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002802 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002803 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002804 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002805
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002806 // Do geometry shader specific validations
2807 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002808 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002809 if (!IsCompatibleDrawModeWithGeometryShader(
2810 mode, program->getGeometryShaderInputPrimitiveType()))
2811 {
2812 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2813 IncompatibleDrawModeAgainstGeometryShader);
2814 return false;
2815 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002816 }
2817 }
2818
Jamie Madill9fdaa492018-02-16 10:52:11 -05002819 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002820}
2821
Jamie Madill5b772312018-03-08 20:28:32 -05002822bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002823 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002824 GLint first,
2825 GLsizei count,
2826 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002827{
Jamie Madillfd716582014-06-06 17:09:04 -04002828 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002830 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002831 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002832 }
2833
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002834 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002835 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002836 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002837 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002838 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002839 if (!ValidateTransformFeedbackPrimitiveMode(context,
2840 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002841 {
James Darpinian30b604d2018-03-12 17:26:57 -07002842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2843 return false;
2844 }
2845
2846 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2847 {
2848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2849 return false;
2850 }
Jamie Madillfd716582014-06-06 17:09:04 -04002851 }
2852
Jiajia Qind9671222016-11-29 16:30:31 +08002853 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002854 {
2855 return false;
2856 }
2857
Corentin Wallez71168a02016-12-19 15:11:18 -08002858 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002859 // - first < 0 has been checked as an error condition.
2860 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002861 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002862 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002863 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002864 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002865 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2866 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2867 {
2868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2869 return false;
2870 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002871
Jamie Madill2da53562018-08-01 11:34:47 -04002872 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002873 {
2874 return false;
2875 }
Jamie Madillfd716582014-06-06 17:09:04 -04002876 }
2877
2878 return true;
2879}
2880
He Yunchaoced53ae2016-11-29 15:00:51 +08002881bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002882 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002883 GLint first,
2884 GLsizei count,
2885 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002886{
Geoff Lang63c5a592017-09-27 14:08:16 -04002887 if (!context->getExtensions().instancedArrays)
2888 {
2889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2890 return false;
2891 }
2892
Corentin Wallez170efbf2017-05-02 13:45:01 -04002893 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002894 {
2895 return false;
2896 }
2897
Corentin Wallez0dc97812017-06-22 14:38:44 -04002898 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002899}
2900
Jamie Madill493f9572018-05-24 19:52:15 -04002901bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002902{
Jamie Madill250d33f2014-06-06 17:09:03 -04002903 switch (type)
2904 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002905 case GL_UNSIGNED_BYTE:
2906 case GL_UNSIGNED_SHORT:
2907 break;
2908 case GL_UNSIGNED_INT:
2909 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002912 return false;
2913 }
2914 break;
2915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002917 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 }
2919
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002920 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002921
Jamie Madill43da7c42018-08-01 11:34:49 -04002922 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002923 if (curTransformFeedback && curTransformFeedback->isActive() &&
2924 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002925 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002926 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2927 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2928 if (context->getExtensions().geometryShader)
2929 {
2930 if (!ValidateTransformFeedbackPrimitiveMode(
2931 context, curTransformFeedback->getPrimitiveMode(), mode))
2932 {
2933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2934 return false;
2935 }
2936 }
2937 else
2938 {
2939 // It is an invalid operation to call DrawElements, DrawRangeElements or
2940 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2941 // 86)
2942 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2943 UnsupportedDrawModeForTransformFeedback);
2944 return false;
2945 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002946 }
2947
Jiajia Qind9671222016-11-29 16:30:31 +08002948 return true;
2949}
2950
Jamie Madill5b772312018-03-08 20:28:32 -05002951bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002952 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002953 GLsizei count,
2954 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002955 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002956 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002957{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002958 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002959 return false;
2960
2961 const State &state = context->getGLState();
2962
Corentin Wallez170efbf2017-05-02 13:45:01 -04002963 if (!ValidateDrawBase(context, mode, count))
2964 {
2965 return false;
2966 }
2967
Jamie Madill43da7c42018-08-01 11:34:49 -04002968 const VertexArray *vao = state.getVertexArray();
2969 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002970
Jamie Madill43da7c42018-08-01 11:34:49 -04002971 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002972
2973 if (context->getExtensions().webglCompatibility)
2974 {
2975 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2976 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2977 {
2978 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2979 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2980 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002982 return false;
2983 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002984
2985 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2986 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2987 // error is generated.
2988 if (reinterpret_cast<intptr_t>(indices) < 0)
2989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002990 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002991 return false;
2992 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002993 }
Jamie Madillcc73f242018-08-01 11:34:48 -04002994 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
2995 {
2996 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2997 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2998 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2999 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3000 return false;
3001 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003002
3003 if (context->getExtensions().webglCompatibility ||
3004 !context->getGLState().areClientArraysEnabled())
3005 {
Brandon Jones2a018152018-06-08 15:59:26 -07003006 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003007 {
3008 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003009 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3010 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003012 return false;
3013 }
3014 }
3015
Jamie Madill9fdaa492018-02-16 10:52:11 -05003016 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003017 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003018 // This is an application error that would normally result in a crash, but we catch it and
3019 // return an error
3020 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3021 return false;
3022 }
3023
3024 if (count > 0 && elementArrayBuffer)
3025 {
3026 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3027 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3028 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3029 constexpr uint64_t kMaxTypeSize = 8;
3030 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3031 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3032 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3033
3034 uint64_t typeSize = typeBytes;
3035 uint64_t elementCount = static_cast<uint64_t>(count);
3036 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3037
3038 // Doing the multiplication here is overflow-safe
3039 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3040
3041 // The offset can be any value, check for overflows
3042 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3043 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003044 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3046 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003047 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003048
3049 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3050 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003051 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3053 return false;
3054 }
3055
3056 ASSERT(isPow2(typeSize) && typeSize > 0);
3057 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3058 {
3059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003061 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003062
3063 if (context->getExtensions().webglCompatibility &&
3064 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3065 {
3066 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3067 ElementArrayBufferBoundForTransformFeedback);
3068 return false;
3069 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003070 }
3071
Jamie Madill2da53562018-08-01 11:34:47 -04003072 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003073 {
3074 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003075 const DrawCallParams &params = context->getParams<DrawCallParams>();
3076 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3077 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003078
3079 // If we use an index greater than our maximum supported index range, return an error.
3080 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3081 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003082 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083 {
3084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3085 return false;
3086 }
3087
Jamie Madill2da53562018-08-01 11:34:47 -04003088 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003089 {
3090 return false;
3091 }
3092
3093 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003094 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003095 }
3096
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003097 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003098}
3099
Jamie Madill5b772312018-03-08 20:28:32 -05003100bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003101 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003102 GLsizei count,
3103 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003104 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003105 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003106{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003107 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003108}
3109
Geoff Lang3edfe032015-09-04 16:38:24 -04003110bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003111 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003112 GLsizei count,
3113 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003114 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003115 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003116{
Geoff Lang63c5a592017-09-27 14:08:16 -04003117 if (!context->getExtensions().instancedArrays)
3118 {
3119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3120 return false;
3121 }
3122
Corentin Wallez170efbf2017-05-02 13:45:01 -04003123 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003124 {
3125 return false;
3126 }
3127
Corentin Wallez0dc97812017-06-22 14:38:44 -04003128 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003129}
3130
He Yunchaoced53ae2016-11-29 15:00:51 +08003131bool ValidateFramebufferTextureBase(Context *context,
3132 GLenum target,
3133 GLenum attachment,
3134 GLuint texture,
3135 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003136{
Geoff Lange8afa902017-09-27 15:00:43 -04003137 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003140 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003141 }
3142
3143 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003144 {
3145 return false;
3146 }
3147
Jamie Madill55ec3b12014-07-03 10:38:57 -04003148 if (texture != 0)
3149 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003150 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003151
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003152 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003154 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003156 }
3157
3158 if (level < 0)
3159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003160 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003161 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003162 }
3163 }
3164
Jamie Madill43da7c42018-08-01 11:34:49 -04003165 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003166 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003167
Jamie Madill84115c92015-04-23 15:00:07 -04003168 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003171 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003172 }
3173
3174 return true;
3175}
3176
Geoff Langb1196682014-07-23 13:47:29 -04003177bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003178{
3179 if (program == 0)
3180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003181 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003182 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003183 }
3184
Jamie Madill43da7c42018-08-01 11:34:49 -04003185 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003186 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003187 {
3188 return false;
3189 }
3190
Jamie Madill0063c512014-08-25 15:47:53 -04003191 if (!programObject || !programObject->isLinked())
3192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003195 }
3196
Geoff Lang7dd2e102014-11-10 15:19:26 -05003197 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003199 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003200 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003201 }
3202
Jamie Madill0063c512014-08-25 15:47:53 -04003203 return true;
3204}
3205
Geoff Langf41d0ee2016-10-07 13:04:23 -04003206static bool ValidateSizedGetUniform(Context *context,
3207 GLuint program,
3208 GLint location,
3209 GLsizei bufSize,
3210 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003211{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003212 if (length)
3213 {
3214 *length = 0;
3215 }
3216
Jamie Madill78f41802014-08-25 15:47:55 -04003217 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003218 {
Jamie Madill78f41802014-08-25 15:47:55 -04003219 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003220 }
3221
Geoff Langf41d0ee2016-10-07 13:04:23 -04003222 if (bufSize < 0)
3223 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003224 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003225 return false;
3226 }
3227
Jamie Madill43da7c42018-08-01 11:34:49 -04003228 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003229 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003230
Jamie Madill78f41802014-08-25 15:47:55 -04003231 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003232 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003233 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003234 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003235 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003238 }
3239
Geoff Langf41d0ee2016-10-07 13:04:23 -04003240 if (length)
3241 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003242 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003243 }
3244
Jamie Madill0063c512014-08-25 15:47:53 -04003245 return true;
3246}
3247
He Yunchaoced53ae2016-11-29 15:00:51 +08003248bool ValidateGetnUniformfvEXT(Context *context,
3249 GLuint program,
3250 GLint location,
3251 GLsizei bufSize,
3252 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003253{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003255}
3256
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003257bool ValidateGetnUniformfvRobustANGLE(Context *context,
3258 GLuint program,
3259 GLint location,
3260 GLsizei bufSize,
3261 GLsizei *length,
3262 GLfloat *params)
3263{
3264 UNIMPLEMENTED();
3265 return false;
3266}
3267
He Yunchaoced53ae2016-11-29 15:00:51 +08003268bool ValidateGetnUniformivEXT(Context *context,
3269 GLuint program,
3270 GLint location,
3271 GLsizei bufSize,
3272 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003273{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003274 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3275}
3276
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003277bool ValidateGetnUniformivRobustANGLE(Context *context,
3278 GLuint program,
3279 GLint location,
3280 GLsizei bufSize,
3281 GLsizei *length,
3282 GLint *params)
3283{
3284 UNIMPLEMENTED();
3285 return false;
3286}
3287
3288bool ValidateGetnUniformuivRobustANGLE(Context *context,
3289 GLuint program,
3290 GLint location,
3291 GLsizei bufSize,
3292 GLsizei *length,
3293 GLuint *params)
3294{
3295 UNIMPLEMENTED();
3296 return false;
3297}
3298
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299bool ValidateGetUniformfvRobustANGLE(Context *context,
3300 GLuint program,
3301 GLint location,
3302 GLsizei bufSize,
3303 GLsizei *length,
3304 GLfloat *params)
3305{
3306 if (!ValidateRobustEntryPoint(context, bufSize))
3307 {
3308 return false;
3309 }
3310
Brandon Jonesd1049182018-03-28 10:02:20 -07003311 GLsizei writeLength = 0;
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003314 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3315 {
3316 return false;
3317 }
3318
3319 SetRobustLengthParam(length, writeLength);
3320
3321 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322}
3323
3324bool ValidateGetUniformivRobustANGLE(Context *context,
3325 GLuint program,
3326 GLint location,
3327 GLsizei bufSize,
3328 GLsizei *length,
3329 GLint *params)
3330{
3331 if (!ValidateRobustEntryPoint(context, bufSize))
3332 {
3333 return false;
3334 }
3335
Brandon Jonesd1049182018-03-28 10:02:20 -07003336 GLsizei writeLength = 0;
3337
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003339 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3340 {
3341 return false;
3342 }
3343
3344 SetRobustLengthParam(length, writeLength);
3345
3346 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003347}
3348
3349bool ValidateGetUniformuivRobustANGLE(Context *context,
3350 GLuint program,
3351 GLint location,
3352 GLsizei bufSize,
3353 GLsizei *length,
3354 GLuint *params)
3355{
3356 if (!ValidateRobustEntryPoint(context, bufSize))
3357 {
3358 return false;
3359 }
3360
3361 if (context->getClientMajorVersion() < 3)
3362 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003363 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003364 return false;
3365 }
3366
Brandon Jonesd1049182018-03-28 10:02:20 -07003367 GLsizei writeLength = 0;
3368
Geoff Langf41d0ee2016-10-07 13:04:23 -04003369 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003370 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3371 {
3372 return false;
3373 }
3374
3375 SetRobustLengthParam(length, writeLength);
3376
3377 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003378}
3379
He Yunchaoced53ae2016-11-29 15:00:51 +08003380bool ValidateDiscardFramebufferBase(Context *context,
3381 GLenum target,
3382 GLsizei numAttachments,
3383 const GLenum *attachments,
3384 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003385{
3386 if (numAttachments < 0)
3387 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003388 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003389 return false;
3390 }
3391
3392 for (GLsizei i = 0; i < numAttachments; ++i)
3393 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003394 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003395 {
3396 if (defaultFramebuffer)
3397 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003399 return false;
3400 }
3401
3402 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003404 context->handleError(InvalidOperation() << "Requested color attachment is "
3405 "greater than the maximum supported "
3406 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003407 return false;
3408 }
3409 }
3410 else
3411 {
3412 switch (attachments[i])
3413 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003414 case GL_DEPTH_ATTACHMENT:
3415 case GL_STENCIL_ATTACHMENT:
3416 case GL_DEPTH_STENCIL_ATTACHMENT:
3417 if (defaultFramebuffer)
3418 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003419 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3420 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003421 return false;
3422 }
3423 break;
3424 case GL_COLOR:
3425 case GL_DEPTH:
3426 case GL_STENCIL:
3427 if (!defaultFramebuffer)
3428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003429 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3430 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003431 return false;
3432 }
3433 break;
3434 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003436 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003437 }
3438 }
3439 }
3440
3441 return true;
3442}
3443
Austin Kinross6ee1e782015-05-29 17:05:37 -07003444bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3445{
Jamie Madill007530e2017-12-28 14:27:04 -05003446 if (!context->getExtensions().debugMarker)
3447 {
3448 // The debug marker calls should not set error state
3449 // However, it seems reasonable to set an error state if the extension is not enabled
3450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3451 return false;
3452 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003453
Jamie Madill007530e2017-12-28 14:27:04 -05003454 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003455 if (length < 0)
3456 {
3457 return false;
3458 }
3459
3460 if (marker == nullptr)
3461 {
3462 return false;
3463 }
3464
3465 return true;
3466}
3467
3468bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3469{
Jamie Madill007530e2017-12-28 14:27:04 -05003470 if (!context->getExtensions().debugMarker)
3471 {
3472 // The debug marker calls should not set error state
3473 // However, it seems reasonable to set an error state if the extension is not enabled
3474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3475 return false;
3476 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003477
Jamie Madill007530e2017-12-28 14:27:04 -05003478 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003479 if (length < 0)
3480 {
3481 return false;
3482 }
3483
3484 if (length > 0 && marker == nullptr)
3485 {
3486 return false;
3487 }
3488
3489 return true;
3490}
3491
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003492bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003493{
Geoff Langa8406172015-07-21 16:53:39 -04003494 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003497 return false;
3498 }
3499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003500 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003501 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003502 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003503 if (!context->getExtensions().eglImage)
3504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidEnum()
3506 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003507 }
3508 break;
3509
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003510 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003511 if (!context->getExtensions().eglImageExternal)
3512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3514 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003515 }
Geoff Langa8406172015-07-21 16:53:39 -04003516 break;
3517
3518 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003520 return false;
3521 }
3522
Rafael Cintron05a449a2018-06-20 18:08:04 -07003523 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003524
Jamie Madill61e16b42017-06-19 11:13:23 -04003525 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003526 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003528 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003529 return false;
3530 }
3531
Jamie Madill007530e2017-12-28 14:27:04 -05003532 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 context->handleError(InvalidOperation()
3535 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003536 return false;
3537 }
3538
Yuly Novikov2eb54072018-08-22 16:41:26 -04003539 if (!imageObject->isTexturable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003541 context->handleError(InvalidOperation()
3542 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Geoff Langdcab33b2015-07-21 13:03:16 -04003546 return true;
3547}
3548
3549bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003550 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003551 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003552{
Geoff Langa8406172015-07-21 16:53:39 -04003553 if (!context->getExtensions().eglImage)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003556 return false;
3557 }
3558
3559 switch (target)
3560 {
3561 case GL_RENDERBUFFER:
3562 break;
3563
3564 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003566 return false;
3567 }
3568
Rafael Cintron05a449a2018-06-20 18:08:04 -07003569 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003570
Jamie Madill61e16b42017-06-19 11:13:23 -04003571 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003572 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003575 return false;
3576 }
3577
Yuly Novikov2eb54072018-08-22 16:41:26 -04003578 if (!imageObject->isRenderable(context))
Geoff Langa8406172015-07-21 16:53:39 -04003579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidOperation()
3581 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Geoff Langdcab33b2015-07-21 13:03:16 -04003585 return true;
3586}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003587
3588bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3589{
Geoff Lang36167ab2015-12-07 10:27:14 -05003590 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003591 {
3592 // The default VAO should always exist
3593 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003595 return false;
3596 }
3597
3598 return true;
3599}
3600
Geoff Langc5629752015-12-07 16:29:04 -05003601bool ValidateProgramBinaryBase(Context *context,
3602 GLuint program,
3603 GLenum binaryFormat,
3604 const void *binary,
3605 GLint length)
3606{
3607 Program *programObject = GetValidProgram(context, program);
3608 if (programObject == nullptr)
3609 {
3610 return false;
3611 }
3612
3613 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3614 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3615 programBinaryFormats.end())
3616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003617 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003618 return false;
3619 }
3620
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003621 if (context->hasActiveTransformFeedback(program))
3622 {
3623 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3625 "is associated with an active transform "
3626 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003627 return false;
3628 }
3629
Geoff Langc5629752015-12-07 16:29:04 -05003630 return true;
3631}
3632
3633bool ValidateGetProgramBinaryBase(Context *context,
3634 GLuint program,
3635 GLsizei bufSize,
3636 GLsizei *length,
3637 GLenum *binaryFormat,
3638 void *binary)
3639{
3640 Program *programObject = GetValidProgram(context, program);
3641 if (programObject == nullptr)
3642 {
3643 return false;
3644 }
3645
3646 if (!programObject->isLinked())
3647 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003649 return false;
3650 }
3651
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003652 if (context->getCaps().programBinaryFormats.empty())
3653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003654 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003655 return false;
3656 }
3657
Geoff Langc5629752015-12-07 16:29:04 -05003658 return true;
3659}
Jamie Madillc29968b2016-01-20 11:17:23 -05003660
Jamie Madill5b772312018-03-08 20:28:32 -05003661bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003662{
3663 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003664 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003665 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003666 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3667 return false;
3668 }
3669 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3670 {
3671 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003672 return false;
3673 }
3674
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003675 ASSERT(context->getGLState().getDrawFramebuffer());
3676 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003677 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3678
3679 // This should come first before the check for the default frame buffer
3680 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3681 // rather than INVALID_OPERATION
3682 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3683 {
3684 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3685
3686 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003687 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3688 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003689 {
3690 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003691 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3692 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3693 // 3.1 is still a bit ambiguous about the error, but future specs are
3694 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003695 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003696 return false;
3697 }
3698 else if (bufs[colorAttachment] >= maxColorAttachment)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation()
3701 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003702 return false;
3703 }
3704 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3705 frameBufferId != 0)
3706 {
3707 // INVALID_OPERATION-GL is bound to buffer and ith argument
3708 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidOperation()
3710 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003711 return false;
3712 }
3713 }
3714
3715 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3716 // and n is not 1 or bufs is bound to value other than BACK and NONE
3717 if (frameBufferId == 0)
3718 {
3719 if (n != 1)
3720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidOperation()
3722 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003723 return false;
3724 }
3725
3726 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(
3729 InvalidOperation()
3730 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003731 return false;
3732 }
3733 }
3734
3735 return true;
3736}
3737
Geoff Lang496c02d2016-10-20 11:38:11 -07003738bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003739 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003740 GLenum pname,
3741 GLsizei *length,
3742 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003743{
Geoff Lang496c02d2016-10-20 11:38:11 -07003744 if (length)
3745 {
3746 *length = 0;
3747 }
3748
3749 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3750 {
3751 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 InvalidOperation()
3753 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003754 return false;
3755 }
3756
Corentin Walleze4477002017-12-01 14:39:58 -05003757 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003758 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003759 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003760 return false;
3761 }
3762
Geoff Lang496c02d2016-10-20 11:38:11 -07003763 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003764 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 case GL_BUFFER_MAP_POINTER:
3766 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003767
Geoff Lang496c02d2016-10-20 11:38:11 -07003768 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 return false;
3771 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003772
3773 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3774 // target bound to zero generate an INVALID_OPERATION error."
3775 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003776 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidOperation()
3779 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 return false;
3781 }
3782
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 if (length)
3784 {
3785 *length = 1;
3786 }
3787
Olli Etuaho4f667482016-03-30 15:56:35 +03003788 return true;
3789}
3790
Corentin Wallez336129f2017-10-17 15:55:40 -04003791bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003792{
Corentin Walleze4477002017-12-01 14:39:58 -05003793 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003794 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 return false;
3797 }
3798
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003799 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003800
3801 if (buffer == nullptr || !buffer->isMapped())
3802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 return false;
3805 }
3806
3807 return true;
3808}
3809
3810bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003811 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 GLintptr offset,
3813 GLsizeiptr length,
3814 GLbitfield access)
3815{
Corentin Walleze4477002017-12-01 14:39:58 -05003816 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 return false;
3820 }
3821
Brandon Jones6cad5662017-06-14 13:25:13 -07003822 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003824 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3825 return false;
3826 }
3827
3828 if (length < 0)
3829 {
3830 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 return false;
3832 }
3833
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003834 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003835
3836 if (!buffer)
3837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 return false;
3840 }
3841
3842 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003843 CheckedNumeric<size_t> checkedOffset(offset);
3844 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003845
Jamie Madille2e406c2016-06-02 13:04:10 -04003846 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
3852 // Check for invalid bits in the mask
3853 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3854 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3855 GL_MAP_UNSYNCHRONIZED_BIT;
3856
3857 if (access & ~(allAccessBits))
3858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003859 context->handleError(InvalidValue()
3860 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003861 return false;
3862 }
3863
3864 if (length == 0)
3865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 return false;
3868 }
3869
3870 if (buffer->isMapped())
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 return false;
3874 }
3875
3876 // Check for invalid bit combinations
3877 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation()
3880 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003881 return false;
3882 }
3883
3884 GLbitfield writeOnlyBits =
3885 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3886
3887 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidOperation()
3890 << "Invalid access bits when mapping buffer for reading: 0x"
3891 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 return false;
3893 }
3894
3895 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003897 context->handleError(
3898 InvalidOperation()
3899 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
Geoff Lang79f71042017-08-14 16:43:43 -04003902
3903 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003904}
3905
3906bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003907 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 GLintptr offset,
3909 GLsizeiptr length)
3910{
Brandon Jones6cad5662017-06-14 13:25:13 -07003911 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3914 return false;
3915 }
3916
3917 if (length < 0)
3918 {
3919 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
Corentin Walleze4477002017-12-01 14:39:58 -05003923 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
3928
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003929 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003930
3931 if (buffer == nullptr)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003934 return false;
3935 }
3936
3937 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003939 context->handleError(InvalidOperation()
3940 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 return false;
3942 }
3943
3944 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003945 CheckedNumeric<size_t> checkedOffset(offset);
3946 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003947
Jamie Madille2e406c2016-06-02 13:04:10 -04003948 if (!checkedSize.IsValid() ||
3949 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003951 context->handleError(InvalidValue()
3952 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 return false;
3954 }
3955
3956 return true;
3957}
3958
Olli Etuaho41997e72016-03-10 13:38:39 +02003959bool ValidateGenOrDelete(Context *context, GLint n)
3960{
3961 if (n < 0)
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003964 return false;
3965 }
3966 return true;
3967}
3968
Jamie Madill5b772312018-03-08 20:28:32 -05003969bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003970{
3971 if (!context->getExtensions().robustClientMemory)
3972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003973 context->handleError(InvalidOperation()
3974 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 return false;
3976 }
3977
3978 if (bufSize < 0)
3979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983
3984 return true;
3985}
3986
Jamie Madill5b772312018-03-08 20:28:32 -05003987bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003988{
3989 if (bufSize < numParams)
3990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3992 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003993 return false;
3994 }
3995
3996 return true;
3997}
3998
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003999bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004000 GLenum target,
4001 GLenum attachment,
4002 GLenum pname,
4003 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004004{
Geoff Lange8afa902017-09-27 15:00:43 -04004005 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004007 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010
4011 int clientVersion = context->getClientMajorVersion();
4012
4013 switch (pname)
4014 {
4015 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4016 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4017 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4018 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4019 break;
4020
Martin Radeve5285d22017-07-14 16:23:53 +03004021 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4022 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4023 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4024 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4025 if (clientVersion < 3 || !context->getExtensions().multiview)
4026 {
4027 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4028 return false;
4029 }
4030 break;
4031
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4033 if (clientVersion < 3 && !context->getExtensions().sRGB)
4034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004035 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004036 return false;
4037 }
4038 break;
4039
4040 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4041 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4044 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4045 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4046 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4047 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4048 if (clientVersion < 3)
4049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004050 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004051 return false;
4052 }
4053 break;
4054
Jiawei Shaoa8802472018-05-28 11:17:47 +08004055 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4056 if (!context->getExtensions().geometryShader)
4057 {
4058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4059 return false;
4060 }
4061 break;
4062
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 return false;
4066 }
4067
4068 // Determine if the attachment is a valid enum
4069 switch (attachment)
4070 {
4071 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 case GL_DEPTH:
4073 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 if (clientVersion < 3)
4075 {
Geoff Langfa125c92017-10-24 13:01:46 -04004076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079 break;
4080
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004081 case GL_DEPTH_STENCIL_ATTACHMENT:
4082 if (clientVersion < 3 && !context->isWebGL1())
4083 {
4084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4085 return false;
4086 }
4087 break;
4088
Geoff Langfa125c92017-10-24 13:01:46 -04004089 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 case GL_DEPTH_ATTACHMENT:
4091 case GL_STENCIL_ATTACHMENT:
4092 break;
4093
4094 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004095 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4096 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4098 {
Geoff Langfa125c92017-10-24 13:01:46 -04004099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 return false;
4101 }
4102 break;
4103 }
4104
4105 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4106 ASSERT(framebuffer);
4107
4108 if (framebuffer->id() == 0)
4109 {
4110 if (clientVersion < 3)
4111 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004113 return false;
4114 }
4115
4116 switch (attachment)
4117 {
4118 case GL_BACK:
4119 case GL_DEPTH:
4120 case GL_STENCIL:
4121 break;
4122
4123 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 return false;
4126 }
4127 }
4128 else
4129 {
4130 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4131 {
4132 // Valid attachment query
4133 }
4134 else
4135 {
4136 switch (attachment)
4137 {
4138 case GL_DEPTH_ATTACHMENT:
4139 case GL_STENCIL_ATTACHMENT:
4140 break;
4141
4142 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004143 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004145 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149
4150 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004151 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 return false;
4153 }
4154 }
4155 }
4156
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004157 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004158 if (attachmentObject)
4159 {
4160 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4161 attachmentObject->type() == GL_TEXTURE ||
4162 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4163
4164 switch (pname)
4165 {
4166 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4167 if (attachmentObject->type() != GL_RENDERBUFFER &&
4168 attachmentObject->type() != GL_TEXTURE)
4169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 break;
4174
4175 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4176 if (attachmentObject->type() != GL_TEXTURE)
4177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 break;
4182
4183 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4184 if (attachmentObject->type() != GL_TEXTURE)
4185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4192 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 return false;
4196 }
4197 break;
4198
4199 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4200 if (attachmentObject->type() != GL_TEXTURE)
4201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 return false;
4204 }
4205 break;
4206
4207 default:
4208 break;
4209 }
4210 }
4211 else
4212 {
4213 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4214 // is NONE, then querying any other pname will generate INVALID_ENUM.
4215
4216 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4217 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4218 // INVALID_OPERATION for all other pnames
4219
4220 switch (pname)
4221 {
4222 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4223 break;
4224
4225 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4226 if (clientVersion < 3)
4227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004228 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004229 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004230 return false;
4231 }
4232 break;
4233
4234 default:
4235 if (clientVersion < 3)
4236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004237 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004238 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004239 return false;
4240 }
4241 else
4242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004243 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004244 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004245 return false;
4246 }
4247 }
4248 }
4249
Martin Radeve5285d22017-07-14 16:23:53 +03004250 if (numParams)
4251 {
4252 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4253 {
4254 // Only when the viewport offsets are queried we can have a varying number of output
4255 // parameters.
4256 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4257 *numParams = numViews * 2;
4258 }
4259 else
4260 {
4261 // For all other queries we can have only one output parameter.
4262 *numParams = 1;
4263 }
4264 }
4265
Geoff Langff5b2d52016-09-07 11:32:23 -04004266 return true;
4267}
4268
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004269bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 GLenum target,
4271 GLenum attachment,
4272 GLenum pname,
4273 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004274 GLsizei *length,
4275 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004276{
4277 if (!ValidateRobustEntryPoint(context, bufSize))
4278 {
4279 return false;
4280 }
4281
Brandon Jonesd1049182018-03-28 10:02:20 -07004282 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004283 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004284 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004285 {
4286 return false;
4287 }
4288
Brandon Jonesd1049182018-03-28 10:02:20 -07004289 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 {
4291 return false;
4292 }
4293
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 SetRobustLengthParam(length, numParams);
4295
Geoff Langff5b2d52016-09-07 11:32:23 -04004296 return true;
4297}
4298
Jamie Madill5b772312018-03-08 20:28:32 -05004299bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004300 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004301 GLenum pname,
4302 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004303 GLsizei *length,
4304 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004305{
4306 if (!ValidateRobustEntryPoint(context, bufSize))
4307 {
4308 return false;
4309 }
4310
Brandon Jonesd1049182018-03-28 10:02:20 -07004311 GLsizei numParams = 0;
4312
4313 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004314 {
4315 return false;
4316 }
4317
Brandon Jonesd1049182018-03-28 10:02:20 -07004318 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004319 {
4320 return false;
4321 }
4322
Brandon Jonesd1049182018-03-28 10:02:20 -07004323 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004324 return true;
4325}
4326
Jamie Madill5b772312018-03-08 20:28:32 -05004327bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004328 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004329 GLenum pname,
4330 GLsizei bufSize,
4331 GLsizei *length,
4332 GLint64 *params)
4333{
Brandon Jonesd1049182018-03-28 10:02:20 -07004334 GLsizei numParams = 0;
4335
Geoff Langebebe1c2016-10-14 12:01:31 -04004336 if (!ValidateRobustEntryPoint(context, bufSize))
4337 {
4338 return false;
4339 }
4340
Brandon Jonesd1049182018-03-28 10:02:20 -07004341 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004342 {
4343 return false;
4344 }
4345
Brandon Jonesd1049182018-03-28 10:02:20 -07004346 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004347 {
4348 return false;
4349 }
4350
Brandon Jonesd1049182018-03-28 10:02:20 -07004351 SetRobustLengthParam(length, numParams);
4352
Geoff Langff5b2d52016-09-07 11:32:23 -04004353 return true;
4354}
4355
Jamie Madill5b772312018-03-08 20:28:32 -05004356bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004357{
4358 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004359 if (numParams)
4360 {
4361 *numParams = 1;
4362 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004363
4364 Program *programObject = GetValidProgram(context, program);
4365 if (!programObject)
4366 {
4367 return false;
4368 }
4369
4370 switch (pname)
4371 {
4372 case GL_DELETE_STATUS:
4373 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004374 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004375 case GL_VALIDATE_STATUS:
4376 case GL_INFO_LOG_LENGTH:
4377 case GL_ATTACHED_SHADERS:
4378 case GL_ACTIVE_ATTRIBUTES:
4379 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4380 case GL_ACTIVE_UNIFORMS:
4381 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4382 break;
4383
4384 case GL_PROGRAM_BINARY_LENGTH:
4385 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004387 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4388 "requires GL_OES_get_program_binary or "
4389 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004390 return false;
4391 }
4392 break;
4393
4394 case GL_ACTIVE_UNIFORM_BLOCKS:
4395 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4396 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4397 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4398 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4399 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4400 if (context->getClientMajorVersion() < 3)
4401 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004402 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004403 return false;
4404 }
4405 break;
4406
Yunchao He61afff12017-03-14 15:34:03 +08004407 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004408 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004409 if (context->getClientVersion() < Version(3, 1))
4410 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004412 return false;
4413 }
4414 break;
4415
Jiawei Shao6ae51612018-02-23 14:03:25 +08004416 case GL_COMPUTE_WORK_GROUP_SIZE:
4417 if (context->getClientVersion() < Version(3, 1))
4418 {
4419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4420 return false;
4421 }
4422
4423 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4424 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4425 // program which has not been linked successfully, or which does not contain objects to
4426 // form a compute shader.
4427 if (!programObject->isLinked())
4428 {
4429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4430 return false;
4431 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004432 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004433 {
4434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4435 return false;
4436 }
4437 break;
4438
Jiawei Shao447bfac2018-03-14 14:23:40 +08004439 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4440 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4441 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4442 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4443 if (!context->getExtensions().geometryShader)
4444 {
4445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4446 return false;
4447 }
4448
4449 // [EXT_geometry_shader] Chapter 7.12
4450 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4451 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4452 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4453 // successfully, or which does not contain objects to form a geometry shader.
4454 if (!programObject->isLinked())
4455 {
4456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4457 return false;
4458 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004459 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004460 {
4461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4462 return false;
4463 }
4464 break;
4465
Geoff Langff5b2d52016-09-07 11:32:23 -04004466 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004468 return false;
4469 }
4470
4471 return true;
4472}
4473
4474bool ValidateGetProgramivRobustANGLE(Context *context,
4475 GLuint program,
4476 GLenum pname,
4477 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004478 GLsizei *length,
4479 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004480{
4481 if (!ValidateRobustEntryPoint(context, bufSize))
4482 {
4483 return false;
4484 }
4485
Brandon Jonesd1049182018-03-28 10:02:20 -07004486 GLsizei numParams = 0;
4487
4488 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004489 {
4490 return false;
4491 }
4492
Brandon Jonesd1049182018-03-28 10:02:20 -07004493 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004494 {
4495 return false;
4496 }
4497
Brandon Jonesd1049182018-03-28 10:02:20 -07004498 SetRobustLengthParam(length, numParams);
4499
Geoff Langff5b2d52016-09-07 11:32:23 -04004500 return true;
4501}
4502
Geoff Lang740d9022016-10-07 11:20:52 -04004503bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4504 GLenum target,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLint *params)
4509{
4510 if (!ValidateRobustEntryPoint(context, bufSize))
4511 {
4512 return false;
4513 }
4514
Brandon Jonesd1049182018-03-28 10:02:20 -07004515 GLsizei numParams = 0;
4516
4517 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004518 {
4519 return false;
4520 }
4521
Brandon Jonesd1049182018-03-28 10:02:20 -07004522 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004523 {
4524 return false;
4525 }
4526
Brandon Jonesd1049182018-03-28 10:02:20 -07004527 SetRobustLengthParam(length, numParams);
4528
Geoff Lang740d9022016-10-07 11:20:52 -04004529 return true;
4530}
4531
Geoff Langd7d0ed32016-10-07 11:33:51 -04004532bool ValidateGetShaderivRobustANGLE(Context *context,
4533 GLuint shader,
4534 GLenum pname,
4535 GLsizei bufSize,
4536 GLsizei *length,
4537 GLint *params)
4538{
4539 if (!ValidateRobustEntryPoint(context, bufSize))
4540 {
4541 return false;
4542 }
4543
Brandon Jonesd1049182018-03-28 10:02:20 -07004544 GLsizei numParams = 0;
4545
4546 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004547 {
4548 return false;
4549 }
4550
Brandon Jonesd1049182018-03-28 10:02:20 -07004551 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004552 {
4553 return false;
4554 }
4555
Brandon Jonesd1049182018-03-28 10:02:20 -07004556 SetRobustLengthParam(length, numParams);
4557
Geoff Langd7d0ed32016-10-07 11:33:51 -04004558 return true;
4559}
4560
Geoff Langc1984ed2016-10-07 12:41:00 -04004561bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004562 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004563 GLenum pname,
4564 GLsizei bufSize,
4565 GLsizei *length,
4566 GLfloat *params)
4567{
4568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
4572
Brandon Jonesd1049182018-03-28 10:02:20 -07004573 GLsizei numParams = 0;
4574
4575 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004581 {
4582 return false;
4583 }
4584
Brandon Jonesd1049182018-03-28 10:02:20 -07004585 SetRobustLengthParam(length, numParams);
4586
Geoff Langc1984ed2016-10-07 12:41:00 -04004587 return true;
4588}
4589
Geoff Langc1984ed2016-10-07 12:41:00 -04004590bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004591 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004592 GLenum pname,
4593 GLsizei bufSize,
4594 GLsizei *length,
4595 GLint *params)
4596{
Brandon Jonesd1049182018-03-28 10:02:20 -07004597
Geoff Langc1984ed2016-10-07 12:41:00 -04004598 if (!ValidateRobustEntryPoint(context, bufSize))
4599 {
4600 return false;
4601 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004602 GLsizei numParams = 0;
4603 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004604 {
4605 return false;
4606 }
4607
Brandon Jonesd1049182018-03-28 10:02:20 -07004608 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004609 {
4610 return false;
4611 }
4612
Brandon Jonesd1049182018-03-28 10:02:20 -07004613 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004614 return true;
4615}
4616
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004617bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4618 TextureType target,
4619 GLenum pname,
4620 GLsizei bufSize,
4621 GLsizei *length,
4622 GLint *params)
4623{
4624 UNIMPLEMENTED();
4625 return false;
4626}
4627
4628bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4629 TextureType target,
4630 GLenum pname,
4631 GLsizei bufSize,
4632 GLsizei *length,
4633 GLuint *params)
4634{
4635 UNIMPLEMENTED();
4636 return false;
4637}
4638
Geoff Langc1984ed2016-10-07 12:41:00 -04004639bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004640 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004641 GLenum pname,
4642 GLsizei bufSize,
4643 const GLfloat *params)
4644{
4645 if (!ValidateRobustEntryPoint(context, bufSize))
4646 {
4647 return false;
4648 }
4649
4650 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4651}
4652
Geoff Langc1984ed2016-10-07 12:41:00 -04004653bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004654 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004655 GLenum pname,
4656 GLsizei bufSize,
4657 const GLint *params)
4658{
4659 if (!ValidateRobustEntryPoint(context, bufSize))
4660 {
4661 return false;
4662 }
4663
4664 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4665}
4666
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004667bool ValidateTexParameterIivRobustANGLE(Context *context,
4668 TextureType target,
4669 GLenum pname,
4670 GLsizei bufSize,
4671 const GLint *params)
4672{
4673 UNIMPLEMENTED();
4674 return false;
4675}
4676
4677bool ValidateTexParameterIuivRobustANGLE(Context *context,
4678 TextureType target,
4679 GLenum pname,
4680 GLsizei bufSize,
4681 const GLuint *params)
4682{
4683 UNIMPLEMENTED();
4684 return false;
4685}
4686
Geoff Langc1984ed2016-10-07 12:41:00 -04004687bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4688 GLuint sampler,
4689 GLenum pname,
4690 GLuint bufSize,
4691 GLsizei *length,
4692 GLfloat *params)
4693{
4694 if (!ValidateRobustEntryPoint(context, bufSize))
4695 {
4696 return false;
4697 }
4698
Brandon Jonesd1049182018-03-28 10:02:20 -07004699 GLsizei numParams = 0;
4700
4701 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004702 {
4703 return false;
4704 }
4705
Brandon Jonesd1049182018-03-28 10:02:20 -07004706 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004707 {
4708 return false;
4709 }
4710
Brandon Jonesd1049182018-03-28 10:02:20 -07004711 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004712 return true;
4713}
4714
Geoff Langc1984ed2016-10-07 12:41:00 -04004715bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4716 GLuint sampler,
4717 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004718 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 GLsizei *length,
4720 GLint *params)
4721{
4722 if (!ValidateRobustEntryPoint(context, bufSize))
4723 {
4724 return false;
4725 }
4726
Brandon Jonesd1049182018-03-28 10:02:20 -07004727 GLsizei numParams = 0;
4728
4729 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004730 {
4731 return false;
4732 }
4733
Brandon Jonesd1049182018-03-28 10:02:20 -07004734 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004735 {
4736 return false;
4737 }
4738
Brandon Jonesd1049182018-03-28 10:02:20 -07004739 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004740 return true;
4741}
4742
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004743bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4744 GLuint sampler,
4745 GLenum pname,
4746 GLsizei bufSize,
4747 GLsizei *length,
4748 GLint *params)
4749{
4750 UNIMPLEMENTED();
4751 return false;
4752}
4753
4754bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4755 GLuint sampler,
4756 GLenum pname,
4757 GLsizei bufSize,
4758 GLsizei *length,
4759 GLuint *params)
4760{
4761 UNIMPLEMENTED();
4762 return false;
4763}
4764
Geoff Langc1984ed2016-10-07 12:41:00 -04004765bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4766 GLuint sampler,
4767 GLenum pname,
4768 GLsizei bufSize,
4769 const GLfloat *params)
4770{
4771 if (!ValidateRobustEntryPoint(context, bufSize))
4772 {
4773 return false;
4774 }
4775
4776 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4777}
4778
Geoff Langc1984ed2016-10-07 12:41:00 -04004779bool ValidateSamplerParameterivRobustANGLE(Context *context,
4780 GLuint sampler,
4781 GLenum pname,
4782 GLsizei bufSize,
4783 const GLint *params)
4784{
4785 if (!ValidateRobustEntryPoint(context, bufSize))
4786 {
4787 return false;
4788 }
4789
4790 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4791}
4792
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004793bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4794 GLuint sampler,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 const GLint *param)
4798{
4799 UNIMPLEMENTED();
4800 return false;
4801}
4802
4803bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4804 GLuint sampler,
4805 GLenum pname,
4806 GLsizei bufSize,
4807 const GLuint *param)
4808{
4809 UNIMPLEMENTED();
4810 return false;
4811}
4812
Geoff Lang0b031062016-10-13 14:30:04 -04004813bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4814 GLuint index,
4815 GLenum pname,
4816 GLsizei bufSize,
4817 GLsizei *length,
4818 GLfloat *params)
4819{
4820 if (!ValidateRobustEntryPoint(context, bufSize))
4821 {
4822 return false;
4823 }
4824
Brandon Jonesd1049182018-03-28 10:02:20 -07004825 GLsizei writeLength = 0;
4826
4827 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004828 {
4829 return false;
4830 }
4831
Brandon Jonesd1049182018-03-28 10:02:20 -07004832 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004833 {
4834 return false;
4835 }
4836
Brandon Jonesd1049182018-03-28 10:02:20 -07004837 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004838 return true;
4839}
4840
Geoff Lang0b031062016-10-13 14:30:04 -04004841bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4842 GLuint index,
4843 GLenum pname,
4844 GLsizei bufSize,
4845 GLsizei *length,
4846 GLint *params)
4847{
4848 if (!ValidateRobustEntryPoint(context, bufSize))
4849 {
4850 return false;
4851 }
4852
Brandon Jonesd1049182018-03-28 10:02:20 -07004853 GLsizei writeLength = 0;
4854
4855 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004856 {
4857 return false;
4858 }
4859
Brandon Jonesd1049182018-03-28 10:02:20 -07004860 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004861 {
4862 return false;
4863 }
4864
Brandon Jonesd1049182018-03-28 10:02:20 -07004865 SetRobustLengthParam(length, writeLength);
4866
Geoff Lang0b031062016-10-13 14:30:04 -04004867 return true;
4868}
4869
Geoff Lang0b031062016-10-13 14:30:04 -04004870bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4871 GLuint index,
4872 GLenum pname,
4873 GLsizei bufSize,
4874 GLsizei *length,
4875 void **pointer)
4876{
4877 if (!ValidateRobustEntryPoint(context, bufSize))
4878 {
4879 return false;
4880 }
4881
Brandon Jonesd1049182018-03-28 10:02:20 -07004882 GLsizei writeLength = 0;
4883
4884 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004885 {
4886 return false;
4887 }
4888
Brandon Jonesd1049182018-03-28 10:02:20 -07004889 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004890 {
4891 return false;
4892 }
4893
Brandon Jonesd1049182018-03-28 10:02:20 -07004894 SetRobustLengthParam(length, writeLength);
4895
Geoff Lang0b031062016-10-13 14:30:04 -04004896 return true;
4897}
4898
Geoff Lang0b031062016-10-13 14:30:04 -04004899bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4900 GLuint index,
4901 GLenum pname,
4902 GLsizei bufSize,
4903 GLsizei *length,
4904 GLint *params)
4905{
4906 if (!ValidateRobustEntryPoint(context, bufSize))
4907 {
4908 return false;
4909 }
4910
Brandon Jonesd1049182018-03-28 10:02:20 -07004911 GLsizei writeLength = 0;
4912
4913 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004914 {
4915 return false;
4916 }
4917
Brandon Jonesd1049182018-03-28 10:02:20 -07004918 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004919 {
4920 return false;
4921 }
4922
Brandon Jonesd1049182018-03-28 10:02:20 -07004923 SetRobustLengthParam(length, writeLength);
4924
Geoff Lang0b031062016-10-13 14:30:04 -04004925 return true;
4926}
4927
Geoff Lang0b031062016-10-13 14:30:04 -04004928bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4929 GLuint index,
4930 GLenum pname,
4931 GLsizei bufSize,
4932 GLsizei *length,
4933 GLuint *params)
4934{
4935 if (!ValidateRobustEntryPoint(context, bufSize))
4936 {
4937 return false;
4938 }
4939
Brandon Jonesd1049182018-03-28 10:02:20 -07004940 GLsizei writeLength = 0;
4941
4942 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004948 {
4949 return false;
4950 }
4951
Brandon Jonesd1049182018-03-28 10:02:20 -07004952 SetRobustLengthParam(length, writeLength);
4953
Geoff Lang0b031062016-10-13 14:30:04 -04004954 return true;
4955}
4956
Geoff Lang6899b872016-10-14 11:30:13 -04004957bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4958 GLuint program,
4959 GLuint uniformBlockIndex,
4960 GLenum pname,
4961 GLsizei bufSize,
4962 GLsizei *length,
4963 GLint *params)
4964{
4965 if (!ValidateRobustEntryPoint(context, bufSize))
4966 {
4967 return false;
4968 }
4969
Brandon Jonesd1049182018-03-28 10:02:20 -07004970 GLsizei writeLength = 0;
4971
4972 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4973 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004974 {
4975 return false;
4976 }
4977
Brandon Jonesd1049182018-03-28 10:02:20 -07004978 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004979 {
4980 return false;
4981 }
4982
Brandon Jonesd1049182018-03-28 10:02:20 -07004983 SetRobustLengthParam(length, writeLength);
4984
Geoff Lang6899b872016-10-14 11:30:13 -04004985 return true;
4986}
4987
Brandon Jones416aaf92018-04-10 08:10:16 -07004988bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004989 GLenum target,
4990 GLenum internalformat,
4991 GLenum pname,
4992 GLsizei bufSize,
4993 GLsizei *length,
4994 GLint *params)
4995{
4996 if (!ValidateRobustEntryPoint(context, bufSize))
4997 {
4998 return false;
4999 }
5000
Brandon Jonesd1049182018-03-28 10:02:20 -07005001 GLsizei numParams = 0;
5002
5003 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5004 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005005 {
5006 return false;
5007 }
5008
Brandon Jonesd1049182018-03-28 10:02:20 -07005009 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005010 {
5011 return false;
5012 }
5013
Brandon Jonesd1049182018-03-28 10:02:20 -07005014 SetRobustLengthParam(length, numParams);
5015
Geoff Lang0a9661f2016-10-20 10:59:20 -07005016 return true;
5017}
5018
Jamie Madill5b772312018-03-08 20:28:32 -05005019bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005020 GLuint attribIndex,
5021 GLint size,
5022 GLenum type,
5023 GLboolean pureInteger)
5024{
5025 const Caps &caps = context->getCaps();
5026 if (attribIndex >= caps.maxVertexAttributes)
5027 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005028 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005029 return false;
5030 }
5031
5032 if (size < 1 || size > 4)
5033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005034 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005035 return false;
Shao80957d92017-02-20 21:25:59 +08005036 }
5037
5038 switch (type)
5039 {
5040 case GL_BYTE:
5041 case GL_UNSIGNED_BYTE:
5042 case GL_SHORT:
5043 case GL_UNSIGNED_SHORT:
5044 break;
5045
5046 case GL_INT:
5047 case GL_UNSIGNED_INT:
5048 if (context->getClientMajorVersion() < 3)
5049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005050 context->handleError(InvalidEnum()
5051 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005052 return false;
5053 }
5054 break;
5055
5056 case GL_FIXED:
5057 case GL_FLOAT:
5058 if (pureInteger)
5059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005061 return false;
5062 }
5063 break;
5064
5065 case GL_HALF_FLOAT:
5066 if (context->getClientMajorVersion() < 3)
5067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005068 context->handleError(InvalidEnum()
5069 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005070 return false;
5071 }
5072 if (pureInteger)
5073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005074 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005075 return false;
5076 }
5077 break;
5078
5079 case GL_INT_2_10_10_10_REV:
5080 case GL_UNSIGNED_INT_2_10_10_10_REV:
5081 if (context->getClientMajorVersion() < 3)
5082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005083 context->handleError(InvalidEnum()
5084 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005085 return false;
5086 }
5087 if (pureInteger)
5088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005090 return false;
5091 }
5092 if (size != 4)
5093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5095 "UNSIGNED_INT_2_10_10_10_REV and "
5096 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005097 return false;
5098 }
5099 break;
5100
5101 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005103 return false;
5104 }
5105
5106 return true;
5107}
5108
Geoff Lang76e65652017-03-27 14:58:02 -04005109// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5110// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5111// specified clear value and the type of a buffer that is being cleared generates an
5112// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005113bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005114 GLint drawbuffer,
5115 const GLenum *validComponentTypes,
5116 size_t validComponentTypeCount)
5117{
5118 const FramebufferAttachment *attachment =
5119 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5120 if (attachment)
5121 {
5122 GLenum componentType = attachment->getFormat().info->componentType;
5123 const GLenum *end = validComponentTypes + validComponentTypeCount;
5124 if (std::find(validComponentTypes, end, componentType) == end)
5125 {
5126 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005127 InvalidOperation()
5128 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005129 return false;
5130 }
5131 }
5132
5133 return true;
5134}
5135
Jamie Madill5b772312018-03-08 20:28:32 -05005136bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005137{
5138 if (!ValidateRobustEntryPoint(context, dataSize))
5139 {
5140 return false;
5141 }
5142
Jamie Madill43da7c42018-08-01 11:34:49 -04005143 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005144 if (pixelUnpackBuffer == nullptr)
5145 {
5146 if (dataSize < imageSize)
5147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005148 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005149 }
5150 }
5151 return true;
5152}
5153
Jamie Madill5b772312018-03-08 20:28:32 -05005154bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005155 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 GLenum pname,
5157 bool pointerVersion,
5158 GLsizei *numParams)
5159{
5160 if (numParams)
5161 {
5162 *numParams = 0;
5163 }
5164
Corentin Walleze4477002017-12-01 14:39:58 -05005165 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170
5171 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5172 if (!buffer)
5173 {
5174 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 return false;
5177 }
5178
5179 const Extensions &extensions = context->getExtensions();
5180
5181 switch (pname)
5182 {
5183 case GL_BUFFER_USAGE:
5184 case GL_BUFFER_SIZE:
5185 break;
5186
5187 case GL_BUFFER_ACCESS_OES:
5188 if (!extensions.mapBuffer)
5189 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005190 context->handleError(InvalidEnum()
5191 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005192 return false;
5193 }
5194 break;
5195
5196 case GL_BUFFER_MAPPED:
5197 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5198 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5199 !extensions.mapBufferRange)
5200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005201 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5202 "GL_OES_mapbuffer or "
5203 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206 break;
5207
5208 case GL_BUFFER_MAP_POINTER:
5209 if (!pointerVersion)
5210 {
5211 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005212 InvalidEnum()
5213 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 return false;
5215 }
5216 break;
5217
5218 case GL_BUFFER_ACCESS_FLAGS:
5219 case GL_BUFFER_MAP_OFFSET:
5220 case GL_BUFFER_MAP_LENGTH:
5221 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005223 context->handleError(InvalidEnum()
5224 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 return false;
5226 }
5227 break;
5228
5229 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005230 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 return false;
5232 }
5233
5234 // All buffer parameter queries return one value.
5235 if (numParams)
5236 {
5237 *numParams = 1;
5238 }
5239
5240 return true;
5241}
5242
5243bool ValidateGetRenderbufferParameterivBase(Context *context,
5244 GLenum target,
5245 GLenum pname,
5246 GLsizei *length)
5247{
5248 if (length)
5249 {
5250 *length = 0;
5251 }
5252
5253 if (target != GL_RENDERBUFFER)
5254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258
5259 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5260 if (renderbuffer == nullptr)
5261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 switch (pname)
5267 {
5268 case GL_RENDERBUFFER_WIDTH:
5269 case GL_RENDERBUFFER_HEIGHT:
5270 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5271 case GL_RENDERBUFFER_RED_SIZE:
5272 case GL_RENDERBUFFER_GREEN_SIZE:
5273 case GL_RENDERBUFFER_BLUE_SIZE:
5274 case GL_RENDERBUFFER_ALPHA_SIZE:
5275 case GL_RENDERBUFFER_DEPTH_SIZE:
5276 case GL_RENDERBUFFER_STENCIL_SIZE:
5277 break;
5278
5279 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5280 if (!context->getExtensions().framebufferMultisample)
5281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005282 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291
5292 if (length)
5293 {
5294 *length = 1;
5295 }
5296 return true;
5297}
5298
5299bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5300{
5301 if (length)
5302 {
5303 *length = 0;
5304 }
5305
5306 if (GetValidShader(context, shader) == nullptr)
5307 {
5308 return false;
5309 }
5310
5311 switch (pname)
5312 {
5313 case GL_SHADER_TYPE:
5314 case GL_DELETE_STATUS:
5315 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005316 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 case GL_INFO_LOG_LENGTH:
5318 case GL_SHADER_SOURCE_LENGTH:
5319 break;
5320
5321 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5322 if (!context->getExtensions().translatedShaderSource)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327 break;
5328
5329 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 return false;
5332 }
5333
5334 if (length)
5335 {
5336 *length = 1;
5337 }
5338 return true;
5339}
5340
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005341bool ValidateGetTexParameterBase(Context *context,
5342 TextureType target,
5343 GLenum pname,
5344 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005345{
5346 if (length)
5347 {
5348 *length = 0;
5349 }
5350
5351 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 return false;
5355 }
5356
5357 if (context->getTargetTexture(target) == nullptr)
5358 {
5359 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005364 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5365 {
5366 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5367 return false;
5368 }
5369
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 switch (pname)
5371 {
5372 case GL_TEXTURE_MAG_FILTER:
5373 case GL_TEXTURE_MIN_FILTER:
5374 case GL_TEXTURE_WRAP_S:
5375 case GL_TEXTURE_WRAP_T:
5376 break;
5377
5378 case GL_TEXTURE_USAGE_ANGLE:
5379 if (!context->getExtensions().textureUsage)
5380 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005382 return false;
5383 }
5384 break;
5385
5386 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005387 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005389 return false;
5390 }
5391 break;
5392
5393 case GL_TEXTURE_IMMUTABLE_FORMAT:
5394 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 return false;
5398 }
5399 break;
5400
5401 case GL_TEXTURE_WRAP_R:
5402 case GL_TEXTURE_IMMUTABLE_LEVELS:
5403 case GL_TEXTURE_SWIZZLE_R:
5404 case GL_TEXTURE_SWIZZLE_G:
5405 case GL_TEXTURE_SWIZZLE_B:
5406 case GL_TEXTURE_SWIZZLE_A:
5407 case GL_TEXTURE_BASE_LEVEL:
5408 case GL_TEXTURE_MAX_LEVEL:
5409 case GL_TEXTURE_MIN_LOD:
5410 case GL_TEXTURE_MAX_LOD:
5411 case GL_TEXTURE_COMPARE_MODE:
5412 case GL_TEXTURE_COMPARE_FUNC:
5413 if (context->getClientMajorVersion() < 3)
5414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005415 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418 break;
5419
5420 case GL_TEXTURE_SRGB_DECODE_EXT:
5421 if (!context->getExtensions().textureSRGBDecode)
5422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005423 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426 break;
5427
Yunchao Hebacaa712018-01-30 14:01:39 +08005428 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5429 if (context->getClientVersion() < Version(3, 1))
5430 {
5431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5432 return false;
5433 }
5434 break;
5435
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005436 case GL_GENERATE_MIPMAP:
5437 case GL_TEXTURE_CROP_RECT_OES:
5438 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5439 // after GL_OES_draw_texture functionality implemented
5440 if (context->getClientMajorVersion() > 1)
5441 {
5442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5443 return false;
5444 }
5445 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450
5451 if (length)
5452 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005453 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 }
5455 return true;
5456}
5457
5458bool ValidateGetVertexAttribBase(Context *context,
5459 GLuint index,
5460 GLenum pname,
5461 GLsizei *length,
5462 bool pointer,
5463 bool pureIntegerEntryPoint)
5464{
5465 if (length)
5466 {
5467 *length = 0;
5468 }
5469
5470 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005472 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475
5476 if (index >= context->getCaps().maxVertexAttributes)
5477 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005478 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 return false;
5480 }
5481
5482 if (pointer)
5483 {
5484 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5485 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489 }
5490 else
5491 {
5492 switch (pname)
5493 {
5494 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5495 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5496 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5497 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5498 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5499 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5500 case GL_CURRENT_VERTEX_ATTRIB:
5501 break;
5502
5503 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5504 static_assert(
5505 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5506 "ANGLE extension enums not equal to GL enums.");
5507 if (context->getClientMajorVersion() < 3 &&
5508 !context->getExtensions().instancedArrays)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5511 "requires OpenGL ES 3.0 or "
5512 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
5515 break;
5516
5517 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5518 if (context->getClientMajorVersion() < 3)
5519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005520 context->handleError(
5521 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 return false;
5523 }
5524 break;
5525
5526 case GL_VERTEX_ATTRIB_BINDING:
5527 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5528 if (context->getClientVersion() < ES_3_1)
5529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005530 context->handleError(InvalidEnum()
5531 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 break;
5535
5536 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540 }
5541
5542 if (length)
5543 {
5544 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5545 {
5546 *length = 4;
5547 }
5548 else
5549 {
5550 *length = 1;
5551 }
5552 }
5553
5554 return true;
5555}
5556
Jamie Madill4928b7c2017-06-20 12:57:39 -04005557bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 GLint x,
5559 GLint y,
5560 GLsizei width,
5561 GLsizei height,
5562 GLenum format,
5563 GLenum type,
5564 GLsizei bufSize,
5565 GLsizei *length,
5566 GLsizei *columns,
5567 GLsizei *rows,
5568 void *pixels)
5569{
5570 if (length != nullptr)
5571 {
5572 *length = 0;
5573 }
5574 if (rows != nullptr)
5575 {
5576 *rows = 0;
5577 }
5578 if (columns != nullptr)
5579 {
5580 *columns = 0;
5581 }
5582
5583 if (width < 0 || height < 0)
5584 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005585 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005589 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005590
Jamie Madill427064d2018-04-13 16:20:34 -04005591 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
5595
Jamie Madille98b1b52018-03-08 09:47:23 -05005596 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 return false;
5599 }
5600
Jamie Madill690c8eb2018-03-12 15:20:03 -04005601 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005602 ASSERT(framebuffer);
5603
5604 if (framebuffer->getReadBufferState() == GL_NONE)
5605 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005606 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609
5610 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5611 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5612 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5613 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5614 // situation is an application error that would lead to a crash in ANGLE.
5615 if (readBuffer == nullptr)
5616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620
Martin Radev28031682017-07-28 14:47:56 +03005621 // ANGLE_multiview, Revision 1:
5622 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005623 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5624 // in the current read framebuffer is more than one.
5625 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005626 {
5627 context->handleError(InvalidFramebufferOperation()
5628 << "Attempting to read from a multi-view framebuffer.");
5629 return false;
5630 }
5631
Geoff Lang280ba992017-04-18 16:30:58 -04005632 if (context->getExtensions().webglCompatibility)
5633 {
5634 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5635 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5636 // and type before validating the combination of format and type. However, the
5637 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5638 // verifies that GL_INVALID_OPERATION is generated.
5639 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5640 // dEQP/WebGL.
5641 if (!ValidReadPixelsFormatEnum(context, format))
5642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005644 return false;
5645 }
5646
5647 if (!ValidReadPixelsTypeEnum(context, type))
5648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005650 return false;
5651 }
5652 }
5653
Jamie Madill690c8eb2018-03-12 15:20:03 -04005654 GLenum currentFormat = GL_NONE;
5655 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5656
5657 GLenum currentType = GL_NONE;
5658 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5659
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5661
5662 bool validFormatTypeCombination =
5663 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5664
5665 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670
5671 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005672 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5674 {
5675 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005676 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005679 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5680 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5681 {
5682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5683 return false;
5684 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005685
5686 // .. the data would be packed to the buffer object such that the memory writes required
5687 // would exceed the data store size.
5688 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005689 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 const auto &pack = context->getGLState().getPackState();
5691
Jamie Madillca2ff382018-07-11 09:01:17 -04005692 GLuint endByte = 0;
5693 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005695 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 return false;
5697 }
5698
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 if (bufSize >= 0)
5700 {
5701 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005704 return false;
5705 }
5706 }
5707
5708 if (pixelPackBuffer != nullptr)
5709 {
5710 CheckedNumeric<size_t> checkedEndByte(endByte);
5711 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5712 checkedEndByte += checkedOffset;
5713
5714 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5715 {
5716 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720 }
5721
5722 if (pixelPackBuffer == nullptr && length != nullptr)
5723 {
5724 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5725 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
5729
5730 *length = static_cast<GLsizei>(endByte);
5731 }
5732
Geoff Langa953b522018-02-21 16:56:23 -05005733 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 angle::CheckedNumeric<int> clippedExtent(length);
5735 if (start < 0)
5736 {
5737 // "subtract" the area that is less than 0
5738 clippedExtent += start;
5739 }
5740
Geoff Langa953b522018-02-21 16:56:23 -05005741 angle::CheckedNumeric<int> readExtent = start;
5742 readExtent += length;
5743 if (!readExtent.IsValid())
5744 {
5745 return false;
5746 }
5747
5748 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 {
5750 // Subtract the region to the right of the read buffer
5751 clippedExtent -= (readExtent - bufferSize);
5752 }
5753
5754 if (!clippedExtent.IsValid())
5755 {
Geoff Langa953b522018-02-21 16:56:23 -05005756 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 }
5758
Geoff Langa953b522018-02-21 16:56:23 -05005759 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5760 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 };
5762
Geoff Langa953b522018-02-21 16:56:23 -05005763 GLsizei writtenColumns = 0;
5764 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5765 {
5766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5767 return false;
5768 }
5769
5770 GLsizei writtenRows = 0;
5771 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5774 return false;
5775 }
5776
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 if (columns != nullptr)
5778 {
Geoff Langa953b522018-02-21 16:56:23 -05005779 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005780 }
5781
5782 if (rows != nullptr)
5783 {
Geoff Langa953b522018-02-21 16:56:23 -05005784 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 }
5786
5787 return true;
5788}
5789
5790template <typename ParamType>
5791bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005792 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005793 GLenum pname,
5794 GLsizei bufSize,
5795 const ParamType *params)
5796{
5797 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005800 return false;
5801 }
5802
5803 if (context->getTargetTexture(target) == nullptr)
5804 {
5805 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005810 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 if (bufSize >= 0 && bufSize < minBufSize)
5812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005814 return false;
5815 }
5816
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005817 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5818 {
5819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5820 return false;
5821 }
5822
Jamie Madillbe849e42017-05-02 15:49:00 -04005823 switch (pname)
5824 {
5825 case GL_TEXTURE_WRAP_R:
5826 case GL_TEXTURE_SWIZZLE_R:
5827 case GL_TEXTURE_SWIZZLE_G:
5828 case GL_TEXTURE_SWIZZLE_B:
5829 case GL_TEXTURE_SWIZZLE_A:
5830 case GL_TEXTURE_BASE_LEVEL:
5831 case GL_TEXTURE_MAX_LEVEL:
5832 case GL_TEXTURE_COMPARE_MODE:
5833 case GL_TEXTURE_COMPARE_FUNC:
5834 case GL_TEXTURE_MIN_LOD:
5835 case GL_TEXTURE_MAX_LOD:
5836 if (context->getClientMajorVersion() < 3)
5837 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005841 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005843 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5844 "available without "
5845 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
5848 break;
5849
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005850 case GL_GENERATE_MIPMAP:
5851 case GL_TEXTURE_CROP_RECT_OES:
5852 if (context->getClientMajorVersion() > 1)
5853 {
5854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5855 return false;
5856 }
5857 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 default:
5859 break;
5860 }
5861
Olli Etuahod310a432018-08-24 15:40:23 +03005862 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005863 {
5864 switch (pname)
5865 {
5866 case GL_TEXTURE_MIN_FILTER:
5867 case GL_TEXTURE_MAG_FILTER:
5868 case GL_TEXTURE_WRAP_S:
5869 case GL_TEXTURE_WRAP_T:
5870 case GL_TEXTURE_WRAP_R:
5871 case GL_TEXTURE_MIN_LOD:
5872 case GL_TEXTURE_MAX_LOD:
5873 case GL_TEXTURE_COMPARE_MODE:
5874 case GL_TEXTURE_COMPARE_FUNC:
5875 context->handleError(InvalidEnum()
5876 << "Invalid parameter for 2D multisampled textures.");
5877 return false;
5878 }
5879 }
5880
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 switch (pname)
5882 {
5883 case GL_TEXTURE_WRAP_S:
5884 case GL_TEXTURE_WRAP_T:
5885 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005886 {
5887 bool restrictedWrapModes =
5888 target == TextureType::External || target == TextureType::Rectangle;
5889 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005891 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005892 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005893 }
5894 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005895
5896 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005897 {
5898 bool restrictedMinFilter =
5899 target == TextureType::External || target == TextureType::Rectangle;
5900 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005902 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005903 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005904 }
5905 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005906
5907 case GL_TEXTURE_MAG_FILTER:
5908 if (!ValidateTextureMagFilterValue(context, params))
5909 {
5910 return false;
5911 }
5912 break;
5913
5914 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005915 if (!context->getExtensions().textureUsage)
5916 {
5917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5918 return false;
5919 }
5920
Jamie Madillbe849e42017-05-02 15:49:00 -04005921 switch (ConvertToGLenum(params[0]))
5922 {
5923 case GL_NONE:
5924 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5925 break;
5926
5927 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 return false;
5930 }
5931 break;
5932
5933 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005934 {
5935 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5936 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005937 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005938 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005940 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5941 }
5942 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005943
5944 case GL_TEXTURE_MIN_LOD:
5945 case GL_TEXTURE_MAX_LOD:
5946 // any value is permissible
5947 break;
5948
5949 case GL_TEXTURE_COMPARE_MODE:
5950 if (!ValidateTextureCompareModeValue(context, params))
5951 {
5952 return false;
5953 }
5954 break;
5955
5956 case GL_TEXTURE_COMPARE_FUNC:
5957 if (!ValidateTextureCompareFuncValue(context, params))
5958 {
5959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_SWIZZLE_R:
5964 case GL_TEXTURE_SWIZZLE_G:
5965 case GL_TEXTURE_SWIZZLE_B:
5966 case GL_TEXTURE_SWIZZLE_A:
5967 switch (ConvertToGLenum(params[0]))
5968 {
5969 case GL_RED:
5970 case GL_GREEN:
5971 case GL_BLUE:
5972 case GL_ALPHA:
5973 case GL_ZERO:
5974 case GL_ONE:
5975 break;
5976
5977 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005979 return false;
5980 }
5981 break;
5982
5983 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005984 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005986 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 return false;
5988 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005989 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005991 context->handleError(InvalidOperation()
5992 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 return false;
5994 }
Olli Etuahod310a432018-08-24 15:40:23 +03005995 if ((target == TextureType::_2DMultisample ||
5996 target == TextureType::_2DMultisampleArray) &&
5997 static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005998 {
5999 context->handleError(InvalidOperation()
6000 << "Base level must be 0 for multisampled textures.");
6001 return false;
6002 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006003 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006004 {
6005 context->handleError(InvalidOperation()
6006 << "Base level must be 0 for rectangle textures.");
6007 return false;
6008 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 break;
6010
6011 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006012 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006014 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 return false;
6016 }
6017 break;
6018
6019 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6020 if (context->getClientVersion() < Version(3, 1))
6021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 return false;
6024 }
6025 switch (ConvertToGLenum(params[0]))
6026 {
6027 case GL_DEPTH_COMPONENT:
6028 case GL_STENCIL_INDEX:
6029 break;
6030
6031 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006032 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006033 return false;
6034 }
6035 break;
6036
6037 case GL_TEXTURE_SRGB_DECODE_EXT:
6038 if (!ValidateTextureSRGBDecodeValue(context, params))
6039 {
6040 return false;
6041 }
6042 break;
6043
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006044 case GL_GENERATE_MIPMAP:
6045 case GL_TEXTURE_CROP_RECT_OES:
6046 if (context->getClientMajorVersion() > 1)
6047 {
6048 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6049 return false;
6050 }
6051 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006052 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006054 return false;
6055 }
6056
6057 return true;
6058}
6059
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006060template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6061template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006062
Jamie Madill5b772312018-03-08 20:28:32 -05006063bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006064{
6065 if (index >= MAX_VERTEX_ATTRIBS)
6066 {
6067 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6068 return false;
6069 }
6070
6071 return true;
6072}
6073
6074bool ValidateGetActiveUniformBlockivBase(Context *context,
6075 GLuint program,
6076 GLuint uniformBlockIndex,
6077 GLenum pname,
6078 GLsizei *length)
6079{
6080 if (length)
6081 {
6082 *length = 0;
6083 }
6084
6085 if (context->getClientMajorVersion() < 3)
6086 {
6087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6088 return false;
6089 }
6090
6091 Program *programObject = GetValidProgram(context, program);
6092 if (!programObject)
6093 {
6094 return false;
6095 }
6096
6097 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6098 {
6099 context->handleError(InvalidValue()
6100 << "uniformBlockIndex exceeds active uniform block count.");
6101 return false;
6102 }
6103
6104 switch (pname)
6105 {
6106 case GL_UNIFORM_BLOCK_BINDING:
6107 case GL_UNIFORM_BLOCK_DATA_SIZE:
6108 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6109 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6110 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6111 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6112 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6113 break;
6114
6115 default:
6116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6117 return false;
6118 }
6119
6120 if (length)
6121 {
6122 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6123 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006124 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006125 programObject->getUniformBlockByIndex(uniformBlockIndex);
6126 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6127 }
6128 else
6129 {
6130 *length = 1;
6131 }
6132 }
6133
6134 return true;
6135}
6136
Jamie Madill9696d072017-08-26 23:19:57 -04006137template <typename ParamType>
6138bool ValidateSamplerParameterBase(Context *context,
6139 GLuint sampler,
6140 GLenum pname,
6141 GLsizei bufSize,
6142 ParamType *params)
6143{
6144 if (context->getClientMajorVersion() < 3)
6145 {
6146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6147 return false;
6148 }
6149
6150 if (!context->isSampler(sampler))
6151 {
6152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6153 return false;
6154 }
6155
6156 const GLsizei minBufSize = 1;
6157 if (bufSize >= 0 && bufSize < minBufSize)
6158 {
6159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6160 return false;
6161 }
6162
6163 switch (pname)
6164 {
6165 case GL_TEXTURE_WRAP_S:
6166 case GL_TEXTURE_WRAP_T:
6167 case GL_TEXTURE_WRAP_R:
6168 if (!ValidateTextureWrapModeValue(context, params, false))
6169 {
6170 return false;
6171 }
6172 break;
6173
6174 case GL_TEXTURE_MIN_FILTER:
6175 if (!ValidateTextureMinFilterValue(context, params, false))
6176 {
6177 return false;
6178 }
6179 break;
6180
6181 case GL_TEXTURE_MAG_FILTER:
6182 if (!ValidateTextureMagFilterValue(context, params))
6183 {
6184 return false;
6185 }
6186 break;
6187
6188 case GL_TEXTURE_MIN_LOD:
6189 case GL_TEXTURE_MAX_LOD:
6190 // any value is permissible
6191 break;
6192
6193 case GL_TEXTURE_COMPARE_MODE:
6194 if (!ValidateTextureCompareModeValue(context, params))
6195 {
6196 return false;
6197 }
6198 break;
6199
6200 case GL_TEXTURE_COMPARE_FUNC:
6201 if (!ValidateTextureCompareFuncValue(context, params))
6202 {
6203 return false;
6204 }
6205 break;
6206
6207 case GL_TEXTURE_SRGB_DECODE_EXT:
6208 if (!ValidateTextureSRGBDecodeValue(context, params))
6209 {
6210 return false;
6211 }
6212 break;
6213
Luc Ferron1b1a8642018-01-23 15:12:01 -05006214 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6215 {
6216 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6217 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6218 {
6219 return false;
6220 }
6221 }
6222 break;
6223
Jamie Madill9696d072017-08-26 23:19:57 -04006224 default:
6225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6226 return false;
6227 }
6228
6229 return true;
6230}
6231
6232template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6233template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6234
6235bool ValidateGetSamplerParameterBase(Context *context,
6236 GLuint sampler,
6237 GLenum pname,
6238 GLsizei *length)
6239{
6240 if (length)
6241 {
6242 *length = 0;
6243 }
6244
6245 if (context->getClientMajorVersion() < 3)
6246 {
6247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6248 return false;
6249 }
6250
6251 if (!context->isSampler(sampler))
6252 {
6253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6254 return false;
6255 }
6256
6257 switch (pname)
6258 {
6259 case GL_TEXTURE_WRAP_S:
6260 case GL_TEXTURE_WRAP_T:
6261 case GL_TEXTURE_WRAP_R:
6262 case GL_TEXTURE_MIN_FILTER:
6263 case GL_TEXTURE_MAG_FILTER:
6264 case GL_TEXTURE_MIN_LOD:
6265 case GL_TEXTURE_MAX_LOD:
6266 case GL_TEXTURE_COMPARE_MODE:
6267 case GL_TEXTURE_COMPARE_FUNC:
6268 break;
6269
Luc Ferron1b1a8642018-01-23 15:12:01 -05006270 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6271 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6272 {
6273 return false;
6274 }
6275 break;
6276
Jamie Madill9696d072017-08-26 23:19:57 -04006277 case GL_TEXTURE_SRGB_DECODE_EXT:
6278 if (!context->getExtensions().textureSRGBDecode)
6279 {
6280 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6281 return false;
6282 }
6283 break;
6284
6285 default:
6286 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6287 return false;
6288 }
6289
6290 if (length)
6291 {
6292 *length = 1;
6293 }
6294 return true;
6295}
6296
6297bool ValidateGetInternalFormativBase(Context *context,
6298 GLenum target,
6299 GLenum internalformat,
6300 GLenum pname,
6301 GLsizei bufSize,
6302 GLsizei *numParams)
6303{
6304 if (numParams)
6305 {
6306 *numParams = 0;
6307 }
6308
6309 if (context->getClientMajorVersion() < 3)
6310 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006312 return false;
6313 }
6314
6315 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006316 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006317 {
6318 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6319 return false;
6320 }
6321
6322 switch (target)
6323 {
6324 case GL_RENDERBUFFER:
6325 break;
6326
6327 case GL_TEXTURE_2D_MULTISAMPLE:
6328 if (context->getClientVersion() < ES_3_1)
6329 {
Olli Etuahod310a432018-08-24 15:40:23 +03006330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureTargetRequiresES31);
Jamie Madill9696d072017-08-26 23:19:57 -04006331 return false;
6332 }
6333 break;
Olli Etuaho064458a2018-08-30 14:02:02 +03006334 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
6335 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03006336 {
6337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), MultisampleArrayExtensionRequired);
6338 return false;
6339 }
6340 break;
Jamie Madill9696d072017-08-26 23:19:57 -04006341 default:
6342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6343 return false;
6344 }
6345
6346 if (bufSize < 0)
6347 {
6348 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6349 return false;
6350 }
6351
6352 GLsizei maxWriteParams = 0;
6353 switch (pname)
6354 {
6355 case GL_NUM_SAMPLE_COUNTS:
6356 maxWriteParams = 1;
6357 break;
6358
6359 case GL_SAMPLES:
6360 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6361 break;
6362
6363 default:
6364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6365 return false;
6366 }
6367
6368 if (numParams)
6369 {
6370 // glGetInternalFormativ will not overflow bufSize
6371 *numParams = std::min(bufSize, maxWriteParams);
6372 }
6373
6374 return true;
6375}
6376
Jamie Madille98b1b52018-03-08 09:47:23 -05006377bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6378{
Jamie Madill427064d2018-04-13 16:20:34 -04006379 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006380 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006381 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006382 return false;
6383 }
6384 return true;
6385}
6386
Lingfeng Yang038dd532018-03-29 17:31:52 -07006387bool ValidateMultitextureUnit(Context *context, GLenum texture)
6388{
6389 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6390 {
6391 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6392 return false;
6393 }
6394 return true;
6395}
6396
Olli Etuahod310a432018-08-24 15:40:23 +03006397bool ValidateTexStorageMultisample(Context *context,
6398 TextureType target,
6399 GLsizei samples,
6400 GLint internalFormat,
6401 GLsizei width,
6402 GLsizei height)
6403{
6404 const Caps &caps = context->getCaps();
6405 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
6406 static_cast<GLuint>(height) > caps.max2DTextureSize)
6407 {
6408 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureWidthOrHeightOutOfRange);
6409 return false;
6410 }
6411
6412 if (samples == 0)
6413 {
6414 ANGLE_VALIDATION_ERR(context, InvalidValue(), SamplesZero);
6415 return false;
6416 }
6417
6418 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
6419 if (!formatCaps.textureAttachment)
6420 {
6421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), RenderableInternalFormat);
6422 return false;
6423 }
6424
6425 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
6426 // is one of the unsized base internalformats listed in table 8.11.
6427 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
6428 if (formatInfo.internalFormat == GL_NONE)
6429 {
6430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnsizedInternalFormatUnsupported);
6431 return false;
6432 }
6433
6434 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
6435 {
6436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), SamplesOutOfRange);
6437 return false;
6438 }
6439
6440 Texture *texture = context->getTargetTexture(target);
6441 if (!texture || texture->id() == 0)
6442 {
6443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ZeroBoundToTarget);
6444 return false;
6445 }
6446
6447 if (texture->getImmutableFormat())
6448 {
6449 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ImmutableTextureBound);
6450 return false;
6451 }
6452 return true;
6453}
6454
Jamie Madillc29968b2016-01-20 11:17:23 -05006455} // namespace gl