blob: 5812e3aee502e687a8c0d6ae95f49dfffb130785 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madill2da53562018-08-01 11:34:47 -040082bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040083{
Jamie Madill51af38b2018-04-15 08:50:56 -040084 // If we're drawing zero vertices, we have enough data.
Jamie Madill2da53562018-08-01 11:34:47 -040085 ASSERT(primcount > 0);
Jamie Madill51af38b2018-04-15 08:50:56 -040086
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040087 if (maxVertex <= context->getStateCache().getNonInstancedVertexElementLimit() &&
88 (primcount - 1) <= context->getStateCache().getInstancedVertexElementLimit())
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040090 return true;
Jamie Madill02c9c042018-04-17 13:43:48 -040091 }
James Darpiniane8a93c62018-01-04 18:02:24 -080092
Jamie Madill88602e62018-08-08 12:49:30 -040093 // An overflow can happen when adding the offset. Check against a special constant.
94 if (context->getStateCache().getNonInstancedVertexElementLimit() ==
95 VertexAttribute::kIntegerOverflow ||
96 context->getStateCache().getInstancedVertexElementLimit() ==
97 VertexAttribute::kIntegerOverflow)
Jamie Madilla2d1d2d2018-08-01 11:34:46 -040098 {
99 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
100 return false;
101 }
102
103 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
104 // We can return INVALID_OPERATION if our buffer does not have enough backing data.
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
106 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400107}
108
Jamie Madill5b772312018-03-08 20:28:32 -0500109bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400110{
111 switch (type)
112 {
113 // Types referenced in Table 3.4 of the ES 2.0.25 spec
114 case GL_UNSIGNED_BYTE:
115 case GL_UNSIGNED_SHORT_4_4_4_4:
116 case GL_UNSIGNED_SHORT_5_5_5_1:
117 case GL_UNSIGNED_SHORT_5_6_5:
118 return context->getClientVersion() >= ES_2_0;
119
120 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
121 case GL_BYTE:
122 case GL_INT:
123 case GL_SHORT:
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_10F_11F_11F_REV:
126 case GL_UNSIGNED_INT_24_8:
127 case GL_UNSIGNED_INT_2_10_10_10_REV:
128 case GL_UNSIGNED_INT_5_9_9_9_REV:
129 case GL_UNSIGNED_SHORT:
130 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
131 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
132 return context->getClientVersion() >= ES_3_0;
133
134 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400135 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
136 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400137
138 case GL_HALF_FLOAT:
139 return context->getClientVersion() >= ES_3_0 ||
140 context->getExtensions().textureHalfFloat;
141
142 case GL_HALF_FLOAT_OES:
143 return context->getExtensions().colorBufferHalfFloat;
144
145 default:
146 return false;
147 }
148}
149
Jamie Madill5b772312018-03-08 20:28:32 -0500150bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400151{
152 switch (format)
153 {
154 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
155 case GL_RGBA:
156 case GL_RGB:
157 case GL_ALPHA:
158 return context->getClientVersion() >= ES_2_0;
159
160 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
161 case GL_RG:
162 case GL_RED:
163 case GL_RGBA_INTEGER:
164 case GL_RGB_INTEGER:
165 case GL_RG_INTEGER:
166 case GL_RED_INTEGER:
167 return context->getClientVersion() >= ES_3_0;
168
169 case GL_SRGB_ALPHA_EXT:
170 case GL_SRGB_EXT:
171 return context->getExtensions().sRGB;
172
173 case GL_BGRA_EXT:
174 return context->getExtensions().readFormatBGRA;
175
176 default:
177 return false;
178 }
179}
180
Jamie Madill5b772312018-03-08 20:28:32 -0500181bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400182 GLenum framebufferComponentType,
183 GLenum format,
184 GLenum type)
185{
186 switch (framebufferComponentType)
187 {
188 case GL_UNSIGNED_NORMALIZED:
189 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
190 // ReadPixels with BGRA even if the extension is not present
191 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
192 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
193 type == GL_UNSIGNED_BYTE);
194
195 case GL_SIGNED_NORMALIZED:
196 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
197
198 case GL_INT:
199 return (format == GL_RGBA_INTEGER && type == GL_INT);
200
201 case GL_UNSIGNED_INT:
202 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
203
204 case GL_FLOAT:
205 return (format == GL_RGBA && type == GL_FLOAT);
206
207 default:
208 UNREACHABLE();
209 return false;
210 }
211}
212
Geoff Langc1984ed2016-10-07 12:41:00 -0400213template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400214bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400215{
216 switch (ConvertToGLenum(params[0]))
217 {
218 case GL_CLAMP_TO_EDGE:
219 break;
220
221 case GL_REPEAT:
222 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400223 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400224 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400225 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400227 return false;
228 }
229 break;
230
231 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400233 return false;
234 }
235
236 return true;
237}
238
239template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400240bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400241{
242 switch (ConvertToGLenum(params[0]))
243 {
244 case GL_NEAREST:
245 case GL_LINEAR:
246 break;
247
248 case GL_NEAREST_MIPMAP_NEAREST:
249 case GL_LINEAR_MIPMAP_NEAREST:
250 case GL_NEAREST_MIPMAP_LINEAR:
251 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400252 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400253 {
254 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400256 return false;
257 }
258 break;
259
260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400262 return false;
263 }
264
265 return true;
266}
267
268template <typename ParamType>
269bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
270{
271 switch (ConvertToGLenum(params[0]))
272 {
273 case GL_NEAREST:
274 case GL_LINEAR:
275 break;
276
277 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
286bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
287{
288 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_NONE:
292 case GL_COMPARE_REF_TO_TEXTURE:
293 break;
294
295 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 return false;
298 }
299
300 return true;
301}
302
303template <typename ParamType>
304bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
305{
306 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
307 switch (ConvertToGLenum(params[0]))
308 {
309 case GL_LEQUAL:
310 case GL_GEQUAL:
311 case GL_LESS:
312 case GL_GREATER:
313 case GL_EQUAL:
314 case GL_NOTEQUAL:
315 case GL_ALWAYS:
316 case GL_NEVER:
317 break;
318
319 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400321 return false;
322 }
323
324 return true;
325}
326
327template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700328bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
329{
330 if (!context->getExtensions().textureSRGBDecode)
331 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700333 return false;
334 }
335
336 switch (ConvertToGLenum(params[0]))
337 {
338 case GL_DECODE_EXT:
339 case GL_SKIP_DECODE_EXT:
340 break;
341
342 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700344 return false;
345 }
346
347 return true;
348}
349
Luc Ferron1b1a8642018-01-23 15:12:01 -0500350bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
351{
352 if (!context->getExtensions().textureFilterAnisotropic)
353 {
354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
355 return false;
356 }
357
358 return true;
359}
360
361bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
362{
363 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
364 {
365 return false;
366 }
367
368 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
369
370 if (paramValue < 1 || paramValue > largest)
371 {
372 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
373 return false;
374 }
375
376 return true;
377}
378
Jamie Madill5b772312018-03-08 20:28:32 -0500379bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400380{
381 const Program *program = context->getGLState().getProgram();
382 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
383
Jamie Madille7d80f32018-08-08 15:49:23 -0400384 return ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
385 framebuffer->getDrawBufferTypeMask().to_ulong(),
386 program->getActiveOutputVariables().to_ulong(),
387 framebuffer->getDrawBufferMask().to_ulong());
Geoff Lange0cff192017-05-30 13:04:56 -0400388}
389
Jamie Madill5b772312018-03-08 20:28:32 -0500390bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400391{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700392 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400393 const Program *program = context->getGLState().getProgram();
394 const VertexArray *vao = context->getGLState().getVertexArray();
395
Brandon Jonesc405ae72017-12-06 14:15:03 -0800396 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
397 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
398 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
399
400 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
401 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
402 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
403
Jamie Madille7d80f32018-08-08 15:49:23 -0400404 return ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(),
405 vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
406 0xFFFF);
Geoff Lang9ab5b822017-05-30 16:19:23 -0400407}
408
Jamie Madill493f9572018-05-24 19:52:15 -0400409bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
410 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800411{
412 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400413 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800414 {
Jamie Madill493f9572018-05-24 19:52:15 -0400415 case PrimitiveMode::Points:
416 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
417 case PrimitiveMode::Lines:
418 case PrimitiveMode::LineStrip:
419 case PrimitiveMode::LineLoop:
420 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
421 case PrimitiveMode::LinesAdjacency:
422 case PrimitiveMode::LineStripAdjacency:
423 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
424 case PrimitiveMode::Triangles:
425 case PrimitiveMode::TriangleFan:
426 case PrimitiveMode::TriangleStrip:
427 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
428 case PrimitiveMode::TrianglesAdjacency:
429 case PrimitiveMode::TriangleStripAdjacency:
430 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800431 default:
432 UNREACHABLE();
433 return false;
434 }
435}
436
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700437// GLES1 texture parameters are a small subset of the others
438bool IsValidGLES1TextureParameter(GLenum pname)
439{
440 switch (pname)
441 {
442 case GL_TEXTURE_MAG_FILTER:
443 case GL_TEXTURE_MIN_FILTER:
444 case GL_TEXTURE_WRAP_S:
445 case GL_TEXTURE_WRAP_T:
446 case GL_TEXTURE_WRAP_R:
447 case GL_GENERATE_MIPMAP:
448 case GL_TEXTURE_CROP_RECT_OES:
449 return true;
450 default:
451 return false;
452 }
453}
Geoff Langf41a7152016-09-19 15:11:17 -0400454} // anonymous namespace
455
Brandon Jonesd1049182018-03-28 10:02:20 -0700456void SetRobustLengthParam(GLsizei *length, GLsizei value)
457{
458 if (length)
459 {
460 *length = value;
461 }
462}
463
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500464bool IsETC2EACFormat(const GLenum format)
465{
466 // ES 3.1, Table 8.19
467 switch (format)
468 {
469 case GL_COMPRESSED_R11_EAC:
470 case GL_COMPRESSED_SIGNED_R11_EAC:
471 case GL_COMPRESSED_RG11_EAC:
472 case GL_COMPRESSED_SIGNED_RG11_EAC:
473 case GL_COMPRESSED_RGB8_ETC2:
474 case GL_COMPRESSED_SRGB8_ETC2:
475 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
476 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
477 case GL_COMPRESSED_RGBA8_ETC2_EAC:
478 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
479 return true;
480
481 default:
482 return false;
483 }
484}
485
Jamie Madill5b772312018-03-08 20:28:32 -0500486bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400487{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800488 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400489 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800490 case TextureType::_2D:
491 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800492 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400493
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800494 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400495 return context->getExtensions().textureRectangle;
496
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800497 case TextureType::_3D:
498 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800499 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500500
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800501 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800502 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400503
He Yunchaoced53ae2016-11-29 15:00:51 +0800504 default:
505 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500506 }
Jamie Madill35d15012013-10-07 10:46:37 -0400507}
508
Jamie Madill5b772312018-03-08 20:28:32 -0500509bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500510{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800511 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500512 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 case TextureType::_2D:
514 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500515 return true;
516
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800517 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400518 return context->getExtensions().textureRectangle;
519
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500520 default:
521 return false;
522 }
523}
524
Jamie Madill5b772312018-03-08 20:28:32 -0500525bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500526{
527 switch (target)
528 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 case TextureType::_3D:
530 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300531 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500532
533 default:
534 return false;
535 }
536}
537
Ian Ewellbda75592016-04-18 17:25:54 -0400538// Most texture GL calls are not compatible with external textures, so we have a separate validation
539// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500540bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400541{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400543 (context->getExtensions().eglImageExternal ||
544 context->getExtensions().eglStreamConsumerExternal);
545}
546
Shannon Woods4dfed832014-03-17 20:03:39 -0400547// This function differs from ValidTextureTarget in that the target must be
548// usable as the destination of a 2D operation-- so a cube face is valid, but
549// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400550// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500551bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400552{
553 switch (target)
554 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 case TextureTarget::_2D:
556 case TextureTarget::CubeMapNegativeX:
557 case TextureTarget::CubeMapNegativeY:
558 case TextureTarget::CubeMapNegativeZ:
559 case TextureTarget::CubeMapPositiveX:
560 case TextureTarget::CubeMapPositiveY:
561 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800562 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400564 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800565 default:
566 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500567 }
568}
569
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800570bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400571 PrimitiveMode transformFeedbackPrimitiveMode,
572 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800573{
574 ASSERT(context);
575
576 if (!context->getExtensions().geometryShader)
577 {
578 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
579 // that does not match the current transform feedback object's draw mode (if transform
580 // feedback is active), (3.0.2, section 2.14, pg 86)
581 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
582 }
583
584 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400585 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800586 {
Jamie Madill493f9572018-05-24 19:52:15 -0400587 case PrimitiveMode::Points:
588 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
589 case PrimitiveMode::Lines:
590 case PrimitiveMode::LineStrip:
591 case PrimitiveMode::LineLoop:
592 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
593 case PrimitiveMode::Triangles:
594 case PrimitiveMode::TriangleFan:
595 case PrimitiveMode::TriangleStrip:
596 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800597 default:
598 UNREACHABLE();
599 return false;
600 }
601}
602
Jamie Madill5b772312018-03-08 20:28:32 -0500603bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400604 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400605 GLsizei count,
606 GLenum type,
607 const GLvoid *indices,
608 GLsizei primcount)
609{
610 if (primcount < 0)
611 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700612 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400613 return false;
614 }
615
616 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
617 {
618 return false;
619 }
620
Jamie Madill9fdaa492018-02-16 10:52:11 -0500621 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400622}
623
624bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400625 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400626 GLint first,
627 GLsizei count,
628 GLsizei primcount)
629{
630 if (primcount < 0)
631 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700632 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 return false;
634 }
635
636 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
637 {
638 return false;
639 }
640
Jamie Madill9fdaa492018-02-16 10:52:11 -0500641 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400642}
643
Jamie Madill5b772312018-03-08 20:28:32 -0500644bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400645{
646 // Verify there is at least one active attribute with a divisor of zero
647 const State &state = context->getGLState();
648
649 Program *program = state.getProgram();
650
651 const auto &attribs = state.getVertexArray()->getVertexAttributes();
652 const auto &bindings = state.getVertexArray()->getVertexBindings();
653 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
654 {
655 const VertexAttribute &attrib = attribs[attributeIndex];
656 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300657 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400658 {
659 return true;
660 }
661 }
662
Brandon Jonesafa75152017-07-21 13:11:29 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400664 return false;
665}
666
Jamie Madill5b772312018-03-08 20:28:32 -0500667bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668{
669 switch (target)
670 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800671 case TextureType::_3D:
672 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800673 return true;
674 default:
675 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400676 }
677}
678
Jamie Madill5b772312018-03-08 20:28:32 -0500679bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800680{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800681 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800682 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800683 case TextureType::_2D:
684 case TextureType::_2DArray:
685 case TextureType::_2DMultisample:
686 case TextureType::CubeMap:
687 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800688 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800689 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400690 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800691 default:
692 return false;
693 }
694}
695
Jamie Madill5b772312018-03-08 20:28:32 -0500696bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500697{
He Yunchaoced53ae2016-11-29 15:00:51 +0800698 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
699 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400700 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500701
702 switch (target)
703 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 case GL_FRAMEBUFFER:
705 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400706
He Yunchaoced53ae2016-11-29 15:00:51 +0800707 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400709 return (context->getExtensions().framebufferBlit ||
710 context->getClientMajorVersion() >= 3);
711
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 default:
713 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500714 }
715}
716
Jamie Madill5b772312018-03-08 20:28:32 -0500717bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400718{
Jamie Madillc29968b2016-01-20 11:17:23 -0500719 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400720 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800721 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400722 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800723 case TextureType::_2D:
724 case TextureType::_2DArray:
725 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500726 maxDimension = caps.max2DTextureSize;
727 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800729 maxDimension = caps.maxCubeMapTextureSize;
730 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800731 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400732 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800733 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 maxDimension = caps.max3DTextureSize;
735 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 default:
737 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400738 }
739
Jamie Madill43da7c42018-08-01 11:34:49 -0400740 return level <= log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400741}
742
Jamie Madill5b772312018-03-08 20:28:32 -0500743bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800744 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700745 GLint level,
746 GLsizei width,
747 GLsizei height,
748 GLsizei depth,
749 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400750{
Brandon Jones6cad5662017-06-14 13:25:13 -0700751 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400752 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700753 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400754 return false;
755 }
Austin Kinross08528e12015-10-07 16:24:40 -0700756 // TexSubImage parameters can be NPOT without textureNPOT extension,
757 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500758 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500759 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500760 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill43da7c42018-08-01 11:34:49 -0400761 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400762 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700763 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400764 return false;
765 }
766
767 if (!ValidMipLevel(context, target, level))
768 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400770 return false;
771 }
772
773 return true;
774}
775
Geoff Lang966c9402017-04-18 12:38:27 -0400776bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
777{
778 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
779 (size % blockSize == 0);
780}
781
Jamie Madill5b772312018-03-08 20:28:32 -0500782bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500783 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400784 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500785 GLsizei width,
786 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400787{
Jamie Madill43da7c42018-08-01 11:34:49 -0400788 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400789 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400790 {
791 return false;
792 }
793
Geoff Lang966c9402017-04-18 12:38:27 -0400794 if (width < 0 || height < 0)
795 {
796 return false;
797 }
798
799 if (CompressedTextureFormatRequiresExactSize(internalFormat))
800 {
801 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
802 // block size for level 0 but WebGL disallows this.
803 bool smallerThanBlockSizeAllowed =
804 level > 0 || !context->getExtensions().webglCompatibility;
805
806 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
807 smallerThanBlockSizeAllowed) ||
808 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
809 smallerThanBlockSizeAllowed))
810 {
811 return false;
812 }
813 }
814
815 return true;
816}
817
Jamie Madill5b772312018-03-08 20:28:32 -0500818bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400819 GLenum internalFormat,
820 GLint xoffset,
821 GLint yoffset,
822 GLsizei width,
823 GLsizei height,
824 size_t textureWidth,
825 size_t textureHeight)
826{
Jamie Madill43da7c42018-08-01 11:34:49 -0400827 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
Geoff Lang966c9402017-04-18 12:38:27 -0400828 if (!formatInfo.compressed)
829 {
830 return false;
831 }
832
Geoff Lang44ff5a72017-02-03 15:15:43 -0500833 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400834 {
835 return false;
836 }
837
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500838 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400839 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500840 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400841 yoffset % formatInfo.compressedBlockHeight != 0)
842 {
843 return false;
844 }
845
846 // Allowed to either have data that is a multiple of block size or is smaller than the block
847 // size but fills the entire mip
848 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
849 static_cast<size_t>(width) == textureWidth &&
850 static_cast<size_t>(height) == textureHeight;
851 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
852 (height % formatInfo.compressedBlockHeight) == 0;
853 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400854 {
855 return false;
856 }
857 }
858
Geoff Langd4f180b2013-09-24 13:57:44 -0400859 return true;
860}
861
Jamie Madill5b772312018-03-08 20:28:32 -0500862bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800863 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400864 GLsizei width,
865 GLsizei height,
866 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400867 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400868 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400869 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400870 GLsizei imageSize)
871{
Jamie Madill43da7c42018-08-01 11:34:49 -0400872 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400873 if (pixelUnpackBuffer == nullptr && imageSize < 0)
874 {
875 // Checks are not required
876 return true;
877 }
878
879 // ...the data would be unpacked from the buffer object such that the memory reads required
880 // would exceed the data store size.
Jamie Madill43da7c42018-08-01 11:34:49 -0400881 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Langdbcced82017-06-06 15:55:54 -0400882 ASSERT(formatInfo.internalFormat != GL_NONE);
Jamie Madill43da7c42018-08-01 11:34:49 -0400883 const Extents size(width, height, depth);
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 const auto &unpack = context->getGLState().getUnpackState();
885
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800886 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400887 GLuint endByte = 0;
888 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 return false;
892 }
893
Geoff Langff5b2d52016-09-07 11:32:23 -0400894 if (pixelUnpackBuffer)
895 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400896 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
898 checkedEndByte += checkedOffset;
899
900 if (!checkedEndByte.IsValid() ||
901 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
902 {
903 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 return false;
906 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800907 if (context->getExtensions().webglCompatibility &&
908 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
909 {
910 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
911 PixelUnpackBufferBoundForTransformFeedback);
912 return false;
913 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400914 }
915 else
916 {
917 ASSERT(imageSize >= 0);
918 if (pixels == nullptr && imageSize != 0)
919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500920 context->handleError(InvalidOperation()
921 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400922 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 }
924
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400925 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 return false;
929 }
930 }
931
932 return true;
933}
934
Corentin Wallezad3ae902018-03-09 13:40:42 -0500935bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -0500936{
Geoff Lang37dde692014-01-31 16:34:54 -0500937 switch (queryType)
938 {
Corentin Wallezad3ae902018-03-09 13:40:42 -0500939 case QueryType::AnySamples:
940 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400941 return context->getClientMajorVersion() >= 3 ||
942 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500943 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +0800944 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -0500945 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +0800946 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500947 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -0500949 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800950 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 default:
952 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500953 }
954}
955
Jamie Madill5b772312018-03-08 20:28:32 -0500956bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400957 GLenum type,
958 GLboolean normalized,
959 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400960 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400961 bool pureInteger)
962{
963 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
965 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
966 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
967 // parameter exceeds 255.
968 constexpr GLsizei kMaxWebGLStride = 255;
969 if (stride > kMaxWebGLStride)
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidValue()
972 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400973 return false;
974 }
975
976 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
977 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
978 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
979 // or an INVALID_OPERATION error is generated.
980 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
981 size_t typeSize = GetVertexFormatTypeSize(internalType);
982
983 ASSERT(isPow2(typeSize) && typeSize > 0);
984 size_t sizeMask = (typeSize - 1);
985 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
986 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 if ((stride & sizeMask) != 0)
992 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 return false;
995 }
996
997 return true;
998}
999
Jamie Madill5b772312018-03-08 20:28:32 -05001000Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001001{
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1003 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1004 // or program object and INVALID_OPERATION if the provided name identifies an object
1005 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001006
Dian Xiang769769a2015-09-09 15:20:08 -07001007 Program *validProgram = context->getProgram(id);
1008
1009 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001010 {
Dian Xiang769769a2015-09-09 15:20:08 -07001011 if (context->getShader(id))
1012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001014 }
1015 else
1016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001017 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001018 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001019 }
Dian Xiang769769a2015-09-09 15:20:08 -07001020
1021 return validProgram;
1022}
1023
Jamie Madill5b772312018-03-08 20:28:32 -05001024Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001025{
1026 // See ValidProgram for spec details.
1027
1028 Shader *validShader = context->getShader(id);
1029
1030 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001031 {
Dian Xiang769769a2015-09-09 15:20:08 -07001032 if (context->getProgram(id))
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001035 }
1036 else
1037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001039 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001040 }
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001043}
1044
Jamie Madill43da7c42018-08-01 11:34:49 -04001045bool ValidateAttachmentTarget(Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001046{
Geoff Langfa125c92017-10-24 13:01:46 -04001047 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001048 {
Geoff Langfa125c92017-10-24 13:01:46 -04001049 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1050 {
1051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1052 return false;
1053 }
Jamie Madillb4472272014-07-03 10:38:55 -04001054
Geoff Langfa125c92017-10-24 13:01:46 -04001055 // Color attachment 0 is validated below because it is always valid
1056 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001058 {
Geoff Langfa125c92017-10-24 13:01:46 -04001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001061 }
1062 }
1063 else
1064 {
1065 switch (attachment)
1066 {
Geoff Langfa125c92017-10-24 13:01:46 -04001067 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001068 case GL_DEPTH_ATTACHMENT:
1069 case GL_STENCIL_ATTACHMENT:
1070 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001071
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_DEPTH_STENCIL_ATTACHMENT:
1073 if (!context->getExtensions().webglCompatibility &&
1074 context->getClientMajorVersion() < 3)
1075 {
Geoff Langfa125c92017-10-24 13:01:46 -04001076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001080
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001084 }
1085 }
1086
1087 return true;
1088}
1089
Jamie Madill5b772312018-03-08 20:28:32 -05001090bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 GLenum target,
1092 GLsizei samples,
1093 GLenum internalformat,
1094 GLsizei width,
1095 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096{
1097 switch (target)
1098 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001099 case GL_RENDERBUFFER:
1100 break;
1101 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105
1106 if (width < 0 || height < 0 || samples < 0)
1107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001112 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1113 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1114
1115 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001116 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001118 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
1122 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1123 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001124 // only sized internal formats.
Jamie Madill43da7c42018-08-01 11:34:49 -04001125 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
Geoff Langca271392017-04-05 12:30:00 -04001126 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 }
1131
Geoff Langaae65a42014-05-26 12:43:44 -04001132 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 if (handle == 0)
1140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
1145 return true;
1146}
1147
Jamie Madill43da7c42018-08-01 11:34:49 -04001148bool ValidateFramebufferRenderbufferParameters(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001149 GLenum target,
1150 GLenum attachment,
1151 GLenum renderbuffertarget,
1152 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001153{
Geoff Lange8afa902017-09-27 15:00:43 -04001154 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001158 }
1159
Jamie Madill43da7c42018-08-01 11:34:49 -04001160 Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161
Jamie Madill84115c92015-04-23 15:00:07 -04001162 ASSERT(framebuffer);
1163 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167 }
1168
Jamie Madillb4472272014-07-03 10:38:55 -04001169 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001170 {
Jamie Madillb4472272014-07-03 10:38:55 -04001171 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 }
1173
Jamie Madillab9d82c2014-01-21 16:38:14 -05001174 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1175 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1176 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1177 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1178 if (renderbuffer != 0)
1179 {
1180 if (!context->getRenderbuffer(renderbuffer))
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001184 }
1185 }
1186
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 return true;
1188}
1189
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001190bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001191 GLint srcX0,
1192 GLint srcY0,
1193 GLint srcX1,
1194 GLint srcY1,
1195 GLint dstX0,
1196 GLint dstY0,
1197 GLint dstX1,
1198 GLint dstY1,
1199 GLbitfield mask,
1200 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201{
1202 switch (filter)
1203 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 case GL_NEAREST:
1205 break;
1206 case GL_LINEAR:
1207 break;
1208 default:
Olli Etuahof0e3c192018-08-15 13:37:21 +03001209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), BlitInvalidFilter);
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 }
1212
1213 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1214 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001215 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitInvalidMask);
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1220 // color buffer, leaving only nearest being unfiltered from above
1221 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1222 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitOnlyNearestForNonColor);
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
Jamie Madill51f40ec2016-06-15 14:06:00 -04001227 const auto &glState = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04001228 Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1229 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001230
1231 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001233 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFramebufferMissing);
Geoff Langb1196682014-07-23 13:47:29 -04001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
Jamie Madill427064d2018-04-13 16:20:34 -04001237 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001238 {
Jamie Madill48faf802014-11-06 15:27:22 -05001239 return false;
1240 }
1241
Jamie Madill427064d2018-04-13 16:20:34 -04001242 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001243 {
Jamie Madill48faf802014-11-06 15:27:22 -05001244 return false;
1245 }
1246
Qin Jiajiaaef92162018-02-27 13:51:44 +08001247 if (readFramebuffer->id() == drawFramebuffer->id())
1248 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitFeedbackLoop);
Qin Jiajiaaef92162018-02-27 13:51:44 +08001250 return false;
1251 }
1252
Jamie Madille98b1b52018-03-08 09:47:23 -05001253 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001258 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1259 // always run it in order to avoid triggering driver bugs.
1260 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1261 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001262 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001263 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1264 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001265 }
1266
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1268
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 if (mask & GL_COLOR_BUFFER_BIT)
1270 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001271 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001272 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273
He Yunchao66a41a22016-12-15 16:45:05 +08001274 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001276 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277
Geoff Langa15472a2015-08-11 11:48:03 -04001278 for (size_t drawbufferIdx = 0;
1279 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Geoff Langa15472a2015-08-11 11:48:03 -04001281 const FramebufferAttachment *attachment =
1282 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1283 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001285 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286
Geoff Langb2f3d052013-08-13 12:49:27 -04001287 // The GL ES 3.0.2 spec (pg 193) states that:
1288 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1290 // as well
1291 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1292 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001293 // Changes with EXT_color_buffer_float:
1294 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001295 GLenum readComponentType = readFormat.info->componentType;
1296 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001298 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001299 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001300 drawComponentType == GL_SIGNED_NORMALIZED);
1301
1302 if (extensions.colorBufferFloat)
1303 {
1304 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1305 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1306
1307 if (readFixedOrFloat != drawFixedOrFloat)
1308 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001309 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1310 BlitTypeMismatchFixedOrFloat);
Jamie Madill6163c752015-12-07 16:32:59 -05001311 return false;
1312 }
1313 }
1314 else if (readFixedPoint != drawFixedPoint)
1315 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001316 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1317 BlitTypeMismatchFixedPoint);
Jamie Madill6163c752015-12-07 16:32:59 -05001318 return false;
1319 }
1320
1321 if (readComponentType == GL_UNSIGNED_INT &&
1322 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1325 BlitTypeMismatchUnsignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001326 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327 }
1328
Jamie Madill6163c752015-12-07 16:32:59 -05001329 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001331 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1332 BlitTypeMismatchSignedInteger);
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335
Jamie Madilla3944d42016-07-22 22:13:26 -04001336 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001337 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001339 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1340 BlitMultisampledFormatOrBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 }
Geoff Lange4915782017-04-12 15:19:07 -04001343
1344 if (context->getExtensions().webglCompatibility &&
1345 *readColorBuffer == *attachment)
1346 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001347 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageColor);
Geoff Lange4915782017-04-12 15:19:07 -04001348 return false;
1349 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 }
1351 }
1352
Jamie Madilla3944d42016-07-22 22:13:26 -04001353 if ((readFormat.info->componentType == GL_INT ||
1354 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1355 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001357 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitIntegerWithLinearFilter);
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
He Yunchao66a41a22016-12-15 16:45:05 +08001361 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1362 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1363 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1364 // situation is an application error that would lead to a crash in ANGLE.
1365 else if (drawFramebuffer->hasEnabledDrawBuffer())
1366 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001367 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingColor);
He Yunchao66a41a22016-12-15 16:45:05 +08001368 return false;
1369 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
1371
He Yunchaoced53ae2016-11-29 15:00:51 +08001372 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001373 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1374 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001376 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 {
Jamie Madill43da7c42018-08-01 11:34:49 -04001378 const FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001379 readFramebuffer->getAttachment(context, attachments[i]);
Jamie Madill43da7c42018-08-01 11:34:49 -04001380 const FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001381 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001383 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Kenneth Russell69382852017-07-21 16:38:44 -04001385 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001387 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1388 BlitDepthOrStencilFormatMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001392 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001394 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1395 BlitMultisampledBoundsMismatch);
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
Geoff Lange4915782017-04-12 15:19:07 -04001398
1399 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1400 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001401 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitSameImageDepthOrStencil);
Geoff Lange4915782017-04-12 15:19:07 -04001402 return false;
1403 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
He Yunchao66a41a22016-12-15 16:45:05 +08001405 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1406 else if (drawBuffer)
1407 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BlitMissingDepthOrStencil);
He Yunchao66a41a22016-12-15 16:45:05 +08001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
1412 }
1413
Martin Radeva3ed4572017-07-27 18:29:37 +03001414 // ANGLE_multiview, Revision 1:
1415 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001416 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1417 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1418 // views in the current read framebuffer is more than one.
1419 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001420 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001421 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitFromMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001422 return false;
1423 }
1424 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1425 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03001426 ANGLE_VALIDATION_ERR(context, InvalidFramebufferOperation(), BlitToMultiview);
Martin Radeva3ed4572017-07-27 18:29:37 +03001427 return false;
1428 }
1429
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 return true;
1431}
1432
Jamie Madill4928b7c2017-06-20 12:57:39 -04001433bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001434 GLint x,
1435 GLint y,
1436 GLsizei width,
1437 GLsizei height,
1438 GLenum format,
1439 GLenum type,
1440 GLsizei bufSize,
1441 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001442 GLsizei *columns,
1443 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001444 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001445{
1446 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001447 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001448 return false;
1449 }
1450
Brandon Jonesd1049182018-03-28 10:02:20 -07001451 GLsizei writeLength = 0;
1452 GLsizei writeColumns = 0;
1453 GLsizei writeRows = 0;
1454
1455 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1456 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001457 {
Geoff Langb1196682014-07-23 13:47:29 -04001458 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001459 }
1460
Brandon Jonesd1049182018-03-28 10:02:20 -07001461 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001462 {
Geoff Langb1196682014-07-23 13:47:29 -04001463 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001464 }
1465
Brandon Jonesd1049182018-03-28 10:02:20 -07001466 SetRobustLengthParam(length, writeLength);
1467 SetRobustLengthParam(columns, writeColumns);
1468 SetRobustLengthParam(rows, writeRows);
1469
Jamie Madillc29968b2016-01-20 11:17:23 -05001470 return true;
1471}
1472
1473bool ValidateReadnPixelsEXT(Context *context,
1474 GLint x,
1475 GLint y,
1476 GLsizei width,
1477 GLsizei height,
1478 GLenum format,
1479 GLenum type,
1480 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001481 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001482{
1483 if (bufSize < 0)
1484 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001485 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001486 return false;
1487 }
1488
Geoff Lang62fce5b2016-09-30 10:46:35 -04001489 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001490 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491}
Jamie Madill26e91952014-03-05 15:01:27 -05001492
Jamie Madill4928b7c2017-06-20 12:57:39 -04001493bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001494 GLint x,
1495 GLint y,
1496 GLsizei width,
1497 GLsizei height,
1498 GLenum format,
1499 GLenum type,
1500 GLsizei bufSize,
1501 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001502 GLsizei *columns,
1503 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001504 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505{
Brandon Jonesd1049182018-03-28 10:02:20 -07001506 GLsizei writeLength = 0;
1507 GLsizei writeColumns = 0;
1508 GLsizei writeRows = 0;
1509
Geoff Lang62fce5b2016-09-30 10:46:35 -04001510 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001511 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001512 return false;
1513 }
1514
Brandon Jonesd1049182018-03-28 10:02:20 -07001515 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1516 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001517 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001518 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001519 }
1520
Brandon Jonesd1049182018-03-28 10:02:20 -07001521 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001522 {
1523 return false;
1524 }
1525
Brandon Jonesd1049182018-03-28 10:02:20 -07001526 SetRobustLengthParam(length, writeLength);
1527 SetRobustLengthParam(columns, writeColumns);
1528 SetRobustLengthParam(rows, writeRows);
1529
Geoff Lang62fce5b2016-09-30 10:46:35 -04001530 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001531}
1532
Jamie Madill43da7c42018-08-01 11:34:49 -04001533bool ValidateGenQueriesEXT(Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001534{
1535 if (!context->getExtensions().occlusionQueryBoolean &&
1536 !context->getExtensions().disjointTimerQuery)
1537 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001539 return false;
1540 }
1541
Olli Etuaho41997e72016-03-10 13:38:39 +02001542 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001543}
1544
Jamie Madill43da7c42018-08-01 11:34:49 -04001545bool ValidateDeleteQueriesEXT(Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001546{
1547 if (!context->getExtensions().occlusionQueryBoolean &&
1548 !context->getExtensions().disjointTimerQuery)
1549 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001551 return false;
1552 }
1553
Olli Etuaho41997e72016-03-10 13:38:39 +02001554 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001555}
1556
Jamie Madill43da7c42018-08-01 11:34:49 -04001557bool ValidateIsQueryEXT(Context *context, GLuint id)
Jamie Madillf0e04492017-08-26 15:28:42 -04001558{
1559 if (!context->getExtensions().occlusionQueryBoolean &&
1560 !context->getExtensions().disjointTimerQuery)
1561 {
1562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1563 return false;
1564 }
1565
1566 return true;
1567}
1568
Jamie Madill43da7c42018-08-01 11:34:49 -04001569bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001570{
1571 if (!ValidQueryType(context, target))
1572 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001574 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001575 }
1576
1577 if (id == 0)
1578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001579 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001580 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001581 }
1582
1583 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1584 // of zero, if the active query object name for <target> is non-zero (for the
1585 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1586 // the active query for either target is non-zero), if <id> is the name of an
1587 // existing query object whose type does not match <target>, or if <id> is the
1588 // active query object name for any query type, the error INVALID_OPERATION is
1589 // generated.
1590
1591 // Ensure no other queries are active
1592 // NOTE: If other queries than occlusion are supported, we will need to check
1593 // separately that:
1594 // a) The query ID passed is not the current active query for any target/type
1595 // b) There are no active queries for the requested target (and in the case
1596 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1597 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001599 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001601 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001602 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001603 }
1604
1605 Query *queryObject = context->getQuery(id, true, target);
1606
1607 // check that name was obtained with glGenQueries
1608 if (!queryObject)
1609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001612 }
1613
1614 // check for type mismatch
1615 if (queryObject->getType() != target)
1616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001619 }
1620
1621 return true;
1622}
1623
Jamie Madill43da7c42018-08-01 11:34:49 -04001624bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001625{
1626 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001627 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001628 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001630 return false;
1631 }
1632
1633 return ValidateBeginQueryBase(context, target, id);
1634}
1635
Jamie Madill43da7c42018-08-01 11:34:49 -04001636bool ValidateEndQueryBase(Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001637{
1638 if (!ValidQueryType(context, target))
1639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001640 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001642 }
1643
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001644 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001645
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001648 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001650 }
1651
Jamie Madill45c785d2014-05-13 14:09:34 -04001652 return true;
1653}
1654
Jamie Madill43da7c42018-08-01 11:34:49 -04001655bool ValidateEndQueryEXT(Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656{
1657 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001658 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661 return false;
1662 }
1663
1664 return ValidateEndQueryBase(context, target);
1665}
1666
Corentin Wallezad3ae902018-03-09 13:40:42 -05001667bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668{
1669 if (!context->getExtensions().disjointTimerQuery)
1670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001671 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672 return false;
1673 }
1674
Corentin Wallezad3ae902018-03-09 13:40:42 -05001675 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001677 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678 return false;
1679 }
1680
1681 Query *queryObject = context->getQuery(id, true, target);
1682 if (queryObject == nullptr)
1683 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685 return false;
1686 }
1687
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001688 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 return false;
1692 }
1693
1694 return true;
1695}
1696
Corentin Wallezad3ae902018-03-09 13:40:42 -05001697bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001698{
Geoff Lang2186c382016-10-14 10:54:54 -04001699 if (numParams)
1700 {
1701 *numParams = 0;
1702 }
1703
Corentin Wallezad3ae902018-03-09 13:40:42 -05001704 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001706 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 switch (pname)
1711 {
1712 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001713 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716 return false;
1717 }
1718 break;
1719 case GL_QUERY_COUNTER_BITS_EXT:
1720 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001721 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001723 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726 break;
1727 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001728 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 return false;
1730 }
1731
Geoff Lang2186c382016-10-14 10:54:54 -04001732 if (numParams)
1733 {
1734 // All queries return only one value
1735 *numParams = 1;
1736 }
1737
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 return true;
1739}
1740
Corentin Wallezad3ae902018-03-09 13:40:42 -05001741bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742{
1743 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001744 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001746 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
Geoff Lang2186c382016-10-14 10:54:54 -04001750 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751}
1752
Geoff Lang2186c382016-10-14 10:54:54 -04001753bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001754 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001755 GLenum pname,
1756 GLsizei bufSize,
1757 GLsizei *length,
1758 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759{
Geoff Lang2186c382016-10-14 10:54:54 -04001760 if (!ValidateRobustEntryPoint(context, bufSize))
1761 {
1762 return false;
1763 }
1764
Brandon Jonesd1049182018-03-28 10:02:20 -07001765 GLsizei numParams = 0;
1766
1767 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001768 {
1769 return false;
1770 }
1771
Brandon Jonesd1049182018-03-28 10:02:20 -07001772 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001773 {
1774 return false;
1775 }
1776
Brandon Jonesd1049182018-03-28 10:02:20 -07001777 SetRobustLengthParam(length, numParams);
1778
Geoff Lang2186c382016-10-14 10:54:54 -04001779 return true;
1780}
1781
1782bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1783{
1784 if (numParams)
1785 {
1786 *numParams = 0;
1787 }
1788
Corentin Wallezad3ae902018-03-09 13:40:42 -05001789 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790
1791 if (!queryObject)
1792 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 return false;
1795 }
1796
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001797 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001799 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 return false;
1801 }
1802
1803 switch (pname)
1804 {
1805 case GL_QUERY_RESULT_EXT:
1806 case GL_QUERY_RESULT_AVAILABLE_EXT:
1807 break;
1808
1809 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001810 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811 return false;
1812 }
1813
Geoff Lang2186c382016-10-14 10:54:54 -04001814 if (numParams)
1815 {
1816 *numParams = 1;
1817 }
1818
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return true;
1820}
1821
1822bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1823{
1824 if (!context->getExtensions().disjointTimerQuery)
1825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001826 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
Geoff Lang2186c382016-10-14 10:54:54 -04001829 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1830}
1831
1832bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1833 GLuint id,
1834 GLenum pname,
1835 GLsizei bufSize,
1836 GLsizei *length,
1837 GLint *params)
1838{
1839 if (!context->getExtensions().disjointTimerQuery)
1840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001841 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001842 return false;
1843 }
1844
1845 if (!ValidateRobustEntryPoint(context, bufSize))
1846 {
1847 return false;
1848 }
1849
Brandon Jonesd1049182018-03-28 10:02:20 -07001850 GLsizei numParams = 0;
1851
1852 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001853 {
1854 return false;
1855 }
1856
Brandon Jonesd1049182018-03-28 10:02:20 -07001857 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001858 {
1859 return false;
1860 }
1861
Brandon Jonesd1049182018-03-28 10:02:20 -07001862 SetRobustLengthParam(length, numParams);
1863
Geoff Lang2186c382016-10-14 10:54:54 -04001864 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865}
1866
1867bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1868{
1869 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001870 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return false;
1874 }
Geoff Lang2186c382016-10-14 10:54:54 -04001875 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1876}
1877
1878bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1879 GLuint id,
1880 GLenum pname,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLuint *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery &&
1886 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001889 return false;
1890 }
1891
1892 if (!ValidateRobustEntryPoint(context, bufSize))
1893 {
1894 return false;
1895 }
1896
Brandon Jonesd1049182018-03-28 10:02:20 -07001897 GLsizei numParams = 0;
1898
1899 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001900 {
1901 return false;
1902 }
1903
Brandon Jonesd1049182018-03-28 10:02:20 -07001904 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001905 {
1906 return false;
1907 }
1908
Brandon Jonesd1049182018-03-28 10:02:20 -07001909 SetRobustLengthParam(length, numParams);
1910
Geoff Lang2186c382016-10-14 10:54:54 -04001911 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912}
1913
1914bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1915{
1916 if (!context->getExtensions().disjointTimerQuery)
1917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 return false;
1920 }
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1922}
1923
1924bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1925 GLuint id,
1926 GLenum pname,
1927 GLsizei bufSize,
1928 GLsizei *length,
1929 GLint64 *params)
1930{
1931 if (!context->getExtensions().disjointTimerQuery)
1932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001934 return false;
1935 }
1936
1937 if (!ValidateRobustEntryPoint(context, bufSize))
1938 {
1939 return false;
1940 }
1941
Brandon Jonesd1049182018-03-28 10:02:20 -07001942 GLsizei numParams = 0;
1943
1944 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001950 {
1951 return false;
1952 }
1953
Brandon Jonesd1049182018-03-28 10:02:20 -07001954 SetRobustLengthParam(length, numParams);
1955
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001957}
1958
1959bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1960{
1961 if (!context->getExtensions().disjointTimerQuery)
1962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 return false;
1965 }
Geoff Lang2186c382016-10-14 10:54:54 -04001966 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1967}
1968
1969bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1970 GLuint id,
1971 GLenum pname,
1972 GLsizei bufSize,
1973 GLsizei *length,
1974 GLuint64 *params)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001979 return false;
1980 }
1981
1982 if (!ValidateRobustEntryPoint(context, bufSize))
1983 {
1984 return false;
1985 }
1986
Brandon Jonesd1049182018-03-28 10:02:20 -07001987 GLsizei numParams = 0;
1988
1989 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001990 {
1991 return false;
1992 }
1993
Brandon Jonesd1049182018-03-28 10:02:20 -07001994 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001995 {
1996 return false;
1997 }
1998
Brandon Jonesd1049182018-03-28 10:02:20 -07001999 SetRobustLengthParam(length, numParams);
2000
Geoff Lang2186c382016-10-14 10:54:54 -04002001 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002}
2003
Jamie Madill5b772312018-03-08 20:28:32 -05002004bool ValidateUniformCommonBase(Context *context,
Jamie Madill43da7c42018-08-01 11:34:49 -04002005 Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002006 GLint location,
2007 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002008 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002009{
Jiajia Qin5451d532017-11-16 17:16:34 +08002010 // TODO(Jiajia): Add image uniform check in future.
2011 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002012 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002013 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002014 return false;
2015 }
2016
Jiajia Qin5451d532017-11-16 17:16:34 +08002017 if (!program)
2018 {
2019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2020 return false;
2021 }
2022
2023 if (!program->isLinked())
2024 {
2025 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2026 return false;
2027 }
2028
2029 if (location == -1)
2030 {
2031 // Silently ignore the uniform command
2032 return false;
2033 }
2034
2035 const auto &uniformLocations = program->getUniformLocations();
2036 size_t castedLocation = static_cast<size_t>(location);
2037 if (castedLocation >= uniformLocations.size())
2038 {
2039 context->handleError(InvalidOperation() << "Invalid uniform location");
2040 return false;
2041 }
2042
2043 const auto &uniformLocation = uniformLocations[castedLocation];
2044 if (uniformLocation.ignored)
2045 {
2046 // Silently ignore the uniform command
2047 return false;
2048 }
2049
2050 if (!uniformLocation.used())
2051 {
2052 context->handleError(InvalidOperation());
2053 return false;
2054 }
2055
2056 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2057
2058 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002059 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 {
2061 context->handleError(InvalidOperation());
2062 return false;
2063 }
2064
2065 *uniformOut = &uniform;
2066 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002067}
2068
Jamie Madill5b772312018-03-08 20:28:32 -05002069bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002070 GLenum uniformType,
2071 GLsizei count,
2072 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002073{
Jiajia Qin5451d532017-11-16 17:16:34 +08002074 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2075 // It is compatible with INT or BOOL.
2076 // Do these cheap tests first, for a little extra speed.
2077 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002078 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002079 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002080 }
2081
Jiajia Qin5451d532017-11-16 17:16:34 +08002082 if (IsSamplerType(uniformType))
2083 {
2084 // Check that the values are in range.
2085 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2086 for (GLsizei i = 0; i < count; ++i)
2087 {
2088 if (value[i] < 0 || value[i] >= max)
2089 {
2090 context->handleError(InvalidValue() << "sampler uniform value out of range");
2091 return false;
2092 }
2093 }
2094 return true;
2095 }
2096
2097 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2098 return false;
2099}
2100
Jamie Madill5b772312018-03-08 20:28:32 -05002101bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002102{
2103 // Check that the value type is compatible with uniform type.
2104 // Do the cheaper test first, for a little extra speed.
2105 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2106 {
2107 return true;
2108 }
2109
2110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2111 return false;
2112}
2113
Jamie Madill5b772312018-03-08 20:28:32 -05002114bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002115{
2116 // Check that the value type is compatible with uniform type.
2117 if (valueType == uniformType)
2118 {
2119 return true;
2120 }
2121
2122 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2123 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002124}
2125
Jamie Madill5b772312018-03-08 20:28:32 -05002126bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002127{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002128 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002129 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002130 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2131 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002132}
2133
Jamie Madill5b772312018-03-08 20:28:32 -05002134bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002135{
2136 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002137 Program *programObject = context->getGLState().getProgram();
Frank Henigmana98a6472017-02-02 21:38:32 -05002138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniform1ivValue(context, uniform->type, count, value);
2140}
2141
Jamie Madill5b772312018-03-08 20:28:32 -05002142bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002143 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002144 GLint location,
2145 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002146 GLboolean transpose)
2147{
Geoff Lang92019432017-11-20 13:09:34 -05002148 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002150 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002151 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002152 }
2153
Jamie Madill62d31cb2015-09-11 13:25:51 -04002154 const LinkedUniform *uniform = nullptr;
Jamie Madill43da7c42018-08-01 11:34:49 -04002155 Program *programObject = context->getGLState().getProgram();
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002156 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2157 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002158}
2159
Jamie Madill5b772312018-03-08 20:28:32 -05002160bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002161{
2162 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002164 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002165 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002166 }
2167
Jamie Madill0af26e12015-03-05 19:54:33 -05002168 const Caps &caps = context->getCaps();
2169
Jamie Madill893ab082014-05-16 16:56:10 -04002170 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2171 {
2172 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2173
Jamie Madill0af26e12015-03-05 19:54:33 -05002174 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002176 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002177 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002178 }
2179 }
2180
2181 switch (pname)
2182 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002183 case GL_TEXTURE_BINDING_2D:
2184 case GL_TEXTURE_BINDING_CUBE_MAP:
2185 case GL_TEXTURE_BINDING_3D:
2186 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002187 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002188 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002189 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2190 if (!context->getExtensions().textureRectangle)
2191 {
2192 context->handleError(InvalidEnum()
2193 << "ANGLE_texture_rectangle extension not present");
2194 return false;
2195 }
2196 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002197 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2198 if (!context->getExtensions().eglStreamConsumerExternal &&
2199 !context->getExtensions().eglImageExternal)
2200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002201 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2202 "nor GL_OES_EGL_image_external "
2203 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002204 return false;
2205 }
2206 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002207
He Yunchaoced53ae2016-11-29 15:00:51 +08002208 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2209 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002210 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002211 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2212 ASSERT(readFramebuffer);
2213
Jamie Madill427064d2018-04-13 16:20:34 -04002214 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002215 {
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002217 }
2218
Jamie Madille98b1b52018-03-08 09:47:23 -05002219 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002222 return false;
2223 }
2224
Jamie Madille98b1b52018-03-08 09:47:23 -05002225 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002226 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002228 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002229 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002230 }
2231 }
2232 break;
2233
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 default:
2235 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002236 }
2237
2238 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002239 if (*numParams == 0)
2240 {
2241 return false;
2242 }
2243
2244 return true;
2245}
2246
Brandon Jonesd1049182018-03-28 10:02:20 -07002247bool ValidateGetBooleanvRobustANGLE(Context *context,
2248 GLenum pname,
2249 GLsizei bufSize,
2250 GLsizei *length,
2251 GLboolean *params)
2252{
2253 GLenum nativeType;
2254 unsigned int numParams = 0;
2255
2256 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2257 {
2258 return false;
2259 }
2260
2261 SetRobustLengthParam(length, numParams);
2262
2263 return true;
2264}
2265
2266bool ValidateGetFloatvRobustANGLE(Context *context,
2267 GLenum pname,
2268 GLsizei bufSize,
2269 GLsizei *length,
2270 GLfloat *params)
2271{
2272 GLenum nativeType;
2273 unsigned int numParams = 0;
2274
2275 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2276 {
2277 return false;
2278 }
2279
2280 SetRobustLengthParam(length, numParams);
2281
2282 return true;
2283}
2284
2285bool ValidateGetIntegervRobustANGLE(Context *context,
2286 GLenum pname,
2287 GLsizei bufSize,
2288 GLsizei *length,
2289 GLint *data)
2290{
2291 GLenum nativeType;
2292 unsigned int numParams = 0;
2293
2294 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2295 {
2296 return false;
2297 }
2298
2299 SetRobustLengthParam(length, numParams);
2300
2301 return true;
2302}
2303
2304bool ValidateGetInteger64vRobustANGLE(Context *context,
2305 GLenum pname,
2306 GLsizei bufSize,
2307 GLsizei *length,
2308 GLint64 *data)
2309{
2310 GLenum nativeType;
2311 unsigned int numParams = 0;
2312
2313 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2314 {
2315 return false;
2316 }
2317
2318 if (nativeType == GL_INT_64_ANGLEX)
2319 {
2320 CastStateValues(context, nativeType, pname, numParams, data);
2321 return false;
2322 }
2323
2324 SetRobustLengthParam(length, numParams);
2325 return true;
2326}
2327
Jamie Madill5b772312018-03-08 20:28:32 -05002328bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002329 GLenum pname,
2330 GLsizei bufSize,
2331 GLenum *nativeType,
2332 unsigned int *numParams)
2333{
2334 if (!ValidateRobustEntryPoint(context, bufSize))
2335 {
2336 return false;
2337 }
2338
2339 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2340 {
2341 return false;
2342 }
2343
2344 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002345 {
2346 return false;
2347 }
2348
2349 return true;
2350}
2351
Jamie Madill5b772312018-03-08 20:28:32 -05002352bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002353 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002354 GLint level,
2355 GLenum internalformat,
2356 bool isSubImage,
2357 GLint xoffset,
2358 GLint yoffset,
2359 GLint zoffset,
2360 GLint x,
2361 GLint y,
2362 GLsizei width,
2363 GLsizei height,
2364 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002365 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002366{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002367 TextureType texType = TextureTargetToType(target);
2368
Brandon Jones6cad5662017-06-14 13:25:13 -07002369 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002371 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2372 return false;
2373 }
2374
2375 if (width < 0 || height < 0)
2376 {
2377 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002378 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002379 }
2380
He Yunchaoced53ae2016-11-29 15:00:51 +08002381 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2382 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002384 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002385 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002386 }
2387
2388 if (border != 0)
2389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002390 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 }
2393
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002394 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002396 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002397 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 }
2399
Jamie Madill43da7c42018-08-01 11:34:49 -04002400 const State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002401 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002402 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 {
Geoff Langb1196682014-07-23 13:47:29 -04002404 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 }
2406
Jamie Madille98b1b52018-03-08 09:47:23 -05002407 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 {
Geoff Langb1196682014-07-23 13:47:29 -04002409 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 }
2411
Martin Radev138064f2016-07-15 12:03:41 +03002412 if (readFramebuffer->getReadBufferState() == GL_NONE)
2413 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002415 return false;
2416 }
2417
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002418 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2419 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002420 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002421 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002422 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2423 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002426 return false;
2427 }
2428
Martin Radev04e2c3b2017-07-27 16:54:35 +03002429 // ANGLE_multiview spec, Revision 1:
2430 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2431 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002432 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2433 // framebuffer is more than one.
2434 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002435 {
2436 context->handleError(InvalidFramebufferOperation()
2437 << "The active read framebuffer object has multiview attachments.");
2438 return false;
2439 }
2440
Jamie Madill43da7c42018-08-01 11:34:49 -04002441 const Caps &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002442
Geoff Langaae65a42014-05-26 12:43:44 -04002443 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002444 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002446 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002447 maxDimension = caps.max2DTextureSize;
2448 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002449
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002450 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002451 maxDimension = caps.maxCubeMapTextureSize;
2452 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002453
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002454 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002455 maxDimension = caps.maxRectangleTextureSize;
2456 break;
2457
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002458 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002459 maxDimension = caps.max2DTextureSize;
2460 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002461
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002462 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002463 maxDimension = caps.max3DTextureSize;
2464 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002465
He Yunchaoced53ae2016-11-29 15:00:51 +08002466 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002467 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002468 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002469 }
2470
Jamie Madill43da7c42018-08-01 11:34:49 -04002471 Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002472 if (!texture)
2473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002475 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002476 }
2477
Geoff Lang69cce582015-09-17 13:20:36 -04002478 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002480 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002481 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002482 }
2483
Jamie Madill43da7c42018-08-01 11:34:49 -04002484 const InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002485 isSubImage ? *texture->getFormat(target, level).info
Jamie Madill43da7c42018-08-01 11:34:49 -04002486 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002487
Geoff Lang966c9402017-04-18 12:38:27 -04002488 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002490 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002491 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002492 }
2493
2494 if (isSubImage)
2495 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002496 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2497 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2498 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002500 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002501 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 }
2503 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002504 else
2505 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002506 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002507 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002508 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002510 }
2511
Geoff Langeb66a6e2016-10-31 13:06:12 -04002512 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002516 }
2517
2518 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002519 if (static_cast<int>(width) > maxLevelDimension ||
2520 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002524 }
2525 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002526
Jamie Madill0c8abca2016-07-22 20:21:26 -04002527 if (textureFormatOut)
2528 {
2529 *textureFormatOut = texture->getFormat(target, level);
2530 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002531
2532 // Detect texture copying feedback loops for WebGL.
2533 if (context->getExtensions().webglCompatibility)
2534 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002535 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002538 return false;
2539 }
2540 }
2541
Jamie Madill560a8d82014-05-21 13:06:20 -04002542 return true;
2543}
2544
Jamie Madillb42162f2018-08-20 12:58:37 -04002545// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
2546// completeness check.
2547const char *ValidateDrawStates(Context *context)
Jamie Madille7d80f32018-08-08 15:49:23 -04002548{
2549 const Extensions &extensions = context->getExtensions();
2550 const State &state = context->getGLState();
2551
2552 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2553 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2554 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2555 if (!extensions.webglCompatibility && state.getVertexArray()->hasMappedEnabledArrayBuffer())
2556 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002557 return kErrorBufferMapped;
Jamie Madille7d80f32018-08-08 15:49:23 -04002558 }
2559
2560 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2561 // Section 6.10 of the WebGL 1.0 spec.
2562 Framebuffer *framebuffer = state.getDrawFramebuffer();
2563 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
2564 {
2565 ASSERT(framebuffer);
2566 const FramebufferAttachment *dsAttachment =
2567 framebuffer->getStencilOrDepthStencilAttachment();
2568 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2569 ASSERT(stencilBits <= 8);
2570
2571 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2572 if (depthStencilState.stencilTest && stencilBits > 0)
2573 {
2574 GLuint maxStencilValue = (1 << stencilBits) - 1;
2575
2576 bool differentRefs =
2577 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2578 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2579 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2580 (depthStencilState.stencilBackWritemask & maxStencilValue);
2581 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2582 (depthStencilState.stencilBackMask & maxStencilValue);
2583
2584 if (differentRefs || differentWritemasks || differentMasks)
2585 {
2586 if (!extensions.webglCompatibility)
2587 {
2588 WARN() << "This ANGLE implementation does not support separate front/back "
2589 "stencil writemasks, reference values, or stencil mask values.";
2590 }
Jamie Madillb42162f2018-08-20 12:58:37 -04002591 return kErrorStencilReferenceMaskOrMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002592 }
2593 }
2594 }
2595
2596 if (!framebuffer->isComplete(context))
2597 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002598 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
2599 return kErrorDrawFramebufferIncomplete;
Jamie Madille7d80f32018-08-08 15:49:23 -04002600 }
2601
2602 if (context->getStateCache().hasAnyEnabledClientAttrib())
2603 {
2604 if (context->getExtensions().webglCompatibility || !state.areClientArraysEnabled())
2605 {
2606 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
2607 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
2608 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
2609 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
Jamie Madillb42162f2018-08-20 12:58:37 -04002610 return kErrorVertexArrayNoBuffer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002611 }
2612
2613 if (state.getVertexArray()->hasEnabledNullPointerClientArray())
2614 {
2615 // This is an application error that would normally result in a crash, but we catch it
2616 // and return an error
Jamie Madillb42162f2018-08-20 12:58:37 -04002617 return kErrorVertexArrayNoBufferPointer;
Jamie Madille7d80f32018-08-08 15:49:23 -04002618 }
2619 }
2620
2621 // If we are running GLES1, there is no current program.
2622 if (context->getClientVersion() >= Version(2, 0))
2623 {
2624 Program *program = state.getProgram();
2625 if (!program)
2626 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002627 return kErrorProgramNotBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002628 }
2629
2630 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2631 // vertex shader stage or fragment shader stage is a undefined behaviour.
2632 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2633 // produce undefined result.
2634 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2635 !program->hasLinkedShaderStage(ShaderType::Fragment))
2636 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002637 return kErrorNoActiveGraphicsShaderStage;
Jamie Madille7d80f32018-08-08 15:49:23 -04002638 }
2639
2640 if (!program->validateSamplers(nullptr, context->getCaps()))
2641 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002642 return kErrorTextureTypeConflict;
Jamie Madille7d80f32018-08-08 15:49:23 -04002643 }
2644
2645 if (extensions.multiview)
2646 {
2647 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2648 const int framebufferNumViews = framebuffer->getNumViews();
2649 if (framebufferNumViews != programNumViews)
2650 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002651 return kErrorMultiviewMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002652 }
2653
2654 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2655 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2656 framebufferNumViews > 1)
2657 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002658 return kErrorMultiviewTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002659 }
2660
2661 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2662 state.isQueryActive(QueryType::TimeElapsed))
2663 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002664 return kErrorMultiviewTimerQuery;
Jamie Madille7d80f32018-08-08 15:49:23 -04002665 }
2666 }
2667
2668 // Uniform buffer validation
2669 for (unsigned int uniformBlockIndex = 0;
2670 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2671 {
2672 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
2673 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2674 const OffsetBindingPointer<Buffer> &uniformBuffer =
2675 state.getIndexedUniformBuffer(blockBinding);
2676
2677 if (uniformBuffer.get() == nullptr)
2678 {
2679 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002680 return kErrorUniformBufferUnbound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002681 }
2682
2683 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2684 if (uniformBufferSize < uniformBlock.dataSize)
2685 {
2686 // undefined behaviour
Jamie Madillb42162f2018-08-20 12:58:37 -04002687 return kErrorUniformBufferTooSmall;
Jamie Madille7d80f32018-08-08 15:49:23 -04002688 }
2689
2690 if (extensions.webglCompatibility &&
2691 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2692 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002693 return kErrorUniformBufferBoundForTransformFeedback;
Jamie Madille7d80f32018-08-08 15:49:23 -04002694 }
2695 }
2696
2697 // Do some additonal WebGL-specific validation
2698 if (extensions.webglCompatibility)
2699 {
2700 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2701 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2702 transformFeedbackObject->buffersBoundForOtherUse())
2703 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002704 return kErrorTransformFeedbackBufferDoubleBound;
Jamie Madille7d80f32018-08-08 15:49:23 -04002705 }
2706
2707 // Detect rendering feedback loops for WebGL.
2708 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2709 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002710 return kErrorFeedbackLoop;
Jamie Madille7d80f32018-08-08 15:49:23 -04002711 }
2712
2713 // Detect that the vertex shader input types match the attribute types
2714 if (!ValidateVertexShaderAttributeTypeMatch(context))
2715 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002716 return kErrorVertexShaderTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002717 }
2718
2719 // Detect that the color buffer types match the fragment shader output types
2720 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2721 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002722 return kErrorDrawBufferTypeMismatch;
Jamie Madille7d80f32018-08-08 15:49:23 -04002723 }
Jamie Madill03cb5262018-08-08 15:49:24 -04002724
2725 const VertexArray *vao = context->getGLState().getVertexArray();
2726 if (vao->hasTransformFeedbackBindingConflict(context))
2727 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002728 return kErrorVertexBufferBoundForTransformFeedback;
Jamie Madill03cb5262018-08-08 15:49:24 -04002729 }
Jamie Madille7d80f32018-08-08 15:49:23 -04002730 }
2731 }
2732
Jamie Madillb42162f2018-08-20 12:58:37 -04002733 return nullptr;
Jamie Madille7d80f32018-08-08 15:49:23 -04002734}
2735
Jamie Madill493f9572018-05-24 19:52:15 -04002736bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002737{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002738 const Extensions &extensions = context->getExtensions();
2739
Jamie Madill1aeb1312014-06-20 13:21:25 -04002740 switch (mode)
2741 {
Jamie Madill493f9572018-05-24 19:52:15 -04002742 case PrimitiveMode::Points:
2743 case PrimitiveMode::Lines:
2744 case PrimitiveMode::LineLoop:
2745 case PrimitiveMode::LineStrip:
2746 case PrimitiveMode::Triangles:
2747 case PrimitiveMode::TriangleStrip:
2748 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002749 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002750
Jamie Madill493f9572018-05-24 19:52:15 -04002751 case PrimitiveMode::LinesAdjacency:
2752 case PrimitiveMode::LineStripAdjacency:
2753 case PrimitiveMode::TrianglesAdjacency:
2754 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002755 if (!extensions.geometryShader)
2756 {
2757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2758 return false;
2759 }
2760 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002761 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002762 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002763 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002764 }
2765
Jamie Madill250d33f2014-06-06 17:09:03 -04002766 if (count < 0)
2767 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002768 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002770 }
2771
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002772 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002773
Jamie Madillb42162f2018-08-20 12:58:37 -04002774 const char *errorMessage = ValidateDrawStates(context);
2775 if (errorMessage)
Jamie Madill250d33f2014-06-06 17:09:03 -04002776 {
Jamie Madillb42162f2018-08-20 12:58:37 -04002777 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
2778 // Incomplete.
2779 GLenum errorCode =
2780 (errorMessage == kErrorDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
2781 : GL_INVALID_OPERATION);
2782 context->handleError(Error(errorCode, errorMessage));
Jamie Madille7d80f32018-08-08 15:49:23 -04002783 return false;
Jamie Madill2da53562018-08-01 11:34:47 -04002784 }
2785
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002786 // If we are running GLES1, there is no current program.
2787 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002788 {
Jamie Madill43da7c42018-08-01 11:34:49 -04002789 Program *program = state.getProgram();
Jamie Madille7d80f32018-08-08 15:49:23 -04002790 ASSERT(program);
James Darpiniane8a93c62018-01-04 18:02:24 -08002791
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002792 // Do geometry shader specific validations
2793 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002794 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002795 if (!IsCompatibleDrawModeWithGeometryShader(
2796 mode, program->getGeometryShaderInputPrimitiveType()))
2797 {
2798 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2799 IncompatibleDrawModeAgainstGeometryShader);
2800 return false;
2801 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002802 }
2803 }
2804
Jamie Madill9fdaa492018-02-16 10:52:11 -05002805 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002806}
2807
Jamie Madill5b772312018-03-08 20:28:32 -05002808bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002809 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002810 GLint first,
2811 GLsizei count,
2812 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002813{
Jamie Madillfd716582014-06-06 17:09:04 -04002814 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002815 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002816 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002817 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002818 }
2819
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002820 const State &state = context->getGLState();
Jamie Madill43da7c42018-08-01 11:34:49 -04002821 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002822 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002823 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002824 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002825 if (!ValidateTransformFeedbackPrimitiveMode(context,
2826 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002827 {
James Darpinian30b604d2018-03-12 17:26:57 -07002828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2829 return false;
2830 }
2831
2832 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2833 {
2834 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2835 return false;
2836 }
Jamie Madillfd716582014-06-06 17:09:04 -04002837 }
2838
Jiajia Qind9671222016-11-29 16:30:31 +08002839 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002840 {
2841 return false;
2842 }
2843
Corentin Wallez71168a02016-12-19 15:11:18 -08002844 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002845 // - first < 0 has been checked as an error condition.
2846 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002847 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002848 ASSERT(first >= 0);
Jamie Madill2da53562018-08-01 11:34:47 -04002849 if (count > 0 && primcount > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002850 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002851 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2852 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2853 {
2854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2855 return false;
2856 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002857
Jamie Madill2da53562018-08-01 11:34:47 -04002858 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex)))
Jamie Madill9fdaa492018-02-16 10:52:11 -05002859 {
2860 return false;
2861 }
Jamie Madillfd716582014-06-06 17:09:04 -04002862 }
2863
2864 return true;
2865}
2866
He Yunchaoced53ae2016-11-29 15:00:51 +08002867bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002868 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002869 GLint first,
2870 GLsizei count,
2871 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002872{
Geoff Lang63c5a592017-09-27 14:08:16 -04002873 if (!context->getExtensions().instancedArrays)
2874 {
2875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2876 return false;
2877 }
2878
Corentin Wallez170efbf2017-05-02 13:45:01 -04002879 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002880 {
2881 return false;
2882 }
2883
Corentin Wallez0dc97812017-06-22 14:38:44 -04002884 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002885}
2886
Jamie Madill493f9572018-05-24 19:52:15 -04002887bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002888{
Jamie Madill250d33f2014-06-06 17:09:03 -04002889 switch (type)
2890 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002891 case GL_UNSIGNED_BYTE:
2892 case GL_UNSIGNED_SHORT:
2893 break;
2894 case GL_UNSIGNED_INT:
2895 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 return false;
2899 }
2900 break;
2901 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002903 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002904 }
2905
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002906 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002907
Jamie Madill43da7c42018-08-01 11:34:49 -04002908 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002909 if (curTransformFeedback && curTransformFeedback->isActive() &&
2910 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002911 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002912 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2913 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2914 if (context->getExtensions().geometryShader)
2915 {
2916 if (!ValidateTransformFeedbackPrimitiveMode(
2917 context, curTransformFeedback->getPrimitiveMode(), mode))
2918 {
2919 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2920 return false;
2921 }
2922 }
2923 else
2924 {
2925 // It is an invalid operation to call DrawElements, DrawRangeElements or
2926 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
2927 // 86)
2928 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2929 UnsupportedDrawModeForTransformFeedback);
2930 return false;
2931 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002932 }
2933
Jiajia Qind9671222016-11-29 16:30:31 +08002934 return true;
2935}
2936
Jamie Madill5b772312018-03-08 20:28:32 -05002937bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002938 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002939 GLsizei count,
2940 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002941 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002942 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002943{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002944 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08002945 return false;
2946
2947 const State &state = context->getGLState();
2948
Corentin Wallez170efbf2017-05-02 13:45:01 -04002949 if (!ValidateDrawBase(context, mode, count))
2950 {
2951 return false;
2952 }
2953
Jamie Madill43da7c42018-08-01 11:34:49 -04002954 const VertexArray *vao = state.getVertexArray();
2955 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002956
Jamie Madill43da7c42018-08-01 11:34:49 -04002957 GLuint typeBytes = GetTypeInfo(type).bytes;
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002958
2959 if (context->getExtensions().webglCompatibility)
2960 {
2961 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2962 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2963 {
2964 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2965 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2966 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002967 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002968 return false;
2969 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002970
2971 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2972 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2973 // error is generated.
2974 if (reinterpret_cast<intptr_t>(indices) < 0)
2975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002977 return false;
2978 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002979 }
Jamie Madillcc73f242018-08-01 11:34:48 -04002980 else if (elementArrayBuffer && elementArrayBuffer->isMapped())
2981 {
2982 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
2983 // FlushMappedBufferRange, and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2984 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2985 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2986 return false;
2987 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002988
2989 if (context->getExtensions().webglCompatibility ||
2990 !context->getGLState().areClientArraysEnabled())
2991 {
Brandon Jones2a018152018-06-08 15:59:26 -07002992 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002993 {
2994 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07002995 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
2996 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002998 return false;
2999 }
3000 }
3001
Jamie Madill9fdaa492018-02-16 10:52:11 -05003002 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003003 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003004 // This is an application error that would normally result in a crash, but we catch it and
3005 // return an error
3006 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3007 return false;
3008 }
3009
3010 if (count > 0 && elementArrayBuffer)
3011 {
3012 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3013 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3014 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3015 constexpr uint64_t kMaxTypeSize = 8;
3016 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3017 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3018 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3019
3020 uint64_t typeSize = typeBytes;
3021 uint64_t elementCount = static_cast<uint64_t>(count);
3022 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3023
3024 // Doing the multiplication here is overflow-safe
3025 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3026
3027 // The offset can be any value, check for overflows
3028 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3029 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003030 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3032 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003033 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003034
3035 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3036 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003037 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3039 return false;
3040 }
3041
3042 ASSERT(isPow2(typeSize) && typeSize > 0);
3043 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3044 {
3045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003046 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003047 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003048
3049 if (context->getExtensions().webglCompatibility &&
3050 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3051 {
3052 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3053 ElementArrayBufferBoundForTransformFeedback);
3054 return false;
3055 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003056 }
3057
Jamie Madill2da53562018-08-01 11:34:47 -04003058 if (!context->getExtensions().robustBufferAccessBehavior && count > 0 && primcount > 0)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003059 {
3060 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003061 const DrawCallParams &params = context->getParams<DrawCallParams>();
3062 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3063 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003064
3065 // If we use an index greater than our maximum supported index range, return an error.
3066 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3067 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003068 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003069 {
3070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3071 return false;
3072 }
3073
Jamie Madill2da53562018-08-01 11:34:47 -04003074 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end)))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003075 {
3076 return false;
3077 }
3078
3079 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003080 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003081 }
3082
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003084}
3085
Jamie Madill5b772312018-03-08 20:28:32 -05003086bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003087 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003088 GLsizei count,
3089 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003090 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003091 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003092{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003093 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003094}
3095
Geoff Lang3edfe032015-09-04 16:38:24 -04003096bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003097 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003098 GLsizei count,
3099 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003100 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003101 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003102{
Geoff Lang63c5a592017-09-27 14:08:16 -04003103 if (!context->getExtensions().instancedArrays)
3104 {
3105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3106 return false;
3107 }
3108
Corentin Wallez170efbf2017-05-02 13:45:01 -04003109 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003110 {
3111 return false;
3112 }
3113
Corentin Wallez0dc97812017-06-22 14:38:44 -04003114 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003115}
3116
He Yunchaoced53ae2016-11-29 15:00:51 +08003117bool ValidateFramebufferTextureBase(Context *context,
3118 GLenum target,
3119 GLenum attachment,
3120 GLuint texture,
3121 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003122{
Geoff Lange8afa902017-09-27 15:00:43 -04003123 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003127 }
3128
3129 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003130 {
3131 return false;
3132 }
3133
Jamie Madill55ec3b12014-07-03 10:38:57 -04003134 if (texture != 0)
3135 {
Jamie Madill43da7c42018-08-01 11:34:49 -04003136 Texture *tex = context->getTexture(texture);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003137
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003138 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003140 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003141 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003142 }
3143
3144 if (level < 0)
3145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003146 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003147 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003148 }
3149 }
3150
Jamie Madill43da7c42018-08-01 11:34:49 -04003151 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003152 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003153
Jamie Madill84115c92015-04-23 15:00:07 -04003154 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003157 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003158 }
3159
3160 return true;
3161}
3162
Geoff Langb1196682014-07-23 13:47:29 -04003163bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003164{
3165 if (program == 0)
3166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003167 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003168 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003169 }
3170
Jamie Madill43da7c42018-08-01 11:34:49 -04003171 Program *programObject = GetValidProgram(context, program);
Dian Xiang769769a2015-09-09 15:20:08 -07003172 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003173 {
3174 return false;
3175 }
3176
Jamie Madill0063c512014-08-25 15:47:53 -04003177 if (!programObject || !programObject->isLinked())
3178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003181 }
3182
Geoff Lang7dd2e102014-11-10 15:19:26 -05003183 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003185 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003187 }
3188
Jamie Madill0063c512014-08-25 15:47:53 -04003189 return true;
3190}
3191
Geoff Langf41d0ee2016-10-07 13:04:23 -04003192static bool ValidateSizedGetUniform(Context *context,
3193 GLuint program,
3194 GLint location,
3195 GLsizei bufSize,
3196 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003197{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003198 if (length)
3199 {
3200 *length = 0;
3201 }
3202
Jamie Madill78f41802014-08-25 15:47:55 -04003203 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003204 {
Jamie Madill78f41802014-08-25 15:47:55 -04003205 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003206 }
3207
Geoff Langf41d0ee2016-10-07 13:04:23 -04003208 if (bufSize < 0)
3209 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003210 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003211 return false;
3212 }
3213
Jamie Madill43da7c42018-08-01 11:34:49 -04003214 Program *programObject = context->getProgram(program);
Jamie Madilla502c742014-08-28 17:19:13 -04003215 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003216
Jamie Madill78f41802014-08-25 15:47:55 -04003217 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003218 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003219 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003220 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003221 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003223 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003224 }
3225
Geoff Langf41d0ee2016-10-07 13:04:23 -04003226 if (length)
3227 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003228 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003229 }
3230
Jamie Madill0063c512014-08-25 15:47:53 -04003231 return true;
3232}
3233
He Yunchaoced53ae2016-11-29 15:00:51 +08003234bool ValidateGetnUniformfvEXT(Context *context,
3235 GLuint program,
3236 GLint location,
3237 GLsizei bufSize,
3238 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003239{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003240 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003241}
3242
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003243bool ValidateGetnUniformfvRobustANGLE(Context *context,
3244 GLuint program,
3245 GLint location,
3246 GLsizei bufSize,
3247 GLsizei *length,
3248 GLfloat *params)
3249{
3250 UNIMPLEMENTED();
3251 return false;
3252}
3253
He Yunchaoced53ae2016-11-29 15:00:51 +08003254bool ValidateGetnUniformivEXT(Context *context,
3255 GLuint program,
3256 GLint location,
3257 GLsizei bufSize,
3258 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003259{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003260 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3261}
3262
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003263bool ValidateGetnUniformivRobustANGLE(Context *context,
3264 GLuint program,
3265 GLint location,
3266 GLsizei bufSize,
3267 GLsizei *length,
3268 GLint *params)
3269{
3270 UNIMPLEMENTED();
3271 return false;
3272}
3273
3274bool ValidateGetnUniformuivRobustANGLE(Context *context,
3275 GLuint program,
3276 GLint location,
3277 GLsizei bufSize,
3278 GLsizei *length,
3279 GLuint *params)
3280{
3281 UNIMPLEMENTED();
3282 return false;
3283}
3284
Geoff Langf41d0ee2016-10-07 13:04:23 -04003285bool ValidateGetUniformfvRobustANGLE(Context *context,
3286 GLuint program,
3287 GLint location,
3288 GLsizei bufSize,
3289 GLsizei *length,
3290 GLfloat *params)
3291{
3292 if (!ValidateRobustEntryPoint(context, bufSize))
3293 {
3294 return false;
3295 }
3296
Brandon Jonesd1049182018-03-28 10:02:20 -07003297 GLsizei writeLength = 0;
3298
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003300 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3301 {
3302 return false;
3303 }
3304
3305 SetRobustLengthParam(length, writeLength);
3306
3307 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308}
3309
3310bool ValidateGetUniformivRobustANGLE(Context *context,
3311 GLuint program,
3312 GLint location,
3313 GLsizei bufSize,
3314 GLsizei *length,
3315 GLint *params)
3316{
3317 if (!ValidateRobustEntryPoint(context, bufSize))
3318 {
3319 return false;
3320 }
3321
Brandon Jonesd1049182018-03-28 10:02:20 -07003322 GLsizei writeLength = 0;
3323
Geoff Langf41d0ee2016-10-07 13:04:23 -04003324 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003325 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3326 {
3327 return false;
3328 }
3329
3330 SetRobustLengthParam(length, writeLength);
3331
3332 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333}
3334
3335bool ValidateGetUniformuivRobustANGLE(Context *context,
3336 GLuint program,
3337 GLint location,
3338 GLsizei bufSize,
3339 GLsizei *length,
3340 GLuint *params)
3341{
3342 if (!ValidateRobustEntryPoint(context, bufSize))
3343 {
3344 return false;
3345 }
3346
3347 if (context->getClientMajorVersion() < 3)
3348 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003349 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003350 return false;
3351 }
3352
Brandon Jonesd1049182018-03-28 10:02:20 -07003353 GLsizei writeLength = 0;
3354
Geoff Langf41d0ee2016-10-07 13:04:23 -04003355 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003356 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3357 {
3358 return false;
3359 }
3360
3361 SetRobustLengthParam(length, writeLength);
3362
3363 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003364}
3365
He Yunchaoced53ae2016-11-29 15:00:51 +08003366bool ValidateDiscardFramebufferBase(Context *context,
3367 GLenum target,
3368 GLsizei numAttachments,
3369 const GLenum *attachments,
3370 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003371{
3372 if (numAttachments < 0)
3373 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003374 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003375 return false;
3376 }
3377
3378 for (GLsizei i = 0; i < numAttachments; ++i)
3379 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003380 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003381 {
3382 if (defaultFramebuffer)
3383 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003385 return false;
3386 }
3387
3388 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003390 context->handleError(InvalidOperation() << "Requested color attachment is "
3391 "greater than the maximum supported "
3392 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003393 return false;
3394 }
3395 }
3396 else
3397 {
3398 switch (attachments[i])
3399 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003400 case GL_DEPTH_ATTACHMENT:
3401 case GL_STENCIL_ATTACHMENT:
3402 case GL_DEPTH_STENCIL_ATTACHMENT:
3403 if (defaultFramebuffer)
3404 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003405 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3406 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003407 return false;
3408 }
3409 break;
3410 case GL_COLOR:
3411 case GL_DEPTH:
3412 case GL_STENCIL:
3413 if (!defaultFramebuffer)
3414 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003415 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3416 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003417 return false;
3418 }
3419 break;
3420 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003422 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003423 }
3424 }
3425 }
3426
3427 return true;
3428}
3429
Austin Kinross6ee1e782015-05-29 17:05:37 -07003430bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3431{
Jamie Madill007530e2017-12-28 14:27:04 -05003432 if (!context->getExtensions().debugMarker)
3433 {
3434 // The debug marker calls should not set error state
3435 // However, it seems reasonable to set an error state if the extension is not enabled
3436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3437 return false;
3438 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003439
Jamie Madill007530e2017-12-28 14:27:04 -05003440 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003441 if (length < 0)
3442 {
3443 return false;
3444 }
3445
3446 if (marker == nullptr)
3447 {
3448 return false;
3449 }
3450
3451 return true;
3452}
3453
3454bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3455{
Jamie Madill007530e2017-12-28 14:27:04 -05003456 if (!context->getExtensions().debugMarker)
3457 {
3458 // The debug marker calls should not set error state
3459 // However, it seems reasonable to set an error state if the extension is not enabled
3460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3461 return false;
3462 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003463
Jamie Madill007530e2017-12-28 14:27:04 -05003464 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003465 if (length < 0)
3466 {
3467 return false;
3468 }
3469
3470 if (length > 0 && marker == nullptr)
3471 {
3472 return false;
3473 }
3474
3475 return true;
3476}
3477
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003478bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003479{
Geoff Langa8406172015-07-21 16:53:39 -04003480 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003483 return false;
3484 }
3485
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003486 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003487 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003488 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003489 if (!context->getExtensions().eglImage)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidEnum()
3492 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003493 }
3494 break;
3495
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003496 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003497 if (!context->getExtensions().eglImageExternal)
3498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003499 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3500 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003501 }
Geoff Langa8406172015-07-21 16:53:39 -04003502 break;
3503
3504 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003506 return false;
3507 }
3508
Rafael Cintron05a449a2018-06-20 18:08:04 -07003509 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003510
Jamie Madill61e16b42017-06-19 11:13:23 -04003511 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003512 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003515 return false;
3516 }
3517
Jamie Madill007530e2017-12-28 14:27:04 -05003518 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(InvalidOperation()
3521 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003522 return false;
3523 }
3524
Geoff Langca271392017-04-05 12:30:00 -04003525 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003526 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003527 if (!textureCaps.texturable)
3528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003529 context->handleError(InvalidOperation()
3530 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003531 return false;
3532 }
3533
Geoff Langdcab33b2015-07-21 13:03:16 -04003534 return true;
3535}
3536
3537bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003538 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003539 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003540{
Geoff Langa8406172015-07-21 16:53:39 -04003541 if (!context->getExtensions().eglImage)
3542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003544 return false;
3545 }
3546
3547 switch (target)
3548 {
3549 case GL_RENDERBUFFER:
3550 break;
3551
3552 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003553 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003554 return false;
3555 }
3556
Rafael Cintron05a449a2018-06-20 18:08:04 -07003557 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003558
Jamie Madill61e16b42017-06-19 11:13:23 -04003559 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003560 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003562 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003563 return false;
3564 }
3565
Geoff Langca271392017-04-05 12:30:00 -04003566 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003567 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003568 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidOperation()
3571 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003572 return false;
3573 }
3574
Geoff Langdcab33b2015-07-21 13:03:16 -04003575 return true;
3576}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003577
3578bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3579{
Geoff Lang36167ab2015-12-07 10:27:14 -05003580 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003581 {
3582 // The default VAO should always exist
3583 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003585 return false;
3586 }
3587
3588 return true;
3589}
3590
Geoff Langc5629752015-12-07 16:29:04 -05003591bool ValidateProgramBinaryBase(Context *context,
3592 GLuint program,
3593 GLenum binaryFormat,
3594 const void *binary,
3595 GLint length)
3596{
3597 Program *programObject = GetValidProgram(context, program);
3598 if (programObject == nullptr)
3599 {
3600 return false;
3601 }
3602
3603 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3604 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3605 programBinaryFormats.end())
3606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003608 return false;
3609 }
3610
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003611 if (context->hasActiveTransformFeedback(program))
3612 {
3613 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3615 "is associated with an active transform "
3616 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003617 return false;
3618 }
3619
Geoff Langc5629752015-12-07 16:29:04 -05003620 return true;
3621}
3622
3623bool ValidateGetProgramBinaryBase(Context *context,
3624 GLuint program,
3625 GLsizei bufSize,
3626 GLsizei *length,
3627 GLenum *binaryFormat,
3628 void *binary)
3629{
3630 Program *programObject = GetValidProgram(context, program);
3631 if (programObject == nullptr)
3632 {
3633 return false;
3634 }
3635
3636 if (!programObject->isLinked())
3637 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003639 return false;
3640 }
3641
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003642 if (context->getCaps().programBinaryFormats.empty())
3643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003645 return false;
3646 }
3647
Geoff Langc5629752015-12-07 16:29:04 -05003648 return true;
3649}
Jamie Madillc29968b2016-01-20 11:17:23 -05003650
Jamie Madill5b772312018-03-08 20:28:32 -05003651bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003652{
3653 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003654 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3657 return false;
3658 }
3659 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3660 {
3661 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003662 return false;
3663 }
3664
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003665 ASSERT(context->getGLState().getDrawFramebuffer());
3666 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003667 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3668
3669 // This should come first before the check for the default frame buffer
3670 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3671 // rather than INVALID_OPERATION
3672 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3673 {
3674 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3675
3676 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003677 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3678 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003679 {
3680 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003681 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3682 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3683 // 3.1 is still a bit ambiguous about the error, but future specs are
3684 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003686 return false;
3687 }
3688 else if (bufs[colorAttachment] >= maxColorAttachment)
3689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003690 context->handleError(InvalidOperation()
3691 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003692 return false;
3693 }
3694 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3695 frameBufferId != 0)
3696 {
3697 // INVALID_OPERATION-GL is bound to buffer and ith argument
3698 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidOperation()
3700 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003701 return false;
3702 }
3703 }
3704
3705 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3706 // and n is not 1 or bufs is bound to value other than BACK and NONE
3707 if (frameBufferId == 0)
3708 {
3709 if (n != 1)
3710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidOperation()
3712 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003713 return false;
3714 }
3715
3716 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(
3719 InvalidOperation()
3720 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003721 return false;
3722 }
3723 }
3724
3725 return true;
3726}
3727
Geoff Lang496c02d2016-10-20 11:38:11 -07003728bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003729 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003730 GLenum pname,
3731 GLsizei *length,
3732 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003733{
Geoff Lang496c02d2016-10-20 11:38:11 -07003734 if (length)
3735 {
3736 *length = 0;
3737 }
3738
3739 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3740 {
3741 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 InvalidOperation()
3743 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003744 return false;
3745 }
3746
Corentin Walleze4477002017-12-01 14:39:58 -05003747 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003748 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003749 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003750 return false;
3751 }
3752
Geoff Lang496c02d2016-10-20 11:38:11 -07003753 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003754 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003755 case GL_BUFFER_MAP_POINTER:
3756 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003757
Geoff Lang496c02d2016-10-20 11:38:11 -07003758 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003759 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003760 return false;
3761 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003762
3763 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3764 // target bound to zero generate an INVALID_OPERATION error."
3765 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003766 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003768 context->handleError(InvalidOperation()
3769 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003770 return false;
3771 }
3772
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 if (length)
3774 {
3775 *length = 1;
3776 }
3777
Olli Etuaho4f667482016-03-30 15:56:35 +03003778 return true;
3779}
3780
Corentin Wallez336129f2017-10-17 15:55:40 -04003781bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003782{
Corentin Walleze4477002017-12-01 14:39:58 -05003783 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003786 return false;
3787 }
3788
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003789 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003790
3791 if (buffer == nullptr || !buffer->isMapped())
3792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003794 return false;
3795 }
3796
3797 return true;
3798}
3799
3800bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003801 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003802 GLintptr offset,
3803 GLsizeiptr length,
3804 GLbitfield access)
3805{
Corentin Walleze4477002017-12-01 14:39:58 -05003806 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 return false;
3810 }
3811
Brandon Jones6cad5662017-06-14 13:25:13 -07003812 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003814 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3815 return false;
3816 }
3817
3818 if (length < 0)
3819 {
3820 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003821 return false;
3822 }
3823
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003824 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003825
3826 if (!buffer)
3827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003828 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 return false;
3830 }
3831
3832 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003833 CheckedNumeric<size_t> checkedOffset(offset);
3834 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003835
Jamie Madille2e406c2016-06-02 13:04:10 -04003836 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 return false;
3840 }
3841
3842 // Check for invalid bits in the mask
3843 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3844 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3845 GL_MAP_UNSYNCHRONIZED_BIT;
3846
3847 if (access & ~(allAccessBits))
3848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(InvalidValue()
3850 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853
3854 if (length == 0)
3855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003857 return false;
3858 }
3859
3860 if (buffer->isMapped())
3861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return false;
3864 }
3865
3866 // Check for invalid bit combinations
3867 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidOperation()
3870 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
3874 GLbitfield writeOnlyBits =
3875 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3876
3877 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidOperation()
3880 << "Invalid access bits when mapping buffer for reading: 0x"
3881 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
3885 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003887 context->handleError(
3888 InvalidOperation()
3889 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
Geoff Lang79f71042017-08-14 16:43:43 -04003892
3893 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894}
3895
3896bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003897 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 GLintptr offset,
3899 GLsizeiptr length)
3900{
Brandon Jones6cad5662017-06-14 13:25:13 -07003901 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003903 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3904 return false;
3905 }
3906
3907 if (length < 0)
3908 {
3909 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 return false;
3911 }
3912
Corentin Walleze4477002017-12-01 14:39:58 -05003913 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003916 return false;
3917 }
3918
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003919 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920
3921 if (buffer == nullptr)
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
3927 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003929 context->handleError(InvalidOperation()
3930 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 return false;
3932 }
3933
3934 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003935 CheckedNumeric<size_t> checkedOffset(offset);
3936 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003937
Jamie Madille2e406c2016-06-02 13:04:10 -04003938 if (!checkedSize.IsValid() ||
3939 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(InvalidValue()
3942 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 return true;
3947}
3948
Olli Etuaho41997e72016-03-10 13:38:39 +02003949bool ValidateGenOrDelete(Context *context, GLint n)
3950{
3951 if (n < 0)
3952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003953 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003954 return false;
3955 }
3956 return true;
3957}
3958
Jamie Madill5b772312018-03-08 20:28:32 -05003959bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003960{
3961 if (!context->getExtensions().robustClientMemory)
3962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003963 context->handleError(InvalidOperation()
3964 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967
3968 if (bufSize < 0)
3969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return false;
3972 }
3973
3974 return true;
3975}
3976
Jamie Madill5b772312018-03-08 20:28:32 -05003977bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003978{
3979 if (bufSize < numParams)
3980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003981 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3982 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003983 return false;
3984 }
3985
3986 return true;
3987}
3988
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003989bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003990 GLenum target,
3991 GLenum attachment,
3992 GLenum pname,
3993 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003994{
Geoff Lange8afa902017-09-27 15:00:43 -04003995 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003998 return false;
3999 }
4000
4001 int clientVersion = context->getClientMajorVersion();
4002
4003 switch (pname)
4004 {
4005 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4006 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4007 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4008 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4009 break;
4010
Martin Radeve5285d22017-07-14 16:23:53 +03004011 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4012 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4013 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4014 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4015 if (clientVersion < 3 || !context->getExtensions().multiview)
4016 {
4017 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4018 return false;
4019 }
4020 break;
4021
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4023 if (clientVersion < 3 && !context->getExtensions().sRGB)
4024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004025 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 return false;
4027 }
4028 break;
4029
4030 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4031 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4032 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4033 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4034 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4035 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4036 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4038 if (clientVersion < 3)
4039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004040 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 return false;
4042 }
4043 break;
4044
Jiawei Shaoa8802472018-05-28 11:17:47 +08004045 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4046 if (!context->getExtensions().geometryShader)
4047 {
4048 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4049 return false;
4050 }
4051 break;
4052
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004054 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 return false;
4056 }
4057
4058 // Determine if the attachment is a valid enum
4059 switch (attachment)
4060 {
4061 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004062 case GL_DEPTH:
4063 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 if (clientVersion < 3)
4065 {
Geoff Langfa125c92017-10-24 13:01:46 -04004066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 return false;
4068 }
4069 break;
4070
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004071 case GL_DEPTH_STENCIL_ATTACHMENT:
4072 if (clientVersion < 3 && !context->isWebGL1())
4073 {
4074 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4075 return false;
4076 }
4077 break;
4078
Geoff Langfa125c92017-10-24 13:01:46 -04004079 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 case GL_DEPTH_ATTACHMENT:
4081 case GL_STENCIL_ATTACHMENT:
4082 break;
4083
4084 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004085 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4086 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4088 {
Geoff Langfa125c92017-10-24 13:01:46 -04004089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 return false;
4091 }
4092 break;
4093 }
4094
4095 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4096 ASSERT(framebuffer);
4097
4098 if (framebuffer->id() == 0)
4099 {
4100 if (clientVersion < 3)
4101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105
4106 switch (attachment)
4107 {
4108 case GL_BACK:
4109 case GL_DEPTH:
4110 case GL_STENCIL:
4111 break;
4112
4113 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 return false;
4116 }
4117 }
4118 else
4119 {
4120 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4121 {
4122 // Valid attachment query
4123 }
4124 else
4125 {
4126 switch (attachment)
4127 {
4128 case GL_DEPTH_ATTACHMENT:
4129 case GL_STENCIL_ATTACHMENT:
4130 break;
4131
4132 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004133 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004135 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 break;
4139
4140 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 return false;
4143 }
4144 }
4145 }
4146
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004147 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 if (attachmentObject)
4149 {
4150 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4151 attachmentObject->type() == GL_TEXTURE ||
4152 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4153
4154 switch (pname)
4155 {
4156 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4157 if (attachmentObject->type() != GL_RENDERBUFFER &&
4158 attachmentObject->type() != GL_TEXTURE)
4159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004161 return false;
4162 }
4163 break;
4164
4165 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4166 if (attachmentObject->type() != GL_TEXTURE)
4167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 break;
4172
4173 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4174 if (attachmentObject->type() != GL_TEXTURE)
4175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004177 return false;
4178 }
4179 break;
4180
4181 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4182 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4183 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 return false;
4186 }
4187 break;
4188
4189 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4190 if (attachmentObject->type() != GL_TEXTURE)
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 return false;
4194 }
4195 break;
4196
4197 default:
4198 break;
4199 }
4200 }
4201 else
4202 {
4203 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4204 // is NONE, then querying any other pname will generate INVALID_ENUM.
4205
4206 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4207 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4208 // INVALID_OPERATION for all other pnames
4209
4210 switch (pname)
4211 {
4212 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4213 break;
4214
4215 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4216 if (clientVersion < 3)
4217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004218 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004219 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 return false;
4221 }
4222 break;
4223
4224 default:
4225 if (clientVersion < 3)
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004228 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004229 return false;
4230 }
4231 else
4232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004233 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004234 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004235 return false;
4236 }
4237 }
4238 }
4239
Martin Radeve5285d22017-07-14 16:23:53 +03004240 if (numParams)
4241 {
4242 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4243 {
4244 // Only when the viewport offsets are queried we can have a varying number of output
4245 // parameters.
4246 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4247 *numParams = numViews * 2;
4248 }
4249 else
4250 {
4251 // For all other queries we can have only one output parameter.
4252 *numParams = 1;
4253 }
4254 }
4255
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 return true;
4257}
4258
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004259bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004260 GLenum target,
4261 GLenum attachment,
4262 GLenum pname,
4263 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004264 GLsizei *length,
4265 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004266{
4267 if (!ValidateRobustEntryPoint(context, bufSize))
4268 {
4269 return false;
4270 }
4271
Brandon Jonesd1049182018-03-28 10:02:20 -07004272 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004273 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004274 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004275 {
4276 return false;
4277 }
4278
Brandon Jonesd1049182018-03-28 10:02:20 -07004279 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004280 {
4281 return false;
4282 }
4283
Brandon Jonesd1049182018-03-28 10:02:20 -07004284 SetRobustLengthParam(length, numParams);
4285
Geoff Langff5b2d52016-09-07 11:32:23 -04004286 return true;
4287}
4288
Jamie Madill5b772312018-03-08 20:28:32 -05004289bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004290 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004291 GLenum pname,
4292 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004293 GLsizei *length,
4294 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004295{
4296 if (!ValidateRobustEntryPoint(context, bufSize))
4297 {
4298 return false;
4299 }
4300
Brandon Jonesd1049182018-03-28 10:02:20 -07004301 GLsizei numParams = 0;
4302
4303 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004304 {
4305 return false;
4306 }
4307
Brandon Jonesd1049182018-03-28 10:02:20 -07004308 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004309 {
4310 return false;
4311 }
4312
Brandon Jonesd1049182018-03-28 10:02:20 -07004313 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004314 return true;
4315}
4316
Jamie Madill5b772312018-03-08 20:28:32 -05004317bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004318 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004319 GLenum pname,
4320 GLsizei bufSize,
4321 GLsizei *length,
4322 GLint64 *params)
4323{
Brandon Jonesd1049182018-03-28 10:02:20 -07004324 GLsizei numParams = 0;
4325
Geoff Langebebe1c2016-10-14 12:01:31 -04004326 if (!ValidateRobustEntryPoint(context, bufSize))
4327 {
4328 return false;
4329 }
4330
Brandon Jonesd1049182018-03-28 10:02:20 -07004331 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004332 {
4333 return false;
4334 }
4335
Brandon Jonesd1049182018-03-28 10:02:20 -07004336 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004337 {
4338 return false;
4339 }
4340
Brandon Jonesd1049182018-03-28 10:02:20 -07004341 SetRobustLengthParam(length, numParams);
4342
Geoff Langff5b2d52016-09-07 11:32:23 -04004343 return true;
4344}
4345
Jamie Madill5b772312018-03-08 20:28:32 -05004346bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004347{
4348 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004349 if (numParams)
4350 {
4351 *numParams = 1;
4352 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004353
4354 Program *programObject = GetValidProgram(context, program);
4355 if (!programObject)
4356 {
4357 return false;
4358 }
4359
4360 switch (pname)
4361 {
4362 case GL_DELETE_STATUS:
4363 case GL_LINK_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08004364 case GL_COMPLETION_STATUS_KHR:
Geoff Langff5b2d52016-09-07 11:32:23 -04004365 case GL_VALIDATE_STATUS:
4366 case GL_INFO_LOG_LENGTH:
4367 case GL_ATTACHED_SHADERS:
4368 case GL_ACTIVE_ATTRIBUTES:
4369 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4370 case GL_ACTIVE_UNIFORMS:
4371 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4372 break;
4373
4374 case GL_PROGRAM_BINARY_LENGTH:
4375 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004377 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4378 "requires GL_OES_get_program_binary or "
4379 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004380 return false;
4381 }
4382 break;
4383
4384 case GL_ACTIVE_UNIFORM_BLOCKS:
4385 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4386 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4387 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4388 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4389 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4390 if (context->getClientMajorVersion() < 3)
4391 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004393 return false;
4394 }
4395 break;
4396
Yunchao He61afff12017-03-14 15:34:03 +08004397 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004398 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004399 if (context->getClientVersion() < Version(3, 1))
4400 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004402 return false;
4403 }
4404 break;
4405
Jiawei Shao6ae51612018-02-23 14:03:25 +08004406 case GL_COMPUTE_WORK_GROUP_SIZE:
4407 if (context->getClientVersion() < Version(3, 1))
4408 {
4409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4410 return false;
4411 }
4412
4413 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4414 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4415 // program which has not been linked successfully, or which does not contain objects to
4416 // form a compute shader.
4417 if (!programObject->isLinked())
4418 {
4419 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4420 return false;
4421 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004422 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004423 {
4424 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4425 return false;
4426 }
4427 break;
4428
Jiawei Shao447bfac2018-03-14 14:23:40 +08004429 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4430 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4431 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4432 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4433 if (!context->getExtensions().geometryShader)
4434 {
4435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4436 return false;
4437 }
4438
4439 // [EXT_geometry_shader] Chapter 7.12
4440 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4441 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4442 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4443 // successfully, or which does not contain objects to form a geometry shader.
4444 if (!programObject->isLinked())
4445 {
4446 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4447 return false;
4448 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004449 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004450 {
4451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4452 return false;
4453 }
4454 break;
4455
Geoff Langff5b2d52016-09-07 11:32:23 -04004456 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004457 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004458 return false;
4459 }
4460
4461 return true;
4462}
4463
4464bool ValidateGetProgramivRobustANGLE(Context *context,
4465 GLuint program,
4466 GLenum pname,
4467 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004468 GLsizei *length,
4469 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004470{
4471 if (!ValidateRobustEntryPoint(context, bufSize))
4472 {
4473 return false;
4474 }
4475
Brandon Jonesd1049182018-03-28 10:02:20 -07004476 GLsizei numParams = 0;
4477
4478 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004479 {
4480 return false;
4481 }
4482
Brandon Jonesd1049182018-03-28 10:02:20 -07004483 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004484 {
4485 return false;
4486 }
4487
Brandon Jonesd1049182018-03-28 10:02:20 -07004488 SetRobustLengthParam(length, numParams);
4489
Geoff Langff5b2d52016-09-07 11:32:23 -04004490 return true;
4491}
4492
Geoff Lang740d9022016-10-07 11:20:52 -04004493bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4494 GLenum target,
4495 GLenum pname,
4496 GLsizei bufSize,
4497 GLsizei *length,
4498 GLint *params)
4499{
4500 if (!ValidateRobustEntryPoint(context, bufSize))
4501 {
4502 return false;
4503 }
4504
Brandon Jonesd1049182018-03-28 10:02:20 -07004505 GLsizei numParams = 0;
4506
4507 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004508 {
4509 return false;
4510 }
4511
Brandon Jonesd1049182018-03-28 10:02:20 -07004512 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004513 {
4514 return false;
4515 }
4516
Brandon Jonesd1049182018-03-28 10:02:20 -07004517 SetRobustLengthParam(length, numParams);
4518
Geoff Lang740d9022016-10-07 11:20:52 -04004519 return true;
4520}
4521
Geoff Langd7d0ed32016-10-07 11:33:51 -04004522bool ValidateGetShaderivRobustANGLE(Context *context,
4523 GLuint shader,
4524 GLenum pname,
4525 GLsizei bufSize,
4526 GLsizei *length,
4527 GLint *params)
4528{
4529 if (!ValidateRobustEntryPoint(context, bufSize))
4530 {
4531 return false;
4532 }
4533
Brandon Jonesd1049182018-03-28 10:02:20 -07004534 GLsizei numParams = 0;
4535
4536 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004537 {
4538 return false;
4539 }
4540
Brandon Jonesd1049182018-03-28 10:02:20 -07004541 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004542 {
4543 return false;
4544 }
4545
Brandon Jonesd1049182018-03-28 10:02:20 -07004546 SetRobustLengthParam(length, numParams);
4547
Geoff Langd7d0ed32016-10-07 11:33:51 -04004548 return true;
4549}
4550
Geoff Langc1984ed2016-10-07 12:41:00 -04004551bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004552 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004553 GLenum pname,
4554 GLsizei bufSize,
4555 GLsizei *length,
4556 GLfloat *params)
4557{
4558 if (!ValidateRobustEntryPoint(context, bufSize))
4559 {
4560 return false;
4561 }
4562
Brandon Jonesd1049182018-03-28 10:02:20 -07004563 GLsizei numParams = 0;
4564
4565 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004566 {
4567 return false;
4568 }
4569
Brandon Jonesd1049182018-03-28 10:02:20 -07004570 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004571 {
4572 return false;
4573 }
4574
Brandon Jonesd1049182018-03-28 10:02:20 -07004575 SetRobustLengthParam(length, numParams);
4576
Geoff Langc1984ed2016-10-07 12:41:00 -04004577 return true;
4578}
4579
Geoff Langc1984ed2016-10-07 12:41:00 -04004580bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004581 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004582 GLenum pname,
4583 GLsizei bufSize,
4584 GLsizei *length,
4585 GLint *params)
4586{
Brandon Jonesd1049182018-03-28 10:02:20 -07004587
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 if (!ValidateRobustEntryPoint(context, bufSize))
4589 {
4590 return false;
4591 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004592 GLsizei numParams = 0;
4593 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004594 {
4595 return false;
4596 }
4597
Brandon Jonesd1049182018-03-28 10:02:20 -07004598 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004599 {
4600 return false;
4601 }
4602
Brandon Jonesd1049182018-03-28 10:02:20 -07004603 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004604 return true;
4605}
4606
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004607bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4608 TextureType target,
4609 GLenum pname,
4610 GLsizei bufSize,
4611 GLsizei *length,
4612 GLint *params)
4613{
4614 UNIMPLEMENTED();
4615 return false;
4616}
4617
4618bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4619 TextureType target,
4620 GLenum pname,
4621 GLsizei bufSize,
4622 GLsizei *length,
4623 GLuint *params)
4624{
4625 UNIMPLEMENTED();
4626 return false;
4627}
4628
Geoff Langc1984ed2016-10-07 12:41:00 -04004629bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004630 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004631 GLenum pname,
4632 GLsizei bufSize,
4633 const GLfloat *params)
4634{
4635 if (!ValidateRobustEntryPoint(context, bufSize))
4636 {
4637 return false;
4638 }
4639
4640 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4641}
4642
Geoff Langc1984ed2016-10-07 12:41:00 -04004643bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004644 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004645 GLenum pname,
4646 GLsizei bufSize,
4647 const GLint *params)
4648{
4649 if (!ValidateRobustEntryPoint(context, bufSize))
4650 {
4651 return false;
4652 }
4653
4654 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4655}
4656
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004657bool ValidateTexParameterIivRobustANGLE(Context *context,
4658 TextureType target,
4659 GLenum pname,
4660 GLsizei bufSize,
4661 const GLint *params)
4662{
4663 UNIMPLEMENTED();
4664 return false;
4665}
4666
4667bool ValidateTexParameterIuivRobustANGLE(Context *context,
4668 TextureType target,
4669 GLenum pname,
4670 GLsizei bufSize,
4671 const GLuint *params)
4672{
4673 UNIMPLEMENTED();
4674 return false;
4675}
4676
Geoff Langc1984ed2016-10-07 12:41:00 -04004677bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4678 GLuint sampler,
4679 GLenum pname,
4680 GLuint bufSize,
4681 GLsizei *length,
4682 GLfloat *params)
4683{
4684 if (!ValidateRobustEntryPoint(context, bufSize))
4685 {
4686 return false;
4687 }
4688
Brandon Jonesd1049182018-03-28 10:02:20 -07004689 GLsizei numParams = 0;
4690
4691 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004692 {
4693 return false;
4694 }
4695
Brandon Jonesd1049182018-03-28 10:02:20 -07004696 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004697 {
4698 return false;
4699 }
4700
Brandon Jonesd1049182018-03-28 10:02:20 -07004701 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004702 return true;
4703}
4704
Geoff Langc1984ed2016-10-07 12:41:00 -04004705bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4706 GLuint sampler,
4707 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004708 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004709 GLsizei *length,
4710 GLint *params)
4711{
4712 if (!ValidateRobustEntryPoint(context, bufSize))
4713 {
4714 return false;
4715 }
4716
Brandon Jonesd1049182018-03-28 10:02:20 -07004717 GLsizei numParams = 0;
4718
4719 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004720 {
4721 return false;
4722 }
4723
Brandon Jonesd1049182018-03-28 10:02:20 -07004724 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004725 {
4726 return false;
4727 }
4728
Brandon Jonesd1049182018-03-28 10:02:20 -07004729 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004730 return true;
4731}
4732
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004733bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4734 GLuint sampler,
4735 GLenum pname,
4736 GLsizei bufSize,
4737 GLsizei *length,
4738 GLint *params)
4739{
4740 UNIMPLEMENTED();
4741 return false;
4742}
4743
4744bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4745 GLuint sampler,
4746 GLenum pname,
4747 GLsizei bufSize,
4748 GLsizei *length,
4749 GLuint *params)
4750{
4751 UNIMPLEMENTED();
4752 return false;
4753}
4754
Geoff Langc1984ed2016-10-07 12:41:00 -04004755bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4756 GLuint sampler,
4757 GLenum pname,
4758 GLsizei bufSize,
4759 const GLfloat *params)
4760{
4761 if (!ValidateRobustEntryPoint(context, bufSize))
4762 {
4763 return false;
4764 }
4765
4766 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4767}
4768
Geoff Langc1984ed2016-10-07 12:41:00 -04004769bool ValidateSamplerParameterivRobustANGLE(Context *context,
4770 GLuint sampler,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 const GLint *params)
4774{
4775 if (!ValidateRobustEntryPoint(context, bufSize))
4776 {
4777 return false;
4778 }
4779
4780 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4781}
4782
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004783bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4784 GLuint sampler,
4785 GLenum pname,
4786 GLsizei bufSize,
4787 const GLint *param)
4788{
4789 UNIMPLEMENTED();
4790 return false;
4791}
4792
4793bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4794 GLuint sampler,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 const GLuint *param)
4798{
4799 UNIMPLEMENTED();
4800 return false;
4801}
4802
Geoff Lang0b031062016-10-13 14:30:04 -04004803bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4804 GLuint index,
4805 GLenum pname,
4806 GLsizei bufSize,
4807 GLsizei *length,
4808 GLfloat *params)
4809{
4810 if (!ValidateRobustEntryPoint(context, bufSize))
4811 {
4812 return false;
4813 }
4814
Brandon Jonesd1049182018-03-28 10:02:20 -07004815 GLsizei writeLength = 0;
4816
4817 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004818 {
4819 return false;
4820 }
4821
Brandon Jonesd1049182018-03-28 10:02:20 -07004822 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004823 {
4824 return false;
4825 }
4826
Brandon Jonesd1049182018-03-28 10:02:20 -07004827 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004828 return true;
4829}
4830
Geoff Lang0b031062016-10-13 14:30:04 -04004831bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4832 GLuint index,
4833 GLenum pname,
4834 GLsizei bufSize,
4835 GLsizei *length,
4836 GLint *params)
4837{
4838 if (!ValidateRobustEntryPoint(context, bufSize))
4839 {
4840 return false;
4841 }
4842
Brandon Jonesd1049182018-03-28 10:02:20 -07004843 GLsizei writeLength = 0;
4844
4845 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004846 {
4847 return false;
4848 }
4849
Brandon Jonesd1049182018-03-28 10:02:20 -07004850 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004851 {
4852 return false;
4853 }
4854
Brandon Jonesd1049182018-03-28 10:02:20 -07004855 SetRobustLengthParam(length, writeLength);
4856
Geoff Lang0b031062016-10-13 14:30:04 -04004857 return true;
4858}
4859
Geoff Lang0b031062016-10-13 14:30:04 -04004860bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4861 GLuint index,
4862 GLenum pname,
4863 GLsizei bufSize,
4864 GLsizei *length,
4865 void **pointer)
4866{
4867 if (!ValidateRobustEntryPoint(context, bufSize))
4868 {
4869 return false;
4870 }
4871
Brandon Jonesd1049182018-03-28 10:02:20 -07004872 GLsizei writeLength = 0;
4873
4874 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004875 {
4876 return false;
4877 }
4878
Brandon Jonesd1049182018-03-28 10:02:20 -07004879 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004880 {
4881 return false;
4882 }
4883
Brandon Jonesd1049182018-03-28 10:02:20 -07004884 SetRobustLengthParam(length, writeLength);
4885
Geoff Lang0b031062016-10-13 14:30:04 -04004886 return true;
4887}
4888
Geoff Lang0b031062016-10-13 14:30:04 -04004889bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4890 GLuint index,
4891 GLenum pname,
4892 GLsizei bufSize,
4893 GLsizei *length,
4894 GLint *params)
4895{
4896 if (!ValidateRobustEntryPoint(context, bufSize))
4897 {
4898 return false;
4899 }
4900
Brandon Jonesd1049182018-03-28 10:02:20 -07004901 GLsizei writeLength = 0;
4902
4903 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004904 {
4905 return false;
4906 }
4907
Brandon Jonesd1049182018-03-28 10:02:20 -07004908 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004909 {
4910 return false;
4911 }
4912
Brandon Jonesd1049182018-03-28 10:02:20 -07004913 SetRobustLengthParam(length, writeLength);
4914
Geoff Lang0b031062016-10-13 14:30:04 -04004915 return true;
4916}
4917
Geoff Lang0b031062016-10-13 14:30:04 -04004918bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4919 GLuint index,
4920 GLenum pname,
4921 GLsizei bufSize,
4922 GLsizei *length,
4923 GLuint *params)
4924{
4925 if (!ValidateRobustEntryPoint(context, bufSize))
4926 {
4927 return false;
4928 }
4929
Brandon Jonesd1049182018-03-28 10:02:20 -07004930 GLsizei writeLength = 0;
4931
4932 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004933 {
4934 return false;
4935 }
4936
Brandon Jonesd1049182018-03-28 10:02:20 -07004937 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004938 {
4939 return false;
4940 }
4941
Brandon Jonesd1049182018-03-28 10:02:20 -07004942 SetRobustLengthParam(length, writeLength);
4943
Geoff Lang0b031062016-10-13 14:30:04 -04004944 return true;
4945}
4946
Geoff Lang6899b872016-10-14 11:30:13 -04004947bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4948 GLuint program,
4949 GLuint uniformBlockIndex,
4950 GLenum pname,
4951 GLsizei bufSize,
4952 GLsizei *length,
4953 GLint *params)
4954{
4955 if (!ValidateRobustEntryPoint(context, bufSize))
4956 {
4957 return false;
4958 }
4959
Brandon Jonesd1049182018-03-28 10:02:20 -07004960 GLsizei writeLength = 0;
4961
4962 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4963 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004964 {
4965 return false;
4966 }
4967
Brandon Jonesd1049182018-03-28 10:02:20 -07004968 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004969 {
4970 return false;
4971 }
4972
Brandon Jonesd1049182018-03-28 10:02:20 -07004973 SetRobustLengthParam(length, writeLength);
4974
Geoff Lang6899b872016-10-14 11:30:13 -04004975 return true;
4976}
4977
Brandon Jones416aaf92018-04-10 08:10:16 -07004978bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004979 GLenum target,
4980 GLenum internalformat,
4981 GLenum pname,
4982 GLsizei bufSize,
4983 GLsizei *length,
4984 GLint *params)
4985{
4986 if (!ValidateRobustEntryPoint(context, bufSize))
4987 {
4988 return false;
4989 }
4990
Brandon Jonesd1049182018-03-28 10:02:20 -07004991 GLsizei numParams = 0;
4992
4993 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4994 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004995 {
4996 return false;
4997 }
4998
Brandon Jonesd1049182018-03-28 10:02:20 -07004999 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005000 {
5001 return false;
5002 }
5003
Brandon Jonesd1049182018-03-28 10:02:20 -07005004 SetRobustLengthParam(length, numParams);
5005
Geoff Lang0a9661f2016-10-20 10:59:20 -07005006 return true;
5007}
5008
Jamie Madill5b772312018-03-08 20:28:32 -05005009bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005010 GLuint attribIndex,
5011 GLint size,
5012 GLenum type,
5013 GLboolean pureInteger)
5014{
5015 const Caps &caps = context->getCaps();
5016 if (attribIndex >= caps.maxVertexAttributes)
5017 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005018 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005019 return false;
5020 }
5021
5022 if (size < 1 || size > 4)
5023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005024 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005025 return false;
Shao80957d92017-02-20 21:25:59 +08005026 }
5027
5028 switch (type)
5029 {
5030 case GL_BYTE:
5031 case GL_UNSIGNED_BYTE:
5032 case GL_SHORT:
5033 case GL_UNSIGNED_SHORT:
5034 break;
5035
5036 case GL_INT:
5037 case GL_UNSIGNED_INT:
5038 if (context->getClientMajorVersion() < 3)
5039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005040 context->handleError(InvalidEnum()
5041 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005042 return false;
5043 }
5044 break;
5045
5046 case GL_FIXED:
5047 case GL_FLOAT:
5048 if (pureInteger)
5049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005050 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005051 return false;
5052 }
5053 break;
5054
5055 case GL_HALF_FLOAT:
5056 if (context->getClientMajorVersion() < 3)
5057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005058 context->handleError(InvalidEnum()
5059 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005060 return false;
5061 }
5062 if (pureInteger)
5063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005065 return false;
5066 }
5067 break;
5068
5069 case GL_INT_2_10_10_10_REV:
5070 case GL_UNSIGNED_INT_2_10_10_10_REV:
5071 if (context->getClientMajorVersion() < 3)
5072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005073 context->handleError(InvalidEnum()
5074 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005075 return false;
5076 }
5077 if (pureInteger)
5078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005079 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005080 return false;
5081 }
5082 if (size != 4)
5083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005084 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5085 "UNSIGNED_INT_2_10_10_10_REV and "
5086 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005087 return false;
5088 }
5089 break;
5090
5091 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005093 return false;
5094 }
5095
5096 return true;
5097}
5098
Geoff Lang76e65652017-03-27 14:58:02 -04005099// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5100// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5101// specified clear value and the type of a buffer that is being cleared generates an
5102// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005103bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005104 GLint drawbuffer,
5105 const GLenum *validComponentTypes,
5106 size_t validComponentTypeCount)
5107{
5108 const FramebufferAttachment *attachment =
5109 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5110 if (attachment)
5111 {
5112 GLenum componentType = attachment->getFormat().info->componentType;
5113 const GLenum *end = validComponentTypes + validComponentTypeCount;
5114 if (std::find(validComponentTypes, end, componentType) == end)
5115 {
5116 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005117 InvalidOperation()
5118 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005119 return false;
5120 }
5121 }
5122
5123 return true;
5124}
5125
Jamie Madill5b772312018-03-08 20:28:32 -05005126bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005127{
5128 if (!ValidateRobustEntryPoint(context, dataSize))
5129 {
5130 return false;
5131 }
5132
Jamie Madill43da7c42018-08-01 11:34:49 -04005133 Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005134 if (pixelUnpackBuffer == nullptr)
5135 {
5136 if (dataSize < imageSize)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005139 }
5140 }
5141 return true;
5142}
5143
Jamie Madill5b772312018-03-08 20:28:32 -05005144bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005145 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005146 GLenum pname,
5147 bool pointerVersion,
5148 GLsizei *numParams)
5149{
5150 if (numParams)
5151 {
5152 *numParams = 0;
5153 }
5154
Corentin Walleze4477002017-12-01 14:39:58 -05005155 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160
5161 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5162 if (!buffer)
5163 {
5164 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 return false;
5167 }
5168
5169 const Extensions &extensions = context->getExtensions();
5170
5171 switch (pname)
5172 {
5173 case GL_BUFFER_USAGE:
5174 case GL_BUFFER_SIZE:
5175 break;
5176
5177 case GL_BUFFER_ACCESS_OES:
5178 if (!extensions.mapBuffer)
5179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005180 context->handleError(InvalidEnum()
5181 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 return false;
5183 }
5184 break;
5185
5186 case GL_BUFFER_MAPPED:
5187 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5188 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5189 !extensions.mapBufferRange)
5190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005191 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5192 "GL_OES_mapbuffer or "
5193 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 return false;
5195 }
5196 break;
5197
5198 case GL_BUFFER_MAP_POINTER:
5199 if (!pointerVersion)
5200 {
5201 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005202 InvalidEnum()
5203 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206 break;
5207
5208 case GL_BUFFER_ACCESS_FLAGS:
5209 case GL_BUFFER_MAP_OFFSET:
5210 case GL_BUFFER_MAP_LENGTH:
5211 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005213 context->handleError(InvalidEnum()
5214 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217 break;
5218
5219 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005221 return false;
5222 }
5223
5224 // All buffer parameter queries return one value.
5225 if (numParams)
5226 {
5227 *numParams = 1;
5228 }
5229
5230 return true;
5231}
5232
5233bool ValidateGetRenderbufferParameterivBase(Context *context,
5234 GLenum target,
5235 GLenum pname,
5236 GLsizei *length)
5237{
5238 if (length)
5239 {
5240 *length = 0;
5241 }
5242
5243 if (target != GL_RENDERBUFFER)
5244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248
5249 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5250 if (renderbuffer == nullptr)
5251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255
5256 switch (pname)
5257 {
5258 case GL_RENDERBUFFER_WIDTH:
5259 case GL_RENDERBUFFER_HEIGHT:
5260 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5261 case GL_RENDERBUFFER_RED_SIZE:
5262 case GL_RENDERBUFFER_GREEN_SIZE:
5263 case GL_RENDERBUFFER_BLUE_SIZE:
5264 case GL_RENDERBUFFER_ALPHA_SIZE:
5265 case GL_RENDERBUFFER_DEPTH_SIZE:
5266 case GL_RENDERBUFFER_STENCIL_SIZE:
5267 break;
5268
5269 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5270 if (!context->getExtensions().framebufferMultisample)
5271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275 break;
5276
5277 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 return false;
5280 }
5281
5282 if (length)
5283 {
5284 *length = 1;
5285 }
5286 return true;
5287}
5288
5289bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5290{
5291 if (length)
5292 {
5293 *length = 0;
5294 }
5295
5296 if (GetValidShader(context, shader) == nullptr)
5297 {
5298 return false;
5299 }
5300
5301 switch (pname)
5302 {
5303 case GL_SHADER_TYPE:
5304 case GL_DELETE_STATUS:
5305 case GL_COMPILE_STATUS:
jchen107ae70d82018-07-06 13:47:01 +08005306 case GL_COMPLETION_STATUS_KHR:
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 case GL_INFO_LOG_LENGTH:
5308 case GL_SHADER_SOURCE_LENGTH:
5309 break;
5310
5311 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5312 if (!context->getExtensions().translatedShaderSource)
5313 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 return false;
5316 }
5317 break;
5318
5319 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
5323
5324 if (length)
5325 {
5326 *length = 1;
5327 }
5328 return true;
5329}
5330
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005331bool ValidateGetTexParameterBase(Context *context,
5332 TextureType target,
5333 GLenum pname,
5334 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005335{
5336 if (length)
5337 {
5338 *length = 0;
5339 }
5340
5341 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5342 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005344 return false;
5345 }
5346
5347 if (context->getTargetTexture(target) == nullptr)
5348 {
5349 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005354 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5355 {
5356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5357 return false;
5358 }
5359
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 switch (pname)
5361 {
5362 case GL_TEXTURE_MAG_FILTER:
5363 case GL_TEXTURE_MIN_FILTER:
5364 case GL_TEXTURE_WRAP_S:
5365 case GL_TEXTURE_WRAP_T:
5366 break;
5367
5368 case GL_TEXTURE_USAGE_ANGLE:
5369 if (!context->getExtensions().textureUsage)
5370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 break;
5375
5376 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005377 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381 break;
5382
5383 case GL_TEXTURE_IMMUTABLE_FORMAT:
5384 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5385 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 case GL_TEXTURE_WRAP_R:
5392 case GL_TEXTURE_IMMUTABLE_LEVELS:
5393 case GL_TEXTURE_SWIZZLE_R:
5394 case GL_TEXTURE_SWIZZLE_G:
5395 case GL_TEXTURE_SWIZZLE_B:
5396 case GL_TEXTURE_SWIZZLE_A:
5397 case GL_TEXTURE_BASE_LEVEL:
5398 case GL_TEXTURE_MAX_LEVEL:
5399 case GL_TEXTURE_MIN_LOD:
5400 case GL_TEXTURE_MAX_LOD:
5401 case GL_TEXTURE_COMPARE_MODE:
5402 case GL_TEXTURE_COMPARE_FUNC:
5403 if (context->getClientMajorVersion() < 3)
5404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005405 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408 break;
5409
5410 case GL_TEXTURE_SRGB_DECODE_EXT:
5411 if (!context->getExtensions().textureSRGBDecode)
5412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005413 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416 break;
5417
Yunchao Hebacaa712018-01-30 14:01:39 +08005418 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5419 if (context->getClientVersion() < Version(3, 1))
5420 {
5421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5422 return false;
5423 }
5424 break;
5425
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005426 case GL_GENERATE_MIPMAP:
5427 case GL_TEXTURE_CROP_RECT_OES:
5428 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5429 // after GL_OES_draw_texture functionality implemented
5430 if (context->getClientMajorVersion() > 1)
5431 {
5432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5433 return false;
5434 }
5435 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 return false;
5439 }
5440
5441 if (length)
5442 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005443 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 }
5445 return true;
5446}
5447
5448bool ValidateGetVertexAttribBase(Context *context,
5449 GLuint index,
5450 GLenum pname,
5451 GLsizei *length,
5452 bool pointer,
5453 bool pureIntegerEntryPoint)
5454{
5455 if (length)
5456 {
5457 *length = 0;
5458 }
5459
5460 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 return false;
5464 }
5465
5466 if (index >= context->getCaps().maxVertexAttributes)
5467 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005468 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005469 return false;
5470 }
5471
5472 if (pointer)
5473 {
5474 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5475 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 return false;
5478 }
5479 }
5480 else
5481 {
5482 switch (pname)
5483 {
5484 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5485 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5486 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5487 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5488 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5489 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5490 case GL_CURRENT_VERTEX_ATTRIB:
5491 break;
5492
5493 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5494 static_assert(
5495 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5496 "ANGLE extension enums not equal to GL enums.");
5497 if (context->getClientMajorVersion() < 3 &&
5498 !context->getExtensions().instancedArrays)
5499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005500 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5501 "requires OpenGL ES 3.0 or "
5502 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505 break;
5506
5507 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5508 if (context->getClientMajorVersion() < 3)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(
5511 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 return false;
5513 }
5514 break;
5515
5516 case GL_VERTEX_ATTRIB_BINDING:
5517 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5518 if (context->getClientVersion() < ES_3_1)
5519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005520 context->handleError(InvalidEnum()
5521 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 return false;
5523 }
5524 break;
5525
5526 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005527 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005528 return false;
5529 }
5530 }
5531
5532 if (length)
5533 {
5534 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5535 {
5536 *length = 4;
5537 }
5538 else
5539 {
5540 *length = 1;
5541 }
5542 }
5543
5544 return true;
5545}
5546
Jamie Madill4928b7c2017-06-20 12:57:39 -04005547bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005548 GLint x,
5549 GLint y,
5550 GLsizei width,
5551 GLsizei height,
5552 GLenum format,
5553 GLenum type,
5554 GLsizei bufSize,
5555 GLsizei *length,
5556 GLsizei *columns,
5557 GLsizei *rows,
5558 void *pixels)
5559{
5560 if (length != nullptr)
5561 {
5562 *length = 0;
5563 }
5564 if (rows != nullptr)
5565 {
5566 *rows = 0;
5567 }
5568 if (columns != nullptr)
5569 {
5570 *columns = 0;
5571 }
5572
5573 if (width < 0 || height < 0)
5574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005575 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005576 return false;
5577 }
5578
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005579 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005580
Jamie Madill427064d2018-04-13 16:20:34 -04005581 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005582 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585
Jamie Madille98b1b52018-03-08 09:47:23 -05005586 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005587 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 return false;
5589 }
5590
Jamie Madill690c8eb2018-03-12 15:20:03 -04005591 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 ASSERT(framebuffer);
5593
5594 if (framebuffer->getReadBufferState() == GL_NONE)
5595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 return false;
5598 }
5599
5600 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5601 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5602 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5603 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5604 // situation is an application error that would lead to a crash in ANGLE.
5605 if (readBuffer == nullptr)
5606 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 return false;
5609 }
5610
Martin Radev28031682017-07-28 14:47:56 +03005611 // ANGLE_multiview, Revision 1:
5612 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005613 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5614 // in the current read framebuffer is more than one.
5615 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005616 {
5617 context->handleError(InvalidFramebufferOperation()
5618 << "Attempting to read from a multi-view framebuffer.");
5619 return false;
5620 }
5621
Geoff Lang280ba992017-04-18 16:30:58 -04005622 if (context->getExtensions().webglCompatibility)
5623 {
5624 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5625 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5626 // and type before validating the combination of format and type. However, the
5627 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5628 // verifies that GL_INVALID_OPERATION is generated.
5629 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5630 // dEQP/WebGL.
5631 if (!ValidReadPixelsFormatEnum(context, format))
5632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005634 return false;
5635 }
5636
5637 if (!ValidReadPixelsTypeEnum(context, type))
5638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005640 return false;
5641 }
5642 }
5643
Jamie Madill690c8eb2018-03-12 15:20:03 -04005644 GLenum currentFormat = GL_NONE;
5645 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5646
5647 GLenum currentType = GL_NONE;
5648 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5649
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5651
5652 bool validFormatTypeCombination =
5653 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5654
5655 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5656 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005658 return false;
5659 }
5660
5661 // Check for pixel pack buffer related API errors
Jamie Madill43da7c42018-08-01 11:34:49 -04005662 Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5664 {
5665 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005666 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 return false;
5668 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005669 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5670 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5671 {
5672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5673 return false;
5674 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005675
5676 // .. the data would be packed to the buffer object such that the memory writes required
5677 // would exceed the data store size.
5678 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Jamie Madill43da7c42018-08-01 11:34:49 -04005679 const Extents size(width, height, 1);
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 const auto &pack = context->getGLState().getPackState();
5681
Jamie Madillca2ff382018-07-11 09:01:17 -04005682 GLuint endByte = 0;
5683 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 return false;
5687 }
5688
Jamie Madillbe849e42017-05-02 15:49:00 -04005689 if (bufSize >= 0)
5690 {
5691 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 return false;
5695 }
5696 }
5697
5698 if (pixelPackBuffer != nullptr)
5699 {
5700 CheckedNumeric<size_t> checkedEndByte(endByte);
5701 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5702 checkedEndByte += checkedOffset;
5703
5704 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5705 {
5706 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 return false;
5709 }
5710 }
5711
5712 if (pixelPackBuffer == nullptr && length != nullptr)
5713 {
5714 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5715 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 return false;
5718 }
5719
5720 *length = static_cast<GLsizei>(endByte);
5721 }
5722
Geoff Langa953b522018-02-21 16:56:23 -05005723 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 angle::CheckedNumeric<int> clippedExtent(length);
5725 if (start < 0)
5726 {
5727 // "subtract" the area that is less than 0
5728 clippedExtent += start;
5729 }
5730
Geoff Langa953b522018-02-21 16:56:23 -05005731 angle::CheckedNumeric<int> readExtent = start;
5732 readExtent += length;
5733 if (!readExtent.IsValid())
5734 {
5735 return false;
5736 }
5737
5738 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005739 {
5740 // Subtract the region to the right of the read buffer
5741 clippedExtent -= (readExtent - bufferSize);
5742 }
5743
5744 if (!clippedExtent.IsValid())
5745 {
Geoff Langa953b522018-02-21 16:56:23 -05005746 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005747 }
5748
Geoff Langa953b522018-02-21 16:56:23 -05005749 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5750 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005751 };
5752
Geoff Langa953b522018-02-21 16:56:23 -05005753 GLsizei writtenColumns = 0;
5754 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5755 {
5756 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5757 return false;
5758 }
5759
5760 GLsizei writtenRows = 0;
5761 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5762 {
5763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5764 return false;
5765 }
5766
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 if (columns != nullptr)
5768 {
Geoff Langa953b522018-02-21 16:56:23 -05005769 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005770 }
5771
5772 if (rows != nullptr)
5773 {
Geoff Langa953b522018-02-21 16:56:23 -05005774 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005775 }
5776
5777 return true;
5778}
5779
5780template <typename ParamType>
5781bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005782 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005783 GLenum pname,
5784 GLsizei bufSize,
5785 const ParamType *params)
5786{
5787 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 return false;
5791 }
5792
5793 if (context->getTargetTexture(target) == nullptr)
5794 {
5795 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 return false;
5798 }
5799
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005800 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 if (bufSize >= 0 && bufSize < minBufSize)
5802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005807 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5808 {
5809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5810 return false;
5811 }
5812
Jamie Madillbe849e42017-05-02 15:49:00 -04005813 switch (pname)
5814 {
5815 case GL_TEXTURE_WRAP_R:
5816 case GL_TEXTURE_SWIZZLE_R:
5817 case GL_TEXTURE_SWIZZLE_G:
5818 case GL_TEXTURE_SWIZZLE_B:
5819 case GL_TEXTURE_SWIZZLE_A:
5820 case GL_TEXTURE_BASE_LEVEL:
5821 case GL_TEXTURE_MAX_LEVEL:
5822 case GL_TEXTURE_COMPARE_MODE:
5823 case GL_TEXTURE_COMPARE_FUNC:
5824 case GL_TEXTURE_MIN_LOD:
5825 case GL_TEXTURE_MAX_LOD:
5826 if (context->getClientMajorVersion() < 3)
5827 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 return false;
5830 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005831 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005833 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5834 "available without "
5835 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005836 return false;
5837 }
5838 break;
5839
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005840 case GL_GENERATE_MIPMAP:
5841 case GL_TEXTURE_CROP_RECT_OES:
5842 if (context->getClientMajorVersion() > 1)
5843 {
5844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5845 return false;
5846 }
5847 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005848 default:
5849 break;
5850 }
5851
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005852 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005853 {
5854 switch (pname)
5855 {
5856 case GL_TEXTURE_MIN_FILTER:
5857 case GL_TEXTURE_MAG_FILTER:
5858 case GL_TEXTURE_WRAP_S:
5859 case GL_TEXTURE_WRAP_T:
5860 case GL_TEXTURE_WRAP_R:
5861 case GL_TEXTURE_MIN_LOD:
5862 case GL_TEXTURE_MAX_LOD:
5863 case GL_TEXTURE_COMPARE_MODE:
5864 case GL_TEXTURE_COMPARE_FUNC:
5865 context->handleError(InvalidEnum()
5866 << "Invalid parameter for 2D multisampled textures.");
5867 return false;
5868 }
5869 }
5870
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 switch (pname)
5872 {
5873 case GL_TEXTURE_WRAP_S:
5874 case GL_TEXTURE_WRAP_T:
5875 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005876 {
5877 bool restrictedWrapModes =
5878 target == TextureType::External || target == TextureType::Rectangle;
5879 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005880 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005881 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005882 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005883 }
5884 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005885
5886 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005887 {
5888 bool restrictedMinFilter =
5889 target == TextureType::External || target == TextureType::Rectangle;
5890 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005891 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005892 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005893 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005894 }
5895 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005896
5897 case GL_TEXTURE_MAG_FILTER:
5898 if (!ValidateTextureMagFilterValue(context, params))
5899 {
5900 return false;
5901 }
5902 break;
5903
5904 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005905 if (!context->getExtensions().textureUsage)
5906 {
5907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5908 return false;
5909 }
5910
Jamie Madillbe849e42017-05-02 15:49:00 -04005911 switch (ConvertToGLenum(params[0]))
5912 {
5913 case GL_NONE:
5914 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5915 break;
5916
5917 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005919 return false;
5920 }
5921 break;
5922
5923 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005924 {
5925 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5926 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005927 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005928 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005930 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5931 }
5932 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005933
5934 case GL_TEXTURE_MIN_LOD:
5935 case GL_TEXTURE_MAX_LOD:
5936 // any value is permissible
5937 break;
5938
5939 case GL_TEXTURE_COMPARE_MODE:
5940 if (!ValidateTextureCompareModeValue(context, params))
5941 {
5942 return false;
5943 }
5944 break;
5945
5946 case GL_TEXTURE_COMPARE_FUNC:
5947 if (!ValidateTextureCompareFuncValue(context, params))
5948 {
5949 return false;
5950 }
5951 break;
5952
5953 case GL_TEXTURE_SWIZZLE_R:
5954 case GL_TEXTURE_SWIZZLE_G:
5955 case GL_TEXTURE_SWIZZLE_B:
5956 case GL_TEXTURE_SWIZZLE_A:
5957 switch (ConvertToGLenum(params[0]))
5958 {
5959 case GL_RED:
5960 case GL_GREEN:
5961 case GL_BLUE:
5962 case GL_ALPHA:
5963 case GL_ZERO:
5964 case GL_ONE:
5965 break;
5966
5967 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 return false;
5970 }
5971 break;
5972
5973 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005974 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005976 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005977 return false;
5978 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005979 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005981 context->handleError(InvalidOperation()
5982 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 return false;
5984 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005985 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005986 {
5987 context->handleError(InvalidOperation()
5988 << "Base level must be 0 for multisampled textures.");
5989 return false;
5990 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005991 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005992 {
5993 context->handleError(InvalidOperation()
5994 << "Base level must be 0 for rectangle textures.");
5995 return false;
5996 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005997 break;
5998
5999 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006000 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006002 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006003 return false;
6004 }
6005 break;
6006
6007 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6008 if (context->getClientVersion() < Version(3, 1))
6009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006010 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006011 return false;
6012 }
6013 switch (ConvertToGLenum(params[0]))
6014 {
6015 case GL_DEPTH_COMPONENT:
6016 case GL_STENCIL_INDEX:
6017 break;
6018
6019 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006021 return false;
6022 }
6023 break;
6024
6025 case GL_TEXTURE_SRGB_DECODE_EXT:
6026 if (!ValidateTextureSRGBDecodeValue(context, params))
6027 {
6028 return false;
6029 }
6030 break;
6031
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006032 case GL_GENERATE_MIPMAP:
6033 case GL_TEXTURE_CROP_RECT_OES:
6034 if (context->getClientMajorVersion() > 1)
6035 {
6036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6037 return false;
6038 }
6039 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006040 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006041 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006042 return false;
6043 }
6044
6045 return true;
6046}
6047
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006048template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6049template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006050
Jamie Madill5b772312018-03-08 20:28:32 -05006051bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006052{
6053 if (index >= MAX_VERTEX_ATTRIBS)
6054 {
6055 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6056 return false;
6057 }
6058
6059 return true;
6060}
6061
6062bool ValidateGetActiveUniformBlockivBase(Context *context,
6063 GLuint program,
6064 GLuint uniformBlockIndex,
6065 GLenum pname,
6066 GLsizei *length)
6067{
6068 if (length)
6069 {
6070 *length = 0;
6071 }
6072
6073 if (context->getClientMajorVersion() < 3)
6074 {
6075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6076 return false;
6077 }
6078
6079 Program *programObject = GetValidProgram(context, program);
6080 if (!programObject)
6081 {
6082 return false;
6083 }
6084
6085 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6086 {
6087 context->handleError(InvalidValue()
6088 << "uniformBlockIndex exceeds active uniform block count.");
6089 return false;
6090 }
6091
6092 switch (pname)
6093 {
6094 case GL_UNIFORM_BLOCK_BINDING:
6095 case GL_UNIFORM_BLOCK_DATA_SIZE:
6096 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6097 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6098 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6099 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6100 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6101 break;
6102
6103 default:
6104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6105 return false;
6106 }
6107
6108 if (length)
6109 {
6110 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6111 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006112 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006113 programObject->getUniformBlockByIndex(uniformBlockIndex);
6114 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6115 }
6116 else
6117 {
6118 *length = 1;
6119 }
6120 }
6121
6122 return true;
6123}
6124
Jamie Madill9696d072017-08-26 23:19:57 -04006125template <typename ParamType>
6126bool ValidateSamplerParameterBase(Context *context,
6127 GLuint sampler,
6128 GLenum pname,
6129 GLsizei bufSize,
6130 ParamType *params)
6131{
6132 if (context->getClientMajorVersion() < 3)
6133 {
6134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6135 return false;
6136 }
6137
6138 if (!context->isSampler(sampler))
6139 {
6140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6141 return false;
6142 }
6143
6144 const GLsizei minBufSize = 1;
6145 if (bufSize >= 0 && bufSize < minBufSize)
6146 {
6147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6148 return false;
6149 }
6150
6151 switch (pname)
6152 {
6153 case GL_TEXTURE_WRAP_S:
6154 case GL_TEXTURE_WRAP_T:
6155 case GL_TEXTURE_WRAP_R:
6156 if (!ValidateTextureWrapModeValue(context, params, false))
6157 {
6158 return false;
6159 }
6160 break;
6161
6162 case GL_TEXTURE_MIN_FILTER:
6163 if (!ValidateTextureMinFilterValue(context, params, false))
6164 {
6165 return false;
6166 }
6167 break;
6168
6169 case GL_TEXTURE_MAG_FILTER:
6170 if (!ValidateTextureMagFilterValue(context, params))
6171 {
6172 return false;
6173 }
6174 break;
6175
6176 case GL_TEXTURE_MIN_LOD:
6177 case GL_TEXTURE_MAX_LOD:
6178 // any value is permissible
6179 break;
6180
6181 case GL_TEXTURE_COMPARE_MODE:
6182 if (!ValidateTextureCompareModeValue(context, params))
6183 {
6184 return false;
6185 }
6186 break;
6187
6188 case GL_TEXTURE_COMPARE_FUNC:
6189 if (!ValidateTextureCompareFuncValue(context, params))
6190 {
6191 return false;
6192 }
6193 break;
6194
6195 case GL_TEXTURE_SRGB_DECODE_EXT:
6196 if (!ValidateTextureSRGBDecodeValue(context, params))
6197 {
6198 return false;
6199 }
6200 break;
6201
Luc Ferron1b1a8642018-01-23 15:12:01 -05006202 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6203 {
6204 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6205 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6206 {
6207 return false;
6208 }
6209 }
6210 break;
6211
Jamie Madill9696d072017-08-26 23:19:57 -04006212 default:
6213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6214 return false;
6215 }
6216
6217 return true;
6218}
6219
6220template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6221template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6222
6223bool ValidateGetSamplerParameterBase(Context *context,
6224 GLuint sampler,
6225 GLenum pname,
6226 GLsizei *length)
6227{
6228 if (length)
6229 {
6230 *length = 0;
6231 }
6232
6233 if (context->getClientMajorVersion() < 3)
6234 {
6235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6236 return false;
6237 }
6238
6239 if (!context->isSampler(sampler))
6240 {
6241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6242 return false;
6243 }
6244
6245 switch (pname)
6246 {
6247 case GL_TEXTURE_WRAP_S:
6248 case GL_TEXTURE_WRAP_T:
6249 case GL_TEXTURE_WRAP_R:
6250 case GL_TEXTURE_MIN_FILTER:
6251 case GL_TEXTURE_MAG_FILTER:
6252 case GL_TEXTURE_MIN_LOD:
6253 case GL_TEXTURE_MAX_LOD:
6254 case GL_TEXTURE_COMPARE_MODE:
6255 case GL_TEXTURE_COMPARE_FUNC:
6256 break;
6257
Luc Ferron1b1a8642018-01-23 15:12:01 -05006258 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6259 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6260 {
6261 return false;
6262 }
6263 break;
6264
Jamie Madill9696d072017-08-26 23:19:57 -04006265 case GL_TEXTURE_SRGB_DECODE_EXT:
6266 if (!context->getExtensions().textureSRGBDecode)
6267 {
6268 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6269 return false;
6270 }
6271 break;
6272
6273 default:
6274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6275 return false;
6276 }
6277
6278 if (length)
6279 {
6280 *length = 1;
6281 }
6282 return true;
6283}
6284
6285bool ValidateGetInternalFormativBase(Context *context,
6286 GLenum target,
6287 GLenum internalformat,
6288 GLenum pname,
6289 GLsizei bufSize,
6290 GLsizei *numParams)
6291{
6292 if (numParams)
6293 {
6294 *numParams = 0;
6295 }
6296
6297 if (context->getClientMajorVersion() < 3)
6298 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006300 return false;
6301 }
6302
6303 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006304 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006305 {
6306 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6307 return false;
6308 }
6309
6310 switch (target)
6311 {
6312 case GL_RENDERBUFFER:
6313 break;
6314
6315 case GL_TEXTURE_2D_MULTISAMPLE:
6316 if (context->getClientVersion() < ES_3_1)
6317 {
6318 context->handleError(InvalidOperation()
6319 << "Texture target requires at least OpenGL ES 3.1.");
6320 return false;
6321 }
6322 break;
6323
6324 default:
6325 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6326 return false;
6327 }
6328
6329 if (bufSize < 0)
6330 {
6331 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6332 return false;
6333 }
6334
6335 GLsizei maxWriteParams = 0;
6336 switch (pname)
6337 {
6338 case GL_NUM_SAMPLE_COUNTS:
6339 maxWriteParams = 1;
6340 break;
6341
6342 case GL_SAMPLES:
6343 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6344 break;
6345
6346 default:
6347 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6348 return false;
6349 }
6350
6351 if (numParams)
6352 {
6353 // glGetInternalFormativ will not overflow bufSize
6354 *numParams = std::min(bufSize, maxWriteParams);
6355 }
6356
6357 return true;
6358}
6359
Jamie Madille98b1b52018-03-08 09:47:23 -05006360bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6361{
Jamie Madill427064d2018-04-13 16:20:34 -04006362 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006363 {
Olli Etuahof0e3c192018-08-15 13:37:21 +03006364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidMultisampledFramebufferOperation);
Jamie Madille98b1b52018-03-08 09:47:23 -05006365 return false;
6366 }
6367 return true;
6368}
6369
Lingfeng Yang038dd532018-03-29 17:31:52 -07006370bool ValidateMultitextureUnit(Context *context, GLenum texture)
6371{
6372 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6373 {
6374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6375 return false;
6376 }
6377 return true;
6378}
6379
Jamie Madillc29968b2016-01-20 11:17:23 -05006380} // namespace gl